Vue3的学习---8

yishengwanwuzhao / 2024-08-24 / 原文

8. Vue可复用解决方案

Vue可复用方案是指在Vue.js项目中,通过创建可复用的组件、指令、插件等,来提高代码的复用性和可维护性常见的Vue可复用方案有:组件(Components)、指令(Directives)、插件(Plugins)、混入(Mixins)、高阶组件(Higher-Order Components, HOC)等。通过这些可复用方案,可以有效地减少代码重复,提高开发效率和代码质量。

8.1 自定义指令

自定义指令是Vue.js中一种强大的功能,允许你在DOM元素上绑定特定的行为。通过自定义指令,你可以封装复杂的DOM操作逻辑,并在多个组件中复用。

以下是如何创建自定义指令的详细步骤:

自定义指令可以包含几个钩子函数,例如 bindinsertedupdatecomponentUpdatedunbind。每个钩子函数都有其特定的用途。

钩子函数

  • bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
  • inserted:被绑定元素插入父节点时调用(仅保证父节点存在,但不一定已被插入文档中)。
  • update:所在组件的VNode更新时调用,但是可能发生在其子VNode更新之前。
  • componentUpdated:指令所在组件的VNode及其子VNode全部更新后调用。
  • unbind:只调用一次,指令与元素解绑时调用。

8.1.1 全局指令

<body>
    <div id="app">
        <div v-date></div>
        <p v-date></p>
    </div>

    <script src="../js/vue3.js"></script>
    <script>
        let app = Vue.createApp({})

        // 自定义指令,directive('指令名', {指令的内容})
        app.directive('date', {
            // 指令的定义,mounted会返回一个dom对象,el是指令所在的元素
            mounted(el) {
                el.innerHTML = new Date()
            }
        })

        app.mount('#app')
    </script>
</body>

8.1.2 局部指令

<body>
    <div id="app">
        <div v-date></div>
        <p v-date></p>
    </div>

    <script src="../js/vue3.js"></script>
    <script>
        let app = Vue.createApp({
            directives: {
                date: {
                    mounted(el) {
                        el.innerHTML = new Date()
                    }
                }
            }
        }).mount('#app')
    </script>
</body>

也可以这么写:

<body>
    <div id="app">
        <div v-date></div>
        <p v-date></p>
    </div>

    <script src="../js/vue3.js"></script>
    <script>
        const mydirective = {
            date: {
                mounted(el) {
                    el.innerHTML = new Date()
                }
            }
        }
        let app = Vue.createApp({
            directives: mydirective
        }).mount('#app')
    </script>
</body>

8.1.3 指令参数

<body>
    <div id="app">
        <img src="../img/jy.jpg" v-imgcir="300">
    </div>

    <script src="../js/vue3.js"></script>
    <script>
        const mydirective = {
            imgcir: {
                mounted(el,binding) {
                    el.style.width = binding.value + 'px'
                    el.style.height = binding.value + 'px'
                    el.style.borderRadius = (binding.value/2) + 'px'
                }
            }
        }
        let app = Vue.createApp({
            directives:mydirective
        }).mount('#app')
    </script>
</body>

8.2 Mixin混入

Mixin混入(Mixin Mixins)是一种编程模式,主要用于在面向对象编程中,通过将一个或多个类的功能“混入”到另一个类中,从而实现代码的复用和功能的扩展。Mixin类通常不单独实例化,而是作为其他类的组成部分,为其提供特定的行为或属性。

Mixin混入的主要特点包括:

  1. 代码复用:Mixin类可以包含一些通用的方法或属性,这些方法或属性可以被多个类共享,从而减少代码重复。
  2. 灵活性:通过Mixin混入,可以在不修改原有类结构的情况下,为类添加新的功能。
  3. 多重继承:在支持多重继承的语言中,Mixin类可以被多个类继承,从而实现复杂的功能组合。

8.2.1 基本用法

