添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement . We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

父组件传给子组件数组的时候,发现在没有使用.sync的情况下,子组件修改此数组会同步到父组件。
不论是普通数组还是对象数组,子组件内对传递下来的数组的增删改操作都会同步到父组件的数组。
issues基本都是英文的,搜索后也不好确定有没有相关问题,因此这里反馈下。

以下代码可复制到 https://jsfiddle.net/yyx990803/okv0rgrk/ 测试

<div id="app">
    {{ message }}//{{strs | json}}
    <child :strs="strs"></child>
    <child2 :strs="strs"></child2>
</div>

javascript

var c = Vue.extend({
    template: '<div><h1>{{msg}}</h1></div>' + 
              '<div v-for="str of strs">' + 
              '<input v-model="str"/>' + 
              '<button @click="del(str)">del</button>' +
              '</div>',
    props: ['strs'],
  data: function () {
    return {
        msg: 'child'
  methods: {
    del: function (item) {
        this.strs.$remove(item);
});
var c2 = Vue.extend({
    template: '<div><h1>{{msg}}</h1></div>' + 
              '<div v-for="str of strs"><input v-model="str"/></div>',
    props: ['strs'],
  data: function () {
    return {
        msg: 'child2'
});
new Vue({
    el: '#app',
    data: {
        message: 'Hello Vue.js!',
        str: 'string',
        strs: ['a','s','d','f'],
        objs: [
            {name: 'a'},{name: 'b'},{name: 'c'},{name: 'd'}
    components: {
        child: c, child2: c2
  wszgxa, Astlvk, yicloud9, stonegithubs, JasonCI, kenberkeley, wxs77577, yjua, kellynlee, ZhouXiangLW, and 16 more reacted with thumbs up emoji
  ZhouXiangLW, Leecason, Miogaror, Zyingying, yangsirgo, and liunanchenFYJJ reacted with hooray emoji
    All reactions

Note that if the prop being passed down is an Object or an Array, it is passed by reference. Mutating the Object or Array itself inside the child will affect parent state, regardless of the binding type you are using.

官网的解释

请问下,如果传的是对象?又想用单向绑定的话?应该怎么写呢?
我现在的解决办法是在父组件中造一个新对象传入子组件,比如:var a = JSON.parse(JSON.stringify(a)),再把a传下去。
请问这样优雅吗?

@Plasmatium 这个我想过,但是遇到一个还没想懂的问题,就是例如这个props是需要通过ajax请求获取的数据,我尝试过通过global event bus去解决这个事,但是总觉得这样做的话会让代码变得一点都不优雅
而且这种实现方法还遇到另外一个问题,不知道组件内的event listener在beforeCreate函数中绑定是不是合理的做法

Hi,@shuaibird 根据vuex文档,异步任务建议放在actions里面,不知到这么做是否合理:在actions里面异步获取该props,然后commit一个mutation,这个mutation更新了state.asyncProps,然后getters里面返回该props的深拷贝,供给需要的组件使用。这么做看起来比较啰嗦,但似乎比较符合状态驱动的意思

具体如下,在store的actions里面:

actions: {
  async getProps ({commit}) {
    //...
    await asyncProps = request(url)
    commit('updateProps', { asyncProps })
    //...

在store的mutations里面:

mutations: {
  updateProps (state, { asyncProps }) {
    state.props = asyncProps

在store的getters里面:

getters: {
  copiedProps (state) {
    return deepCopy(state.props)

在代码合适的地方dispatch('getProps', {url})

@Plasmatium
今天我想到了一个简单一点的实现方法,就是对store传进component的state进行copy操作到data里边,component的value绑定data相对应的key值,然后watch store传进来的state,变化就对组件内部的data进行copy
另外,之所以会遇到这个问题,是因为我用了一些开源组件。所以个人觉得比较理想的做法是,不对组件的props直接进行修改,例如传进组件的props是array,现在要对这个props进行item删除的操作,我看到的开源组件不少是直接使用splice函数。我自己写的组件则会emit一个新的array,对原array不进行直接的操作
我写的immutableRemove函数

* remove an element of an array without mutate the original array & return a new one * @param {Array} items * @param {Number} index * @return {Array} Return a new array without the removed element const immutableRemove = (items, index) => [...items.slice(0, index), ...items.slice(index + 1, items.length)]

@shuaibird 这样的话,可否把传入目标组件props的array先deep copy一份,给该组件自用

考虑到可能确实需要有双向绑定的功能,那么在父组件中,监听这个array的副本,如果被子组件在内部改了,那么就commit给store

@Plasmatium 请问接收props过来的对象后,已经使用computed将其复制一遍,当改变了该computed变量的值后,发现原来的props对象的值也变了,这可能是什么原因?还麻烦指点一下