Что касается того, почему вы видите такое поведение, когда вы не можете изменить объект root, но можете изменить свойства под ним, открытая переменная слота является мелким клоном, поэтому ссылка на верхний уровень не совпадает с ссылка на объект в дочернем компоненте. Я добавил console.log и обернул .string
в объект, чтобы показать его. Нажмите child
, а затем modify
кнопки.
Таким образом, похоже, что вы пытаетесь представить состояние дочернего компонента родительскому компоненту, чтобы вы могли обратиться к родительскому компоненту и изменить его состояние. Обычно это не тот способ, которым вы должны использовать Vue. Идея состоит в том, что состояние должно быть перемещено выше в дереве, и детерминированные реквизиты распространяются вниз через ваше дерево компонентов.
Прямая ссылка и изменение состояния дочерних компонентов является антипаттерном. Это должно стимулировать разработку компонентов, которые имеют детерминированное поведение c, и поддерживать разделение компонентов (чтобы они оставались автономными и многоразовыми). Также есть некоторые преимущества в производительности.
Этот парень хорошо это объясняет: { ссылка }
Vue и React основаны на схожих концепциях.
const Child = {
template: `<div>
{{ object }}
<slot name="named" v-bind="object">
</slot>
<button @click="click">child</button>
</div>`,
data() {
return {
object: {
string: {x: "initial"}
}
}
},
methods: {
click() {
window.ChildObjectReference = this.object;
this.object.string.x = "modify in child"
}
}
}
new Vue({
components: {
Child,
},
template: `
<div class="page1">
<Child>
<template v-slot:named="slot">
<button @click="click(slot)">modify top level through slot</button>
</template>
</Child>
</div>`,
methods: {
click(slot) {
console.log( `slot: `,slot, `\nobject = `, window.ChildObjectReference,
`\nslot !== ref as object: `, slot === window.ChildObjectReference,
`\nslot.string === ref object.string: `, slot.string === window.ChildObjectReference.string)
}
}
}).$mount('#app')
<div id="app"></div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.min.js"></script>
Отображение взаимодействия между слотом и родительским компонентом:
const Child = {
template: `<div>
{{ object }}
<slot name="named" v-bind="object">
</slot>
<button @click="click">child</button>
</div>`,
data() {
return {
object: {
string: "initial"
}
}
},
methods: {
click() {
this.object.string = "modify in child"
}
}
}
new Vue({
data: {
topLevelObject: { property: "top level initial" }
},
components: {
Child,
},
template: `
<div class="page1">
<Child>
<template v-slot:named="slot">
<div>this is v-bind:'object' on slot 'named' put into variable slot: {{ slot }}</div>
<button @click="click(slot)">modify top level through slot</button>
</template>
</Child>
Top Level state: {{ topLevelObject }}
</div>`,
methods: {
click(slot) {
this.topLevelObject.property = "slot.string pushed to top level: " + slot.string
}
}
}).$mount('#app')
<div id="app"></div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.min.js"></script>