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

Posted

技术标签:

【中文标题】将 Laravel Blade 模板与 Vue JS 和事件监听器一起使用【英文标题】:Using Laravel Blade templates with Vue JS and event listeners 【发布时间】:2021-07-22 22:38:51 【问题描述】:

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

components/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 是不是最好的方法。

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

【问题讨论】:

所以在第二部分中,您将安装它并直接访问实际上是组件一部分的输入字段,这就是它起作用的原因。那么,您是否试图将注意力集中在页面呈现本身上? @Adi,它按预期工作,但是,我只是质疑这是否是最佳实践。对我来说,这感觉像是一种解决方法。通常我会通过&lt;a @click="doSomething()"&gt; 绑定一个点击监听器,如果有一个类似的方法来绑定到一个插槽中包含的元素会很好。 如果您不希望函数在初始渲染时运行,请优先使用&lt;a @click="doSomething"&gt; 【参考方案1】:

不确定到底是什么问题,也许

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

以某种方式异步(生命周期方面),您可能需要将其包装成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 节点,因此将其作为原生焦点可能是解决方案。

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

【讨论】:

感谢您的回复。我猜大家的共识是,以这种方式添加事件监听器是可以的。我的示例中的代码按预期工作。我只是质疑添加事件监听器的风格。我确信这一定是想要在 Vue 模板中使用样式化 Blade 组件并将事件绑定到它们时遇到的常见问题 如上所述,对我来说看起来不错。 :D 不确定我是否在正确的轨道上,但您不能使用属性包将您的事件处理程序@click 传递给刀片组件吗? @futureweb 我想这是正确的,但我不知道组件是否有正确的上下文来触发正确的方法。【参考方案2】:

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

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>

【讨论】:

以上是关于将 Laravel Blade 模板与 Vue JS 和事件监听器一起使用的主要内容,如果未能解决你的问题,请参考以下文章

使用 Blade/Mustache 模板混合 Laravel 和 Vue.Js

Laravel 中的 Blade 模板与普通 php

带有 Vue js 组件和 Googlebot 的 Laravel Blade 模板

Blade 中的 VueJS 模板未更新

如何将数组从 Laravel Blade 传递到 Laravel 6/Vue 2.6 中的 Vue 组件。*

将 Laravel 路由中的数组传递给 Blade 模板