避免直接改变道具,因为该值将被覆盖

Dmi*_*kov 16 javascript vue.js

升级到Vue 2.0时我遇到了很常见的问题

我收到警告:

避免直接改变道具,因为只要父组件重新渲染,该值就会被覆盖.而是根据prop的值使用数据或计算属性.Prop变异:"username"(在组件中找到)

我多次阅读文档,但我仍然无法理解如何修复它.

usernamepassword在主Vue应用程序中声明.

这是我的代码:

var GuestMenu = Vue.extend({
   props : ['username', 'password'],
      template: `
        <div id="auth">
            <form class="form-inline pull-right">
                <div class="form-group">
                    <label class="sr-only" for="UserName">User name</label>
                  <input type="username" v-model="username" class="form-control" id="UserName" placeholder="username">
                </div>
                <div class="form-group">
                  <label class="sr-only" for="Password">Password</label>
                  <input type="password" v-model="password" class="form-control" id="Password" placeholder="Password">
                </div>
            </form>
        </div>`,
    });
Run Code Online (Sandbox Code Playgroud)

 

App = new Vue ({ 
   el: '#app',
  data: 
    {
      topMenuView: "guestmenu",
      contentView: "guestcontent",
      username: "",
      password: "",

    }
})
Run Code Online (Sandbox Code Playgroud)

我试过v-bind但它似乎没有用,我无法理解为什么.它应该将值绑定到父级(主Vue应用程序)

Ger*_*ied 16

从Vue 2.3.0开始,您可以使用.sync修饰符:

示例vom https://vuejs.org/v2/guide/components-custom-events.html#sync-Modifier:

<text-document :title.sync="title"></text-document>
Run Code Online (Sandbox Code Playgroud)

在你的控制器......

this.$emit('update:title', newTitle)
Run Code Online (Sandbox Code Playgroud)


And*_*ndy 9

您应该使用getter和setter来创建计算属性,然后使用它$emit来更新属性,例如:

var GuestMenu = Vue.extend({
    props: ['username', 'password'],
    template: `
    <div id="auth">
        <form class="form-inline pull-right">
            <div class="form-group">
                <label class="sr-only" for="UserName">User name</label>
              <input type="username" v-model="usernameInput" class="form-control" id="UserName" placeholder="username">
            </div>
            <div class="form-group">
              <label class="sr-only" for="Password">Password</label>
              <input type="password" v-model="passwordInput" class="form-control" id="Password" placeholder="Password">
            </div>
        </form>
    </div>`,
    computed: {
        usernameInput: {
            get: function(){
                return this.username;
            },
            set: function(newValue){
                this.$emit('update:username', newValue)
            }   
        },
        passwordInput: {
            get: function(){
                return this.password;
            },
            set: function(newValue){
                this.$emit('update:password', newValue)
            }   
        },
    }
});
Run Code Online (Sandbox Code Playgroud)


the*_*ker 7

Vue.js认为这是反模式.例如,声明和设置一些道具,如

this.propsVal = 'new Props Value'
Run Code Online (Sandbox Code Playgroud)

因此,要解决此问题,您必须从道具中获取值到Vue实例的数据或计算属性.喜欢...

props: ['propsVal'],
data: function() {
   return {
       propVal: this.propsVal
   };
},
methods: {
...
}
Run Code Online (Sandbox Code Playgroud)

你可以正常使用你的道具价值.


小智 5

如果你想改变 props - 使用 object.

<component :user="global.user"></component>
Run Code Online (Sandbox Code Playgroud)

成分:

    props: ['user'],
    methods: {
      setUser: function() {
        this.user.username= "User";
        this.user.password= "myPass123";
      }
    }
Run Code Online (Sandbox Code Playgroud)

  • 您不应该使用对象来“绕过”此警告。相反,您根本不应该修改 props,而是将它们分配给本地可变的“数据”属性。如果你需要修改全局数据,你应该考虑 Vuex,但无论你如何处理全局数据,你都不应该编辑 props。 (5认同)

Tia*_*oLr 1

当您使用v-bind两个方向绑定的属性时,这就是您收到警告的原因。

如果您需要从父 Vue 组件传递初始用户名,您可以v-bind与另一个数据属性一起使用,例如,_username并在创建组件时将初始值从属性复制到内部数据:

props : ['username', 'password'],
data () {
  return {
    _username: this.username,
    _password: this.password
  }
}
Run Code Online (Sandbox Code Playgroud)

编辑:您还可以在属性更改时使用 $watch 更新 _username / _password 组件数据。