<body>
    <div id="app">
        {{ num }}
        {{ name }}
        {{ date }}
    </div>

    <script src="../js/vue3.js"></script>
    <script>
        const common = {
            data() {
                return {
                    name: '张三'
                }
            }
        }

        const date = {
            data() {
                return {
                    date: new Date()
                }
            }
        }

        let app = Vue.createApp({
            data() {
                return {
                    num: 100
                }
            },
            mixins: [common, date]
        }).mount('#app')
    </script>
</body>

8.2.2 混入优先级

Vue中Mixin混入的优先级规则如下:

  • 数据对象(data):组件自身的数据优先级更高。
  • 生命周期钩子函数:Mixin中的钩子函数会在组件自身的钩子函数之前调用。
  • 方法(methods)、计算属性(computed)和其他选项:组件自身的定义会覆盖Mixin中的定义。
<body>
    <div id="app">
        {{ num }}
        {{ name }}<br>
        <button @click="add">点击</button>
    </div>

    <script src="../js/vue3.js"></script>
    <script>
        const common = {
            data() {
                return {
                    name: '张三',
                    num: 200
                }
            },
            methods: {
                add() {
                    console.log('这是Mixin混入中的方法');
                }
            },
            created() {
                console.log('vue实例创建后生命周期函数--Mixin');
            }
        }

        let app = Vue.createApp({
            data() {
                return {
                    num: 100
                }
            },
            mixins: [common],
            methods: {
                add() {
                    console.log('这是组件中的一个方法');
                }
            },
            created() {
                console.log('vue实例创建后生命周期函数--组件');
            }
        }).mount('#app')
    </script>
</body>

8.2.3 全局Mixin

<body>
    <div id="app">
        {{ num }}
        <button @click="add">点击</button>
    </div>

    <script src="../js/vue3.js"></script>
    <script>
        let app = Vue.createApp({})

        app.mixin({
            data() {
                return {
                    num: 100
                }
            },
            methods: {
                add() {
                    console.log('这是Mixin混入中的方法');
                }
            },
            created() {
                console.log('vue实例创建后生命周期函数--Mixin');
            }
        })

        app.mount('#app')
    </script>
</body>

8.3 插件

插件(Plugin)是一种扩展Vue功能的方式。插件可以全局地为Vue应用添加一些功能,如添加全局方法或属性、添加全局资源(指令、过滤器、过渡等)、通过全局混入(Mixin)添加一些组件选项,或者向Vue实例添加实例方法。

8.3.1 基本用法

<body>
    <div id="app">
        
    </div>

    <script src="../js/vue3.js"></script>
    <script>
        // 插件声明有两种方式
        // 1、对象形式
        /*
        const MyPlugin = {
            // app:将使用插件的Vue实例通过app参数传入;options:参数
            install(app, options) {
                console.log('hello world');
                console.log(app);
                console.log(options);
            }
        }
        */

        // 2、函数形式
        const MyPlugin = (app, options) => {
            console.log('hello world');
            console.log(app);
            console.log(options);
        }

        let app = Vue.createApp({})

        app.use(MyPlugin, { name:'张三' })

        app.mount('#app')
    </script>
</body>

8.3.2 给Vue扩展功能

<body>
    <div id="app">
        <img src="../img/jy.jpg" v-imgcir="300">
        {{ date }}
    </div>

    <script src="../js/vue3.js"></script>
    <script>
        const MyPlugin = {
            install(app, options) {
                app.directive('imgcir', {
                    mounted(el, binding) {
                        el.style.width = binding.value + 'px'
                        el.style.height = binding.value + 'px'
                        el.style.borderRadius = (binding.value / 2) + 'px'
                    }
                })
                app.mixin({
                    data() {
                        return {
                            date: new Date()
                        }
                    }
                })
            }
        }
        let app = Vue.createApp({})

        app.use(MyPlugin)

        app.mount('#app')
    </script>
</body>