简体   繁体   English

在兄弟 VueJS 组件上调用 .focus()

[英]Call .focus() on a sibling VueJS Component

I have a select component.我有一个选择组件。 I have a input component.我有一个输入组件。 When the select component is changed I need to .select() the input component.当更改选择组件时,我需要.select()输入组件。 These are two unrelated components ie siblings to the main Vue instance.这是两个不相关的组件,即主 Vue 实例的兄弟。

Both of these components are composed from templates so using the ref attribute is not an option as per the documentation https://v2.vuejs.org/v2/guide/components.html#Child-Component-Refs这两个组件都是由模板组成的,因此根据文档https://v2.vuejs.org/v2/guide/components.html#Child-Component-Refs ,使用 ref 属性不是一个选项

How would I go about doing this?我该怎么做呢? I've composed a simple example in codepen - https://codepen.io/anon/pen/MVmLVZ我在 codepen 中编写了一个简单的示例 - https://codepen.io/anon/pen/MVmLVZ

HTML 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 Code 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'
    });

There are several ways you could do this, and the right one depends on what the reasons are for implementing this behavior.有几种方法可以做到这一点,正确的方法取决于实现此行为的原因。 It sounds like the value selected is significant to the app, rather than just being relevant to the select component, so it should come from the parent.听起来选择的值对应用程序很重要,而不仅仅是与选择组件相关,因此它应该来自父级。 The parent can also pass that value to the input, which can watch it for changes and set focus.父母也可以将该值传递给输入,它可以watch它的变化并设置焦点。

That solution might look like this snippet:该解决方案可能类似于以下代码段:

 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>

If, on the other hand, you really want to know that the select changed, and not just that the value changed, you could pass an event bus to the input so that the parent could relay the change to its child.另一方面,如果您真的想知道select发生了变化,而不仅仅是值发生了变化,您可以将事件总线传递给输入,以便父级可以将更改传递给其子级。 That might look like this snippet:这可能看起来像这个片段:

 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>

This keeps things encapsulated: the parent knows only that one child changes and that the other child handles change events.这使事情保持封装:父母只知道一个孩子发生了变化,而另一个孩子处理了变化事件。 Neither component knows about the other.两个组件都不知道另一个组件。

You need to emit a custom event from you select-component to the parent : VueJS Custom Events您需要从选择组件向父组件发出自定义事件: VueJS 自定义事件

Parent component :父组件:

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

Select Component :选择组件:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM