将Laravel Blade模板与Vue JS和事件侦听器一起使用



我正在使用Laraval自定义组件,例如,我有:

组件/input.blade.php

<input type="text" class="rounded">

注意:这是一个简单的例子,这里的关键部分是我想重用刀片模板生成的HTML。

现在我可以创建一个带有作用域插槽的Vue组件:

js/components/Search.vue

<template>
  <div>
    <slot name="search-input" />
  </div>
</template>
<script>
  export default {
    methods: {
      focus() {
        console.log('focus input');
      }
    }
  }
</script>
// ... and registering the component
// among others 
Vue.component('search', require('js/components/Search'));
new Vue({
  el: '#vue_app'
});

现在很好,我可以使用我的组件如下:

views/somepage.blade.php

<search>
  <template v-slot:search>
    <x-input>
  </template>
</search>

所有的工作都如预期的那样,但是正如你所看到的,我有一个focus方法,我希望在关注刀片输入时触发它。

现在我不能这样做:

js/components/Search.vue

<template>
  <div>
    <slot name="search-input" @focus="focus" />
  </div>
</template>
<script>
  export default {
    methods: {
      focus() {
        console.log('focus input');
      }
    }
  }
</script>

但我可以做到:

js/components/Search.vue

<template>
  <div>
    <div ref="search-container"><slot name="search-input" /></div>
  </div>
</template>
<script>
  export default {
    methods: {
      mounted() {
          this.$refs['search-container'].querySelector('input').addEventListener('focus', this.focus)
      },
      focus() {
        console.log('focus input');
      }
    }
  }
</script>

但我不确定在Vue组件中使用addEventListener是否是最好的方法。

有没有更好的方法来实现我想要做的事情?

不确定确切的问题,可能是

this.$refs['search-container'].querySelector('input').addEventListener('focus', this.focus)

以某种方式async(生命周期方面(,并且您可能需要将其封装到nextTick

this.$nextTick(() => {
  this.$refs['search-container'].querySelector('input').addEventListener('focus', this.focus)
})

顺便说一句,IMO添加监听器的这种方式没有问题。

此外,可以按照此处的建议尝试@focus.native="focus":https://v2.vuejs.org/v2/guide/components-custom-events.html#Binding-组件的本机事件
因为可能是水合作用,元素可能需要一些时间才能作为Vue节点使用,因此将其作为本机焦点可能是解决方案。

不确定这些是否可行,但这是我的两个想法。

我的首选解决方案是利用作用域槽及其槽道具来传递方法。最终解决方案如下:

views/somepage.blade.php

<search>
  <template v-slot:default>
    <x-input @focus="slot.methods.focus">
  </template>
</search>

您可以在上面看到,我正在引用slot-props变量slot来访问我在下面定义的变量。请注意,我传递了一个methods对象。调用对象methods只是我的一个偏好。我决定在必要时添加methodsprops

js/components/Search.vue

<template>
  <div>
    <slot :methods="{ focus }" />
  </div>
</template>
<script>
  export default {
    methods: {
      focus() {
        console.log('focus input');
      }
    }
  }
</script>

最新更新