Vue3应用API——component、directive


一、component

1.介绍

  component是用来进行全局组件注册的。开发中经常有这样一个场景:一个组件可能在其他多个组件中被使用到,如果每次都像往常一样注册并导入就会显得十分多余。这时候就可以考虑使用component将这个组件注册成一个全局组件,就可以在其他组件中直接使用

2.实践

入口文件: 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>

成功渲染后的界面
在这里插入图片描述

3.应用场景

  当需要使用到的组件在其他组件中也有使用时,就可以考虑使用全局组件。例如,Ant Design中的组件就会在多个组件中使用到,所以在使用时都会使用app.use(Element)。这个use的过程其实就是将一个个Ant Design组件注册成为全局组件,具体注册代码为:

components.forEach(component => {
  app.component(component.name, component);
})

  如果当项目中也有一些业务组件可以提炼出来作为公共组件在多个组件中使用,就需要使用app.component来注册这些公共组件。

二、directive

1.介绍

  directive主要是用来自定义指令的。这里应用该API进行全局指令的定义,一旦定义了就可以在各个组件中使用该指令。

2.实践

入口文件: 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钩子中可用

3.应用场景

  当很多组件都需要重复做一个相同的动作时,比如页面刚加载,多个组件就需要有一个配合的动作(比如边框出现一秒后消失等)。这种重复的动作就可以考虑用directive封装一个全局的自定义vue指令。不仅使用方便,还便于后期维护。directive在实际开发中使用较少,即使使用也基本上是用自定义指令操作一下Dom。


总结

  本文作以学习总结,摘自深入实战Vue开发(殷荣桧 / 著):以Vue3接口(API)为例讲解

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JV_32

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值