在 Vue JS 和事件监听器中使用 Laravel Blade 模板

Using Laravel Blade templates with Vue JS and event listeners

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

components/input.blade.php

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

注意:这是一个简单的例子,这里关键的部分是我想复用blade模板生成的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 方法,我希望在关注 blade 输入时触发该方法。

现在我不能这样做了:

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://vuejs.org/v2/guide/components-custom-events.html#Binding-Native-Events-to-Components
因为可能是水合作用,元素可能需要一些时间才能作为 Vue 节点可用,因此将其固定在本地焦点可能是解决方案。

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

我的首选解决方案是利用 scoped slots 及其插槽道具来传递方法。最终解决方案如下所示:

views/somepage.blade.php

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

你可以在上面看到我正在引用插槽道具变量 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>