最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Call .focus() on a sibling VueJS Component - Stack Overflow

programmeradmin2浏览0评论

I have a select ponent. I have a input ponent. When the select ponent is changed I need to .select() the input ponent. These are two unrelated ponents i.e. siblings to the main Vue instance.

Both of these ponents are posed from templates so using the ref attribute is not an option as per the documentation .html#Child-Component-Refs

How would I go about doing this? I've posed a simple example in codepen -

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

  Vueponent('some-input', {
    template: `#vueTemplate-some-input`
  });

  Vueponent('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'
    });

I have a select ponent. I have a input ponent. When the select ponent is changed I need to .select() the input ponent. These are two unrelated ponents i.e. siblings to the main Vue instance.

Both of these ponents are posed from templates so using the ref attribute is not an option as per the documentation https://v2.vuejs/v2/guide/ponents.html#Child-Component-Refs

How would I go about doing this? I've posed a simple example in 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 Code

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

  Vue.ponent('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'
    });
Share edited Jul 14, 2022 at 1:18 tony19 139k23 gold badges278 silver badges348 bronze badges asked Mar 22, 2018 at 12:36 Andrew BerridgeAndrew Berridge 4936 silver badges16 bronze badges 1
  • Here is one way. codepen.io/Kradek/pen/yKbwVB?editors=1010 – Bert Commented Mar 22, 2018 at 12:40
Add a ment  | 

2 Answers 2

Reset to default 2

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 ponent, so it should e from the parent. The parent can also pass that value to the input, which can watch it for changes and set focus.

That solution might look like this snippet:

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

Vue.ponent("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./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. That might look like this snippet:

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

Vue.ponent("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./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 ponent knows about the other.

You need to emit a custom event from you select-ponent to the parent : VueJS Custom Events

Parent ponent :

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

Select Component :

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

评论列表(0)

  1. 暂无评论