对于vuejs中自定义组件v-model的一些疑问

代码比较简单,直接如下

<template>

<div id="app">

<button @click="_add">父组件按钮点击</button>

<ul>

<li v-for="(item,index) in message" :key="index">

{{item.name}}

</li>

</ul>

<hr>

<children v-model="message"></children>

</div>

</template>

<script>

import children from './components/children'

export default {

name: 'app',

components: {

children

},

data(){

return{

message: []

}

},

methods: {

_add(){

this.message.push({

name:'name1'

})

},

},

}

</script>

<template>

<div class="children">

<button @click="_add">子组件按钮点击</button>

<ul>

<li v-for="(item,index) in message" :key="index">

{{item.name}}

</li>

</ul>

</div>

</template>

<script>

export default {

name: "children",

props: {

value: {

type: Array

},

},

data() {

return {

message: []

}

},

watch:{

value(newVal){

this.message = newVal

}

},

methods: {

_add(){

this.message.push({

name:'name2'

})

},

},

};

</script>

点击父按钮会正常传递数据到子组件,如图:
对于vuejs中自定义组件v-model的一些疑问
只点击子组件因为没有 emit 传值显示也是正常,如图:
对于vuejs中自定义组件v-model的一些疑问
但是问题来了,如果先点击一次父按钮,再点击子组件里面的按钮,这时为什么会触发父组件数据更新?如图:
对于vuejs中自定义组件v-model的一些疑问
其中的 name1 是第一次先点击父组件的结果,name2 是第二次点击子组件按钮出现的结果。
在官网的介绍当中,说如果要更新父组件的数据,需要手动 emit 触发更新,目前遇到的这种情况不是很明白为什么会自动触发更新数据。

请前辈们解答下这个疑问~~~

回答

数据类型的问题,当前数据类型是数组,子组件监听赋值的时候相当于共享了内存地址,可以试试楼上说的深拷贝,但是如果是基于数组对象等复杂数据机构,需要特殊的深拷贝方法;

// 子组件修改

<template>

<div class="children">

<button @click="_add">子组件按钮点击</button>

<ul>

<li v-for="(item, index) in message" :key="index">

{{ item.name || item }}

</li>

</ul>

</div>

</template>

<script>

export default {

name: "children",

props: {

value: {

type: Array

}

},

data() {

return {

message: []

};

},

watch: {

value(newVal) {

this.message = newVal;

}

},

methods: {

_add() {

// this.message.push({

// name: "name2"

// });

this.message += "¥子¥";

}

}

};

</script>

// 父组件修改

<template>

<button @click="_add">父组件按钮点击</button>

<ul>

<li v-for="(item, index) in message" :key="index">

{{ item.name || item }}

</li>

</ul>

<hr />

<children v-model="message"></children>

</template>

<script>

export default class App extends Vue {

// private message: { name: string }[] = [];

private message = "";

public _add() {

this.message += "$父$";

// this.message.push({

// name: "name1"

// });

}

}

</script>

如上改用非复杂数据类型不会出现题主说的问题

这是因为子组件的 message 不是由父组件直接传递进来的参数,而是自己声明的属性,只是在 watch.value 函数执行后才由父组件传入的 value改写,在父组件改写message前,二者并不相关。
如果你在子组件的 mounted 函数里写:

console.log(this.message === this.value);

理应为 false
但如果在 watch.value 的末尾写同样的代码,输出理应为 true

如果你给父子组件的初始 message 传不同的值的话,他们在首屏的显示必然是不一样的,这也能证明此时二者还不是同一个东西。

如果想使二者始终一致的话,子组件里的 message应为 prop

 props: {

message: {

type: Array,

default: () => []

},

},

兄弟我试了下,如果 v-model 绑定的不是一个数组,而是一个布尔值,就不会出现你的这种情况,可能是数组比较特殊吧!或者这是个 bug,或者你对数组进行深拷贝试下

<template>

<div class="children">

<button @click="_add">子组件按钮点击</button>

<ul> <li v-for="(item,index) in message" :key="index">

{{item.name}}

</li>

</ul> </div></template>

<script>

export default {

name: "children",

props: {

value: {

type: Array

},

},

data() {

return {

message: []

}

},

watch:{

value(newVal){

this.message = JSON.parse(JSON.stringify(newVal));

}

},

methods: {

_add(){

this.message.push({

name:'name2'

})

},

},

};

</script>

以上是 对于vuejs中自定义组件v-model的一些疑问 的全部内容, 来源链接: utcz.com/a/85493.html

回到顶部