vue.js - 在插槽上执行 js
问题描述
我是网络开发的初学者,我正在尝试帮助朋友重新启动旧游戏。我负责工具提示组件,但我碰壁了......
有很多 Vue 组件,其中很多我想调用一个名为 Tooltip 的子组件,我使用它vue-tippy
来轻松配置。这是组件:
<template>
<tippy class="tippy-tooltip">
<slot name='tooltip-trigger'></slot>
<template #content>
<slot name='tooltip-content'>
</slot>
</template>
</tippy>
</template>
<script>
import { formatText } from "@/utils/formatText";
export default {
name: "Tooltip",
methods:{
formatContent(value) {
if (! value) return '';
return formatText(value.toString());
}
},
}
</script>
在其他组件之一中,我尝试使用工具提示:
<template>
<a class="action-button" href="#">
<Tooltip>
<template #tooltip-trigger>
<span v-if="action.movementPointCost > 0">{{ action.movementPointCost }}<img src="@/assets/images/pm.png" alt="mp"></span>
<span v-else-if="action.actionPointCost > 0">{{ action.actionPointCost }}<img src="@/assets/images/pa.png" alt="ap"></span>
<span v-if="action.canExecute">{{ action.name }}</span>
<span v-else><s>{{ action.name }}</s></span>
<span v-if="action.successRate < 100" class="success-rate"> ({{ action.successRate }}%)</span>
</template>
<template #tooltip-content>
<h1>{{action.name}}</h1>
<p>{{action.description}}</p>
</template>
</Tooltip>
</a>
</template>
<script>
import Tooltip from "@/components/Utils/ToolTip";
export default {
props: {
action: Object
},
components: {Tooltip}
};
</script>
从这里一切都很好,工具提示以正确的内容正确显示。
问题是,文本中的文本{{ named.description }}
需要与formatContent
内容一起格式化。我知道我可以使用道具,组件看起来像这样:
工具提示.vue:
<template>
<tippy class="tippy-tooltip">
<slot name='tooltip-trigger'></slot>
<template #content>
<h1 v-html="formatContent(title)" />
<p v-html="formatContent(content)"/>
</template>
</tippy>
</template>
<script>
import { formatText } from "@/utils/formatText";
export default {
name: "Tooltip",
methods:{
formatContent(value) {
if (! value) return '';
return formatText(value.toString());
}
},
props: {
title: {
type: String,
required: true
},
content: {
type: Array,
required: true
}
}
}
</script>
父.vue:
<template>
<a class="action-button" href="#">
<Tooltip :title="action.name" :content="action.description">
<template v-slot:tooltip-trigger>
<span v-if="action.movementPointCost > 0">{{ action.movementPointCost }}<img src="@/assets/images/pm.png" alt="mp"></span>
<span v-else-if="action.actionPointCost > 0">{{ action.actionPointCost }}<img src="@/assets/images/pa.png" alt="ap"></span>
<span v-if="action.canExecute">{{ action.name }}</span>
<span v-else><s>{{ action.name }}</s></span>
<span v-if="action.successRate < 100" class="success-rate"> ({{ action.successRate }}%)</span>
</template>
</Tooltip>
</a>
</template>
<script>
import Tooltip from "@/components/Utils/ToolTip";
export default {
props: {
action: Object
},
components: {Tooltip}
};
</script>
但我需要在工具提示组件中使用一个插槽,因为我们将有一些带有v-for
.
有没有办法将数据从插槽传递到 JS 函数?
解决方案
如果我对您的理解正确,那么您正在这里寻找作用域插槽。
这些将允许您将信息(包括方法)从子组件(带有<slot>
元素的组件)传递回父组件(填充这些插槽的组件),允许父组件直接在插入的内容中使用选择的信息。
在这种情况下,我们可以让父母访问formatContent()
,这将允许他们传递直接使用它的内容。这让我们可以通过 props 的数据传递来保持 slot 的灵活性。
要将其添加到您的示例中,我们将一些“范围”添加到您的内容槽中Tooltip.vue
。<slot>
这只是意味着我们为您的元素提供一个或多个属性,在这种情况下, formatContent
:
<!-- Tooltip.vue -->
<template>
<tippy class="tippy-tooltip">
<slot name='tooltip-trigger'></slot>
<template #content>
<!-- Attributes we add or bind to this slot (eg. formatContent) -->
<!-- become available to components using the slot -->
<slot name='tooltip-content' :formatContent="formatContent"></slot>
</template>
</tippy>
</template>
<script>
import { formatText } from "@/utils/formatText";
export default {
name: "Tooltip",
methods: {
formatContent(value) {
// Rewrote as a ternary, but keep what you're comfortable with
return !value ? '' : formatText(value.toString());
}
},
}
</script>
现在我们已经为插槽添加了一些范围,用内容填充插槽的父母可以通过调用插槽的“范围”来使用它:
<!-- Parent.vue -->
<template>
<a class="action-button" href="#">
<Tooltip>
. . .
<template #tooltip-content="{ formatContent }">
<!-- Elements in this slot now have access to 'formatContent' -->
<h1>{{ formatContent(action.name) }}</h1>
<p>{{ formatContent(action.description) }}</p>
</template>
</Tooltip>
</a>
</template>
. . .
旁注:我更喜欢对插槽范围使用解构语法,因为我觉得它更清晰,并且您只需公开您实际使用的内容:
<template #tooltip-content="{ formatContent }">
但是,如果您愿意,也可以在此处使用变量名称,这将成为一个对象,其中包含您的所有插槽内容作为属性。例如。:
<template #tooltip-content="slotProps">
<!-- 'formatContent' is now a property of 'slotProps' -->
<h1>{{ slotProps.formatContent(action.name) }}</h1>
<p>{{ slotProps.formatContent(action.description) }}</p>
</template>
如果您仍然需要v-html
渲染,您仍然可以在插槽中执行此操作:
<template #tooltip-content="{ formatContent }">
<h1 v-html="formatContent(title)" />
<p v-html="formatContent(content)"/>
</template>
推荐阅读
- reactjs - react-redux 在react-reducer中刷新网页时刷新商店值?
- javascript - Select 查询是否使用 Firestore 上的所有文档大小?
- autodesk-forge - 使用 Forge API 查看 Revit 绘图视图
- c - 如何在 C 中将 RGB565 转换为 HSL 颜色
- redhat - xdotool 无法在 redhat 上检测到 headless firefox 没有 GUI
- ios - 如何使用 SwiftUI 观察 TextField 值并结合?
- java - 我正在尝试在 java 中合并两个 JsonObjects
- javascript - 刷新页面后的粗体活动菜单
- docker - 配置文件更改为 VerneMQ docker 映像
- spring - 为什么 Querydsl 总是要求连接是事务性的?