gpt4 book ai didi

vuejs2 - Vue.js - 父 <-> 插槽通信

转载 作者:行者123 更新时间:2023-12-01 04:37:38 25 4
gpt4 key购买 nike

我正在编写一小部分 Vue 组件来创建一个库以在 future 的项目中使用,但我对这个主题很困惑;也许我需要一种完全不同的方法,但我不知道......

我从(我认为这就是所谓的)策略模式中获得灵感:您创建一个模板组件,其行为取决于您作为参数传递的嵌套组件。例如,我创建了一个 Preview 组件,它拥有一个更改 bkg 图像的方法,并且我想在该组件中嵌套一个能够调用此方法的叠加层。因为这个覆盖可以是我认为如果它通过一个插槽嵌套会很好的一切:

<template>
<div class="preview" :class="{active: active}">
<div class="content">
<slot name="content"></slot>
</div>
<div class="overlay"><slot></slot></div>
</div>
</template>

(我会通过 img 列表将内容设为 v-for)

和js:
props: {
content: {default: function () { return [] }}
},
data: function () {
return {
preview: null
}
},
methods: {
setPreview: function (e) {
this.preview = e
}
}
}

然后是触发更改 onmouseover 的子组件:
<template>
<div @mouseover="set">
<slot></slot> <!-- some random content -->
</div>
</template>

<script>
export default {
props: ['target']
methods: {
set: function () {
// figure a way to call "parent" setPreview
}
}
}
</script>

然后我会像这样使用这个组件:
<preview>
<template slot="content">... a bounch of v-if bound images</template>
<template>
<change-preview-onover target="first-img">...</change-preview-onover>
<change-preview-onclick target="second-img">...</change-preview-onclick> <!-- different policy -->
</template>
</preview>

我尝试了两种不同的方法:作用域插槽和提供/注入(inject)。
使用作用域插槽,我得到如下内容:
//preview
<template>
<div class="preview" :class="{active: active}">
<div class="content">
<slot name="content"></slot>
</div>
<div class="overlay" :callback="{setPreview}"><slot></slot></div>
</div>
</template>
//js...

//overlay element
<template>
<div @mouseover="set">
<slot></slot> <!-- some random content -->
</div>
</template>
<script>
export default {
props: ['target', 'callback']
methods: {
set: function () {
this.callback.setPreview(this.target)
}
}
}
</script>

//usage
<preview>
<template slot="content">... a bounch of v-if bound images</template>
<template slot-scope={callback}>
<change-preview-onover :callback="callback" target="first-img">...</change-preview-onover>
<change-preview-onclick :callback="callback" target="second-img">...</change-preview-onclick>
</template>
</preview>

我不喜欢这种方式,因为它破坏了封装(用户必须知道回调的存在并将其传递给所有更改预览组件)并且得到了很多冗余代码。我试图在覆盖组件内移动插槽范围,但没有任何运气。
所以我读过有关提供/注入(inject)的信息,基本上现在我喜欢这样:
//preview.js
provide: function () {
return {
setPreview: this.setPreview
}
}

//overlay.js
inject: ['setPreview'],
props: ['target'],
methods: {
set: function () {
this.setPreview(this.target)
}
}

这看起来很酷,但我不明白这是否是提供/注入(inject)的方式,或者是否可以在任何地方使用它(主要是性能方面,我会滥用它)来创建一个父 <->插槽通信,当然,插槽是在语义上与父对象相关联的东西

编辑 1

在 Vue.js 中有一种处理父子通信的标准方法:

parent/child

但这在插槽中不起作用,因为 Vue 如何处理组件的范围。鉴于我的示例 Preview 不是覆盖的父级,因为它没有直接嵌套在组件模板中。相反,如果我写这样的东西:
<template>
<div class="preview" :class="{active: active}">
<content>...<content> <!-- changes here -->
<overlay>...</overlay> <!-- and here -->
</div>
</template>

Overlay 和 Content 可以自由地与 Preview 通信,只需发出事件。
但是通过插槽,就像我之前提出的第一个示例一样,内容和覆盖(和预览)都是通用 App 内容的子级,因此 emit 不会触发到 Preview,而是触发到 App(或任何包含预览组件的东西) ;所以我需要一种新的方式来从插槽到父级进行通信,反之亦然。

关于这个主题的主线程: https://github.com/vuejs/vue/issues/4332
在这里,他们使用作用域插槽(好的,但很糟糕)或 $parent,我不能使用它,因为它需要该插槽是父级的直接子级,这并不总是正确的,也许我想添加一个转换或其他东西,得到这样的东西:
//Modal
<div>
<tr-fade> <!-- tr-fade is a registered comopnent and so it's the $parent of slot -->
<slot></slot>
</tr-fade>
</div>

我的问题是:
provide/inject处理这种情况的好方法?插槽范围是否更适合,即使恕我直言打破封装并且它很冗长?还是有其他方法可以在不放弃插槽提供的定制级别的情况下实现这种“策略模式”?

最佳答案

您可以简单地将 child 的上下文注入(inject)插槽中,然后从该上下文中发出事件:

// the child
<template>
<div>
<slot :context="thisContext"/>
</div>
</template>

<script>
export default
{
computed:
{
thisContext()
{
return this;
}
}
}
</script>

// the parent
<template>
<child @custom_event="handleCustom">
<template slot-scope="ctx">
<button @click="sendClick(ctx)">Click me</button>
</template>
</child>
</template>

<script>
export default
{
methods:
{
sendClick(ctx)
{
ctx.$emit('custom_event', {custom_data: 3});
},
handleCustom(payload)
{
console.log("Custom payload:", payload);
}
}
}
</script>

关于vuejs2 - Vue.js - 父 <-> 插槽通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51427841/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com