Vue 开发人员必须知道的 8 个秘密
- 内联语句处理程序:处理多个参数
- 从功能组件发出事件
- 将所有 props 传递给子组件
- 从父级观察子级属性的变化
- 在路由器视图中监听子事件
- Vue 组件生命周期钩子并不按照你认为的顺序运行
- 如何知道子组件是否已安装
- 如何知道动态注册的vuex模块是否已注册
内联语句处理程序:处理多个参数
简短解释:
在内联语句处理程序中,除了$event
特殊变量之外,我们还可以访问另一个特殊变量:arguments
。$event
只能访问第一个参数,而arguments
可以访问所有参数。
详细说明:
在内联语句处理程序中,我们已经知道我们可以访问特殊$event
变量。
因此,如果子组件发出带有参数的事件,我们可以使用以下方式访问它$event
:
父组件
<template>
// ...
<Child @event="someVariable = $event" />
// ...
</template>
子组件
export default {
//...
emitEvent () {
this.$emit('event', 'a simple text')
}
//...
}
当子组件是我们可以访问的组件时,这种方法非常有效,因为我们可以确保只传递一个参数。
但是如果我们使用第三方组件/库(例如 dropzone.js)通过事件传递许多参数怎么办?
只能$event
访问第一个参数。请参阅 codesandbox 示例,其中说明了$event
只能捕获第一个参数。(单击按钮即可查看控制台)
在这种情况下,$event
我们可以使用arguments
,并且所有参数都可以访问。
因此,在上面的代码中,为了使其工作,我们必须将第 4 行更改为Child.vue
从:
<GrandChild @event="$emit('event', $event)"/>
到:
<GrandChild @event="$emit('event', arguments)"/>
从功能组件发出事件
简短解释:
使用函数式组件意味着我们无法访问this
上下文。因此,我们无法执行this.$emit()
。但是……我们可以访问 ,listeners
所以我们可以执行<button @click="listeners.clicked"></button>
详细说明:
函数式组件是无状态的(没有响应式数据)和无实例的(没有 this 上下文)。但是函数式组件可以访问一些属性,例如props
、children
等等,以及最重要的(在本例中)listeners
。
根据Vue 文档:
listeners:包含父级注册的事件监听器的对象。这是 data.on 的别名。
这意味着我们可以从功能组件发出事件。Wiii :P
简单示例:
<template functional>
<button @click="listeners['custom-event']('message from child')">
Button from child
</button>
</template>
工作示例(单击按钮并打开控制台)
如果我们想从带有渲染函数的函数组件中发出事件,该怎么办?可以吗?当然可以!
简单示例:
export default {
functional: true,
render(createElement, { listeners }) {
return createElement(
"button",
{
on: {
click: event => {
const emit_event = listeners.event_from_child;
emit_event("Hello World!Is this the message we excpected? :/");
}
}
},
"Pass event to parent"
);
}
};
工作示例
有人可能会问,我们能不能用这种方法来使用.sync
Modifier
? 答案是?当然!
<button @click="listeners['update:message']('some text')">Click me</button>
将所有 props 传递给子组件
假设我们有一个组件,它接收参数props
,并且我们想将所有这些 props 传递给子组件。为了实现这一点,我们可以这样做:
<ChildComponent v-bind="$props" />
利用v-bind
我们还可以拥有如下对象:
data: () =>({
obj: {
firstName: 'John',
lastName: 'Doe',
age: 30
}
})
并将firstName
、lastName
、age
作为props
子组件传递,例如:
<Child v-bind="obj" />
从父级观察子级属性的变化
你可能想知道为什么要这么做,你是对的!这是一种不好的做法。但有时你会使用第三方组件,并且希望监视它们的属性以满足你的需求。
很久以前,在一个项目中,我们使用了一个日期选择器,我们希望能够检测弹出窗口何时可见。可惜的是,没有这个选项。我发现日期选择器使用了一个popupVisible
响应式属性,但库没有公开它。所以我不得不想办法从我的组件中监控这个属性。
下面的代码无法检测变化:
watch: {
'$refs.datePicker.popupVisible': {
handler (new_value) {
console.log('value changed')
},
deep: true
}
}
为了检测子组件属性的变化,您应该执行以下操作:
mounted() {
this.$watch(
"$refs.picker.popupVisible",
(new_value, old_value) => {
//execute your code here
}
);
}
工作示例:
详细了解vm.$watch
在路由器视图中监听子事件
大多数人应该已经知道这一点,因为它很简单,但我已经被问过很多次下面的问题了。
假设你有一个具有嵌套路由的组件:
<template>
//...
<router-view></router-view>
//...
</template>
并且您有如下嵌套路线:
<template>
//...
<button @click="$emit('event')"></button>
//...
</template>
因此,与嵌套路由对应的组件会发出一个事件。问题是:如何监听该事件?
简单的答案用代码演示:
<template>
//...
<router-view @event="callAMethod"></router-view>
//...
</template>
router-view
没错!我们在组件中监听该事件
Vue 组件生命周期钩子并不按照你认为的顺序运行
假设您有 2 个页面。主页和关于。
当从主页切换到关于时,关于组件的钩子将在主页组件的钩子之前运行。(created
beforeDestroy
请稍等片刻)
奇怪吗?尝试通过查看控制台在下面的工作示例中切换路线。
作为解决方案(虽然我不知道这是否是最好的解决方案),您可以使用transition-mode out-in
<transition mode="out-in">
<router-view></router-view>
</transition>
如何知道子组件是否已安装?
假设你有一个子组件,并且你想在子组件的钩子执行时执行某些操作。你可以这样做:
<Child @hook:created="doSomething" />
因此,如何知道子组件何时安装的问题是:
<Child @hook:mounted="componentMountedDoSomething" />
如何知道动态 vuex 注册的模块是否已注册?
借助动态注册/注销vuex 模块的功能,我们可以大大提高性能。
推荐大家阅读一篇非常有用的文章:性能优化:延迟加载 vuex 模块
我们可以注册一个 vuex 模块:
this.$store.registerModule('my-module', MyModule)
并取消注册:
this.$store.unregisterModule('my-module')
要知道模块是否已经注册:
if (Object.keys(this.$store._modules.root._children).includes('my-module')) {
// module is registered
}
我的时间非常有限,但我很高兴能抽出时间来写这篇文章(虽然花了不少时间)。希望它能对你有所帮助,也希望你喜欢。
如果您能留言提供解决方案,我将非常高兴。例如,关于最后一个“秘密”,您可以使用 Vuex Store 来指示模块是否已注册。
文章来源:https://dev.to/the_one/8-secrets-vue-developers-must-know-5la这是我在DEV 社区的第一篇文章。感谢阅读。