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

时间:2016-11-13 14:02:40

标签: javascript vue.js

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

我收到警告:

  

避免直接改变道具,因为该值将被覆盖   每当父组件重新渲染时。相反,使用数据或   基于prop值的计算属性。支持变异:   “用户名”(在组件中找到)

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

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>`,
    });

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

    }
})

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

9 个答案:

答案 0 :(得分:9)

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

样本https://vuejs.org/v2/guide/components-custom-events.html#sync-Modifier

<text-document :title.sync="title"></text-document>

并在您的控制器中...

this.$emit('update:title', newTitle)

答案 1 :(得分:4)

您应该使用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)
            }   
        },
    }
});

答案 2 :(得分:1)

我不确定您要实现什么目标,但我会从中选择两个。

第一个:摆脱警告的全部。

data () {
  return {
    childVal: this.parentVal
  }
}

第二个:您想在父母与孩子之间进行交流。

如果我做对了,这是子组件中的<input>与父组件进行通信的基本示例。

父HTML:

<p>{{ user }}</p>
<child-component v-model="user">

父母JS:

data () {
  return {
    user: 'John'
  }
}

子HTML:

<input v-bind:value="value" @input="$emit('input', $event.target.value)">

儿童JS:

props: ['value']

工作示例:http://jsfiddle.net/kf3aLr1u/

您还可以在文档https://vuejs.org/v2/guide/components.html中阅读有关此内容的更多信息。

答案 3 :(得分:1)

一个SELECT ActiveSystem.*, temp.MaxReportDate FROM ActiveSystem LEFT JOIN ( SELECT Serial_Number, MAX(ReportDate) AS MaxReportDate FROM LicenseReport GROUP BY Serial_Number ) AS temp ON ActiveSystem.SerialNo = temp.Serial_Number 属性和一个适当的computedget对我有用:

set

上面的代码用于切换对话框。

答案 4 :(得分:0)

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

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

props : ['username', 'password'],
data () {
  return {
    _username: this.username,
    _password: this.password
  }
}

编辑:当属性发生变化时,您还可以使用$ watch更新_username / _password组件数据。

答案 5 :(得分:0)

快速解决方案,如果您的道具是一个物体。

您可以避免在Javascript中使用$emit或通过使用Object.assign()来获取该错误。 这将与v-model属性相同。

示例:

// Update the user
Object.assign(this.userProp, user);

答案 6 :(得分:0)

var GuestMenu = Vue.extend({
   props : {
    uNpW:{type:Object}
   }
      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="uNpW.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="uNpW.password" class="form-control" id="Password" placeholder="Password">
                </div>
            </form>
        </div>`,
    });
App = new Vue ({ 
   el: '#app',
  data: 
    {
      topMenuView: "guestmenu",
      contentView: "guestcontent",
      unAndPw:{username: "",password: ""}

    }
})
in main html
<guest-menu :uNpW=unAndPw> </guest-menu>

您不需要发射或任何其他东西

答案 7 :(得分:0)

您可以使用发射,然后:

<text-document :title.sync="title"></text-document>

更改值是:

this.$emit('update:title', newTitle)

或另一种方式:

this.$emit('update')

您可以使用模板:

<text-document :update="oneFunctionInMethods()"></text-document>

答案 8 :(得分:0)

遵循以下非常简单的说明:

//Parent Component
<InsertForm :formSchema="formSchema" v-on:getFormSchema="setFormSchema"></InsertForm>
<script>
import InsertForm from "./insertForm.vue"; //select file

export default {
components: { InsertForm },

data: () => ({
    formSchema:{
       id:'',
       webUrl:''
    },
}),

methods: {
      setFormSchema(data)
      {
        this.formSchema = data.formSchema;
      }
    }
}
</script>

// From Child Component. That means from insertForm.vue file

<script>

export default {
    props: ["formSchema"],
    data: () => ({

    }),
}
//Where you need
this.$emit("getFormSchema", {'formSchema':{"id":1,"webUrl":"bdprescription.com"}});
</script>