【问题标题】:Vue 3.0 How to assign a prop to a ref without changing the propVue 3.0 如何在不更改道具的情况下将道具分配给参考
【发布时间】:2020-12-14 05:22:42
【问题描述】:

我正在从父组件发送一个道具:user。现在在子组件中,我想复制它而不改变道具的值。

我试着这样做:

export default defineComponent({
  props: {
    apiUser: {
      required: true,
      type: Object
    }
  },
  setup(props) {
    const user = ref(props.apiUser);

    return { user };
  }
});

但是,如果我更改用户对象的值,它也会更改 apiUser 属性。我想也许使用 Object.assign 会起作用,但是 ref 不再是反应性的了。

在 Vue 2.0 中,我会这样做:

export default {
  props: {
     apiUser: {
       required: true,
       type: Object
     }
  },
  data() {
    return {
      user: {}
    }
  },
  mounted() {
    this.user = this.apiUser;
    // Now I can use this.user without changing this.apiUser's value.
  }
};

感谢@buttons 的评论导致答案。

const user = reactive({ ...props.apiUser });

【问题讨论】:

  • 好吧,它不会是反应式的,但你不能 Object.assign() / JSON.parse(JSON.stringify()) / lodash cloneDeep() 用户,添加数据引用,对此进行更改,然后 $emit 将更改返回给父级,您将在其中通过合并或 $set 反应性地合并更改,然后将其作为道具推回原处?我意识到您正在使用新的组合 API,而且我无论如何都不是 Vue 3 专家,但这至少是我一直这样做的方式,而 Vue 2 用于大型应用程序。
  • @Abarth,真的吗?这似乎是一种低效的方法。我希望有人知道一种更有效的方法。无论如何,谢谢!
  • 如果你想复制道具,你必须使用 Object.assign 或类似的东西。真正的问题是,你到底想做什么?为什么需要道具副本?
  • 我当然很乐意听到更好的方法。我将在下面添加我的方法作为答案,显然忽略它,如果结果不是答案,但至少我觉得我已经解释了自己。
  • 啊,我的错。对于对象值,建议使用reactive。很确定这不会引发类型错误。尝试使用const user = reactive(...props.apiUser);。这里是使用 ref vs reactive 的时间。

标签: javascript vue.js vue-composition-api


【解决方案1】:

正如评论部分所讨论的,在这些情况下我个人喜欢的 Vue 2 方法如下,它在更新模型时基本上会往返。

父 (apiUser) ->
孩子(将 apiUser 克隆到用户,进行更改,发出)->
父级(设置响应式更改)->
Child(自动接收更改,并创建新的克隆)

家长

<template>
   <div class="parent-root"
      <child :apiUser="apiUser" @setUserData="setUserData" />
   </div>
</template>

// ----------------------------------------------------
// (Obviously imports of child component etc.)
export default {
   data() {
      apiUser: {
         id: 'e134',
         age: 27
      }
   },

   methods: {
      setUserData(payload) {
         this.$set(this.apiUser, 'age', payload);
      }
   }
}

儿童

<template>
   <div class="child-root"
      {{ apiUser }}
   </div>
</template>

// ----------------------------------------------------
// (Obviously imports of components etc.)
export default {
   props: {
      apiUser: {
         required: true,
         type: Object
      }
   },

   data() {
      user: null
   },

   watch: {
      apiUser: {
         deep: true,
         handler() {
            // Whatever clone method you want to use
            this.user = cloneDeep(this.apiUser);
         }
      }
   },

   mounted() {
      // Whatever clone method you want to use
      this.user = cloneDeep(this.apiUser);
   },

   methods: {
      // Whatever function catching the changes you want to do
      setUserData(payload) {
         this.$emit('setUserData', this.user);
      }
   }
}

对任何错过的类型表示歉意

【讨论】:

    【解决方案2】:
    props: {
     apiUser: {
       required: true,
       type: Object
     }
    },
    setup(props) {
       const userCopy = toRef(props, 'apiUser')
    }
    

    通过组合 API,我们拥有 toRef API,允许您从任何 source reactive object 创建副本。由于props 对象是reactive,因此您使用toRef(),它不会改变您的道具。

    【讨论】:

    • 我试过const userCopy = ref(props.apiUser);。你知道这种情况下的区别吗?两者都显示了值,但只有 toRef 使其具有反应性。
    猜你喜欢
    • 1970-01-01
    • 2021-03-07
    • 1970-01-01
    • 1970-01-01
    • 2018-02-07
    • 1970-01-01
    • 2019-10-09
    • 2021-04-10
    • 2021-04-01
    相关资源
    最近更新 更多