• 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 的全局组件  并能在各个组件中直接使用
    */
    app.component("el-button", {
        name: "el-button",
        template: ''
    });
    
    app.mount('#app');
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    App.vue

    <template>
      
      <el-button />
    template>
    
    <script setup>
    // 此处无需再注册组件
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

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

    3.应用场景

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

    components.forEach(component => {
      app.component(component.name, component);
    })
    
    • 1
    • 2
    • 3

      如果当项目中也有一些业务组件可以提炼出来作为公共组件在多个组件中使用,就需要使用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');
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    实现效果

    注: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);
        },
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    未触发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)为例讲解

  • 相关阅读:
    Webpack vs Vite的核心差异
    web前端期末大作业 基于HTML+CSS+JavaScript绿色的在线教育平台网站响应式企业网站模板
    新鲜速递:Spring Boot3多模块项目跨包自动注入的方法,快速编写自己的starter项目
    java-php-python-ssm学生请假系统演示计算机毕业设计
    Anconda环境中python默认不是该环境下的python
    三层vlan实验
    不重启Docker能添加自签SSL证书镜像仓库吗?
    第一个微信小程序的初始化过程、小程序微信开发平台的下载、如何注册一个微信小程序的账号
    【HTML】前端网页开发工具Vscode中DOCTYPE和lang以及字符集的作用
    【JavaSE】面向对象——属性和方法
  • 原文地址:https://blog.csdn.net/m0_53375764/article/details/127705235