Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
3.9k views
in Technique[技术] by (71.8m points)

对于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>

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

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
数据类型的问题,当前数据类型是数组,子组件监听赋值的时候相当于共享了内存地址,可以试试楼上说的深拷贝,但是如果是基于数组对象等复杂数据机构,需要特殊的深拷贝方法;
// 子组件修改
<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>

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...