正确使用Vue $ refs

时间:2018-03-01 00:35:29

标签: javascript vue.js

我尝试在我的vue组件中重新创建this exact内联编辑功能。但是,我可能错了,我看到一些语法已经过时Vue,特别是正在使用的v-el指令。我试图像这样更新语法:

new Vue({
  el: '#app',
  data: {
    numbers: [{
        val: 'one',
        edit: false
      },
      {
        val: 'two',
        edit: false
      },
      {
        val: 'three',
        edit: false
      }
    ]
  },

  methods: {
    toggleEdit: function(ev, number) {
      number.edit = !number.edit

      // Focus input field
      if (number.edit) {
        Vue.nextTick(function() {
          ev.$refs.input.focus(); // error occurs here
        })
      }
    },

    saveEdit: function(ev, number) {
      //save your changes
      this.toggleEdit(ev, number);
    }
  }
})
<div id="app">
  <template v-for="number in numbers">
        <span v-show="!number.edit"
              v-on:click="toggleEdit(this, number)">{{number.val}}</span>

        <input type="text"
               ref="input"
               v-model="number.val"
               v-show="number.edit"
               v-on:blur="saveEdit(ev, number)"> <br>
    </template>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.13/dist/vue.js"></script>

但是我遇到了一系列错误...有关如何正确执行此操作的任何建议?

以下是错误:

  

[Vue警告]:nextTick出错:“TypeError:undefined不是对象   (评估'ev。$ refs.input')“

2 个答案:

答案 0 :(得分:8)

许多事情从Vue.js 1.x变为2.x.我将引导您完成您的片段中所需的更改:

  • v-repeat应为v-for
  • v-el="input"替换为ref="input"
    • 由于您在ref="input"中使用v-for,因此this.$refs.input将是一个元素数组,而不是单个元素。
    • 要访问每个元素,您需要一个索引(对于数组),这就是为什么您应该在index中包含v-for变量:v-for="(number, index) in numbers" < / LI>
    • index而不是ev传递给函数,以便稍后使用<input>
    • 获取vm.$refs.input[index].focus(); s

这就是它。更改后,您将获得:

&#13;
&#13;
new Vue({
  el: '#app',
  data: {
    numbers: [
        {
            val: 'one',
            edit: false
        },
        {   val: 'two',
            edit: false
        },
        {
            val: 'three',
            edit: false
        }
    ]
  },
  methods: {
    toggleEdit: function(index, number){
        number.edit = !number.edit;

        // Focus input field
        var vm = this;
        if (number.edit){
            Vue.nextTick(function() {
                vm.$refs.input[index].focus();
            })   
        }
    },

    saveEdit: function(index, number){
        //save your changes
        this.toggleEdit(index, number);
    }
  }
})
&#13;
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.13/dist/vue.js"></script>
<div id="app">
    <template v-for="(number, index) in numbers">
        <span v-show="!number.edit"
              v-on:click="toggleEdit(index, number)">{{number.val}}</span>

        <input type="text"
               ref="input"
               v-model="number.val"
               v-show="number.edit"
               v-on:blur="saveEdit(index, number)"> <br>
    </template>
</div>
&#13;
&#13;
&#13;

答案 1 :(得分:3)

如果您想要功能而不是代码设计,我建议您重新设计它。我想你想要编辑数据,数据不应该知道它是否被编辑。这是组件的作用。

因此,让我们创建一个允许您v-model数据的组件。组件本身具有跨度和输入。如果您正在编辑,则会显示输入,否则显示跨度。点击开始编辑,模糊停止编辑。编辑开始时,将焦点设置在输入上。

需要value道具。其输入元素会发出input事件以表示更改(每component v-model spec

new Vue({
  el: '#app',
  data: {
    stuff: ['one', 'two', 'three']
  },
  components: {
    inlineEditor: {
      template: '#inline-editor-template',
      props: ['value'],
      data() {
        return {
          editing: false
        }
      },
      methods: {
        startEditing() {
          this.editing = true;
          this.$nextTick(() => this.$refs.input.focus());
        },
        stopEditing() {
          this.editing = false;
        }
      }
    }
  }
});
<script src="//unpkg.com/vue@latest/dist/vue.js"></script>
<div id="app">
  <inline-editor v-for="item, index in stuff" v-model="stuff[index]"></inline-editor>
</div>

<template id="inline-editor-template">
  <div>
    <span @click="startEditing" v-show="!editing">{{value}}</span>
    <input ref="input" :value="value" @input="e => $emit('input', e.target.value)" @blur="stopEditing" v-show="editing">
  </div>
</template>