【问题标题】:Trying to create generic input component尝试创建通用输入组件
【发布时间】:2017-04-08 23:40:26
【问题描述】:

我有很多表单要在我正在开发的 Web 应用程序中创建,为此我正在使用 Vue,因此我一直在尝试创建一个可以在整个过程中使用的通用输入组件。我正在使用 Bootstrap 网格,所以我的想法是我应该能够向组件传递一些要占用的列、一个标签、一个名称和一个用作 v-model 的属性。我想我已经到了那里,但是我遇到了变异道具的问题 - [Vue 警告]:避免直接变异道具,因为每当父组件重新渲染时,该值都会被覆盖。相反,使用基于道具值的数据或计算属性。正在变异的道具:“模型” (在组件中找到)。 这是模板(简化形式):

 <template id="field">
<div v-bind:class="colsClass">

    <div class='form-group form-group-sm'>
        <label v-bind:for="name">{{labelText}}</label>

        <input v-bind:id='name' ref="input" class='form-control' v-bind:name='name' v-model='model'/>

    </div>
</div>

这是(再次简化的)JS:

Vue.component('field', {

    template: '#field',

    props: ['cols','label','group','name','model'],


    computed:{
        colsClass:function(){
            return "col-xs-"+this.cols
        }
        ,
        labelText:function(){
            if(this.label) {
                return this.label
            } else {
                return _.startCase(this.name);
            }
        }

    }


});

这是在另一个“编辑产品”组件中使用的,如下所示:

<field :cols="8" name="name" :model="product.name"></field>

当我编辑字段的值时,这会显示 OK,但会引发错误(或更准确地说是警告)。那我做错了什么?

【问题讨论】:

    标签: vue.js


    【解决方案1】:

    实际上,我所采用的解决方案比上面建议的要简单,实际上非常简单,取自https://forum-archive.vuejs.org/topic/4468/trying-to-understand-v-model-on-custom-components/9

    我不想要 'model' 属性,我有一个 'value' 属性,所以 JS 改成这样:

    Vue.component('field', {
    
    template: '#field',
    
    props: ['cols','label','group','name','value'],
    
    
    computed:{
        colsClass:function(){
            return "col-xs-"+this.cols
        }
        ,
        labelText:function(){
            if(this.label) {
                return this.label
            } else {
                return _.startCase(this.name);
            }
        }
    
    }
    });
    

    模板变成这样:

        <div class='form-group form-group-sm'>
            <label :for="name">{{labelText}}</label>
    
            <input :id='name' :name='name' class='form-control' :value="value" @input="$emit('input', $event.target.value)"/>
    
        </div>
    </div>
    

    我是这样使用它的:

    <field :cols="8" name="name" v-model="product.name"></field>
    

    不同之处在于我实际上并没有尝试传递模型道具,我只是传递一个值,并监听该值的变化。它似乎工作得很好,并且足够干净和简单。我的下一个挑战是将一组任意属性传递给输入,但这是另一个问题的主题。

    【讨论】:

      【解决方案2】:

      正如警告所暗示的,您不应直接编辑您为该值传递的道具。

      而是将其用作原始值,并在其输入上设置一个单独的值 - 您可以将其传递给 v-model。如果您需要父级具有当前值,则还传递一个道具,该道具将允许您更新父级上的参数,即

      输入组件

      # script
      props: [
        'origValue',
        'valueChange',
      ],
      data: {
        inputValue: '',
        ...
      },
      mounted () {
        this.inputValue = this.origValue
      },
      watch: {
        inputValue () {
          this.valueChange(this.inputValue)
        },
        ...
      },
      ...
      
      # template
      <input type="text" v-model="inputValue">
      

      父母

      # script
      data () {
        return {
          fieldValue: 'foo',
          ...
        },
      },
      methods: {
        updateField (value) {
          this.fieldValue = value
        },
        ...
      },
      ... 
      
      # template
      <field :value-change="updateField" :orig-value="fieldValue"></field>
      

      【讨论】:

        猜你喜欢
        • 2019-09-23
        • 2015-06-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-10
        • 2013-07-11
        • 2021-09-05
        • 1970-01-01
        相关资源
        最近更新 更多