我正在使用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
只是我的一个偏好。我决定在必要时添加methods
和props
。
js/components/Search.vue
<template>
<div>
<slot :methods="{ focus }" />
</div>
</template>
<script>
export default {
methods: {
focus() {
console.log('focus input');
}
}
}
</script>