【问题标题】:Call .focus() on a sibling VueJS Component在兄弟 VueJS 组件上调用 .focus()
【发布时间】:2018-08-31 21:40:50
【问题描述】:

我有一个选择组件。我有一个输入组件。更改选择组件时,我需要.Select()输入组件。这是两个不相关的组件,即主 Vue 实例的兄弟姐妹。

这两个组件都由模板组成,因此根据文档https://vuejs.org/v2/guide/components.html#Child-Component-Refs,使用 ref 属性不是一个选项

我该怎么做呢?我在 codepen 中编写了一个简单的示例- https://codepen.io/anon/pen/MVmLVZ

HTML

<div id='my-app'>
  <some-select></some-select>
  <some-input></some-input>
</div>
<script type="text/x-template" id="vueTemplate-some-select">
  <select @change="doStuff">
    <option value='1'>Value 1</option>
    <option value='2'>Value 2</option>
  </select>
</script>
<script type="text/x-template" id="vueTemplate-some-input">
  <input ref='text-some-input' type='text' value='Some Value'/>
</script>

Vue 代码

  Vue.component('some-input', {
    template: `#vueTemplate-some-input`
  });

  Vue.component('some-select', {
       methods: {
            doStuff: function() {
              // Do some stuff
              //TODO: Now focus on input text field
              //this.$refs['text-some-input'].focus(); // Cant use refs, refs is empty
            }
        },
        template: `#vueTemplate-some-select`
    });

  var app = new Vue({
        el: '#my-app'
    });

【问题讨论】:

标签: javascript vue.js vue-component


【解决方案1】:

有几种方法可以做到这一点,正确的方法取决于实现此行为的原因。听起来选择的值对应用程序很重要,而不仅仅是与选择组件相关,因此它应该来自父级。父级也可以将该值传递给输入,输入可以watch 进行更改和设置焦点。

该解决方案可能看起来像这样 sn-p:

Vue.component("some-input", {
  template: `#vueTemplate-some-input`,
  props: ['watchValue'],
  watch: {
    watchValue() {
      this.$refs['text-some-input'].focus();
    }
  }
});

Vue.component("some-select", {
  props: ['value'],
  methods: {
    doStuff: function(event) {
      this.$emit('input', event.target.value);
    }
  },
  template: `#vueTemplate-some-select`
});

var app = new Vue({
  el: "#my-app",
  data: {
    selectedValue: null
  }
});
<script src="//unpkg.com/vue@latest/dist/vue.js"></script>
<div id='my-app'>
  <some-select v-model="selectedValue"></some-select>
  <some-input :watch-value="selectedValue"></some-input>
  <div>Selected: {{selectedValue}}</div>
</div>
<script type="text/x-template" id="vueTemplate-some-select">
  <select :value="value" @change="doStuff">
    <option value='1'>Value 1</option>
    <option value='2'>Value 2</option>
  </select>
</script>
<script type="text/x-template" id="vueTemplate-some-input">
  <input ref='text-some-input' type='text' value='Some Value' />
</script>

另一方面,如果您真的想知道 select 发生了变化,而不仅仅是值发生了变化,您可以将事件总线传递给输入,以便父级可以将更改传递给其子级.这可能看起来像这样 sn-p:

Vue.component("some-input", {
  template: `#vueTemplate-some-input`,
  props: ['changeBus'],
  mounted() {
    this.changeBus.$on('change', () => this.$refs['text-some-input'].focus());
  }
});

Vue.component("some-select", {
  methods: {
    doStuff: function(event) {
      this.$emit('change', event.target.value);
    }
  },
  template: `#vueTemplate-some-select`
});

var app = new Vue({
  el: "#my-app",
  data: {
    changeBus: new Vue()
  }
});
<script src="//unpkg.com/vue@latest/dist/vue.js"></script>
<div id='my-app'>
  <some-select @change="changeBus.$emit('change')"></some-select>
  <some-input :change-bus="changeBus"></some-input>
</div>
<script type="text/x-template" id="vueTemplate-some-select">
  <select @change="doStuff">
    <option value='1'>Value 1</option>
    <option value='2'>Value 2</option>
  </select>
</script>
<script type="text/x-template" id="vueTemplate-some-input">
  <input ref='text-some-input' type='text' value='Some Value' />
</script>

这使事情保持封装:父母只知道一个孩子发生了变化,而另一个孩子处理了变化事件。两个组件都不知道另一个组件。

【讨论】:

  • 谢谢,您的第二个选项最适合我。我没有创建事件总线,而是将 $on 和 $emit 处理程序附加到组件已经可用的 this.$root 上。
【解决方案2】:

您需要从您的选择组件向父组件发出自定义事件: VueJS Custom Events

父组件:

<select-component @valueChanged="this.$refs.myInput.focus()"></select-component>
<input type="text" ref="myInput"/>

选择组件:

<select v-model="mySelectValue" @change="$emit('valueChanged', mySelectValue)"></select>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多