赞
踩
component是用来进行全局组件注册的。开发中经常有这样一个场景:一个组件可能在其他多个组件中被使用到,如果每次都像往常一样注册并导入就会显得十分多余。这时候就可以考虑使用component将这个组件注册成一个全局组件,就可以在其他组件中直接使用。
入口文件: main.js
import { createApp } from 'vue/dist/vue.esm-bundler'
import App from './App.vue'
let app = createApp(App);
/*
使用app.component来模仿写一个 Element UI 的全局组件 <el-button> 并能在各个组件中直接使用
*/
app.component("el-button", {
name: "el-button",
template: '<button value="按钮">ElementUI按钮</button>'
});
app.mount('#app');
App.vue
<template>
<!-- 在App.vue上直接使用定义好的全局组件 -->
<el-button />
</template>
<script setup>
// 此处无需再注册组件
</script>
成功渲染后的界面
当需要使用到的组件在其他组件中也有使用时,就可以考虑使用全局组件。例如,Ant Design中的组件就会在多个组件中使用到,所以在使用时都会使用app.use(Element)。这个use的过程其实就是将一个个Ant Design组件注册成为全局组件,具体注册代码为:
components.forEach(component => {
app.component(component.name, component);
})
如果当项目中也有一些业务组件可以提炼出来作为公共组件在多个组件中使用,就需要使用app.component来注册这些公共组件。
directive主要是用来自定义指令的。这里应用该API进行全局指令的定义,一旦定义了就可以在各个组件中使用该指令。
入口文件: main.js
import { createApp } from 'vue' import App from './App.vue' let app = createApp(App); // 封装一个 v-focus 的全局指令,页面挂载后输入框自动聚焦 app.directive("focus", { // 使用 mounted 钩子:当绑定的元素插入到 DOM 中时 mounted(el, binding, vnode, prevNode) { el.focus(); // 当元素插入到 DOM 后实现聚焦 }, }) // 封装一个 v-font 的全局指令,2s后字体变小并变色 app.directive('font', { mounted(el) { setTimeout(() => { el.style.fontSize = 6 + 'px'; el.style.color = "pink"; }, 2000); }, }) app.mount('#app');
App.vue
<template>
<input v-if="isShow" v-model="myName" v-focus>
<br>
<span v-font>{{ appName }}</span>
<br>
<HelloWorld v-font></HelloWorld>
</template>
<script setup>
import { ref } from 'vue';
import HelloWorld from './components/HelloWorld.vue';
let isShow = ref(true);
let myName = ref('Jeck');
let appName = ref("app");
</script>
实现效果
注:在Vue3中,对directive中各个钩子的命名实现了对Vue3组件生命周期钩子的同步,大大降低了在Vue2时代对于新钩子概念的理解的难度。
举个栗子:
// 封装一个 v-focus 的全局指令,页面挂在后输入框自动聚焦 app.directive("focus", { beforeMount(el, binding, vnode, prevNode) { // TODO: 只触发一次,只执行一次的操作放这边 console.log("beforeMount中的el", el); console.log("beforeMount中的el.parentNode=======>", el.parentNode); console.log("beforeMount中的binding=======>", binding); console.log("beforeMount中的vnode=======>", vnode); console.log("beforeMount中的prevNode=======>", prevNode); console.log("----------------------------------"); }, // 当绑定的元素插入到 DOM 中时 mounted(el, binding, vnode, prevNode) { console.log("mounted中的el", el); console.log("mounted中的el.parentNode=======>", el.parentNode); console.log("mounted中的binding=======>", binding); console.log("mounted中的vnode=======>", vnode); console.log("mounted中的prevNode=======>", prevNode); el.focus(); // 当元素插入到 DOM 后实现聚焦 console.log("----------------------------------"); }, // 组件更新前的状态 beforeUpdate(el, binding, vnode, prevNode) { console.log("beforeUpdate中的el", el); console.log("beforeUpdate中的binding=======>", binding); console.log("beforeUpdate中的vnode=======>", vnode); console.log("beforeUpdate中的prevNode=======>", prevNode); console.log("----------------------------------"); }, // 组件更新后的状态 updated(el, binding, vnode, prevNode) { console.log("updated中的el", el); console.log("updated中的binding=======>", binding); console.log("updated中的vnode=======>", vnode); console.log("updated中的prevNode=======>", prevNode); }, // 指令从组件上解除绑定之前 beforeUnmount(el, binding, vnode, prevNode) { console.log("beforeUnmount中的el", el); console.log("beforeUnmount中的binding=======>", binding); console.log("beforeUnmount中的vnode=======>", vnode); console.log("beforeUnmount中的prevNode=======>", prevNode); console.log("----------------------------------"); }, // 指令从组件上解除绑定之后 unmounted(el, binding, vnode, prevNode) { console.log("unmounted中的el", el); console.log("unmounted中的binding=======>", binding); console.log("unmounted中的vnode=======>", vnode); console.log("unmounted中的prevNode=======>", prevNode); }, })
未触发vnode变化的操作前,控制台打印:
编辑输入框,触发vnode变化的操作后,控制台打印:
设置定时器,3s后删除输入框组件(将组件与自定义指令解绑),触发beforeUnmount / unmounte钩子,控制台打印:
钩子中各个参数解读:
el: 指令绑定到的元素,主要用于直接操作Dom
binding: 包含以下 property 的对象
instance: 使用指令的组件实例
value: 传递给指令的值
oldValue: 先前的值,在 beforeUpdate 和 updated钩子中可用
arg: 参数传递给指令
modifiers: 包含修饰符的对象
dir: 一个对象,在注册指令时作为参数传递
vnode: 上面作为el参数收到的真实Dom元素的蓝图
prevNode: 是一个虚拟节点,仅在beforeUpdate 和 updated钩子中可用
当很多组件都需要重复做一个相同的动作时,比如页面刚加载,多个组件就需要有一个配合的动作(比如边框出现一秒后消失等)。这种重复的动作就可以考虑用directive封装一个全局的自定义vue指令。不仅使用方便,还便于后期维护。directive在实际开发中使用较少,即使使用也基本上是用自定义指令操作一下Dom。
本文作以学习总结,摘自深入实战Vue开发(殷荣桧 / 著):以Vue3接口(API)为例讲解
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。