美文网首页
Vue3 | 组件的定义及复用性、局部组件、全局组件、组件间传值

Vue3 | 组件的定义及复用性、局部组件、全局组件、组件间传值

作者: 凌川江雪 | 来源:发表于2021-03-14 00:27 被阅读0次

    完整原文地址见简书https://www.jianshu.com/p/1bc868ff488f

    更多完整Vue笔记目录敬请见《前端 Web 笔记 汇总目录(Updating)》


    本文内容提要

    • Vue.createApp()的参数是页面的根组件

    • 自定义的子组件是可以被复用的,且多个复用子组件之间数据相互独立

    • 自定义的【全局子组件】方便快捷,随处可用,但影响性能

    • 定义局部组件

    • 局部组件再例

    • 局部组件语法一重点

    • 全局组件、局部组件比较

    • 父子组件间相互通信的方式

    • 动态参数传参 解决 number转string的问题

    • 传参类型校验

      • 传参类型校验再例【Boolean例】
      • 传参类型校验再例【Function例】【传递函数型参数】
    • props

      • props块的required属性 配置必填效果
      • props块的default属性 配置默认值
      • props块的validator属性 配置参数值大小限制
    • 多个数据 传参时常规写法

    • 使用Object方式优化v-bind传参

    • HTML中,推荐使用 横杠分割法 代替 驼峰命名法

    • 单向数据流的理解

      • 解决方法
      • 单向数据流存在的意义
    • Non-prop 属性

      • 子组件使用inheritAttrs: false属性配置,可以拒绝继承接收 父组件传递过来的属性
      • Non-props 应用场景
      • $attrs修饰符
      • $attrs修饰符 再例
      • $attrs 运用于生命周期方法中

    Vue.createApp()的参数是页面的根组件

    Vue.createApp()传入的参数,将作为页面的根组件,
    似Android的rootView

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Hello World! heheheheheheda</title>
        <script src="https://unpkg.com/vue@next"></script>
    </head>
    
    <body>
        <div id="heheApp"></div>
    </body>
    <script>
        const app = Vue.createApp({
            template: `
            <div>
                hello!
            </div>`
        });
    
        const vm = app.mount('#heheApp');
    </script>
    </html>
    
    效果:

    自定义的子组件是可以被复用的,且多个复用子组件之间数据相互独立

    如下复用三个<counter/>自定义子组件,三个<counter/>之间数据相互独立:

    <script>
        const app = Vue.createApp({
            template: `
            <div>
                <counter/>
                <counter/>
                <counter/>
            </div>`
        });
    
        app.component('counter',{
            data() {
                return {
                    count: 1
                }
            },
            template: `
                <div @click="count += 1">{{count}}</div>
            `
        })
    
        const vm = app.mount('#heheApp');
    </script>
    
    效果:

    自定义的【全局子组件】方便快捷,随处可用,但影响性能

    自定义的全局子组件方便快捷,随处可用,
    任何地方都可以引用子组件,如下【似Android的Fragment】代码;

    但只要使用.component()定义了子组件,子组件便挂载在VueApp实例上了,
    即使不调用该子组件,它也会占用内存和性能:

    <script>
        const app = Vue.createApp({
            template: `
            <div>
                <counter-parent />
            </div>`
        });
    
        app.component('counter-parent',{
            template: `
                <div>
                    <counter/>
                </div>`
        })
    
        app.component('counter',{
            data() {
                return {
                    count: 1
                }
            },
            template: `
                <div @click="count += 1">{{count}}</div>`
        })
    
        const vm = app.mount('#heheApp');
    </script>
    
    效果:

    定义局部组件

    语法:

     const 局部组件实例名= {
            data() {
                return {
                    ...
                }
            },
            template: 
                ...
        }
    
    const app = Vue.createApp({
            components: { 定义局部组件引用名 : 局部组件实例名},
            template: `
            <div> <局部组件引用名/> </div>`
        });
    

    案例代码:

    <script>
        const counter = {
            data() {
                return {
                    count: 1
                }
            },
            template: `
                <div @click="count += 1">{{count}}</div>`
        }
    
        const app = Vue.createApp({
            components: { localWidget : counter},
            template: `
            <div>
                <localWidget />
            </div>`
        });
    
        const vm = app.mount('#heheApp');
    </script>
    

    效果:




    如果局部组件实例名定义的局部组件引用名 相同,
    则可以直接使用以下的简写语法
    <script>
    
        const counter = {
            data() {
                return {
                    count: 1
                }
            },
            template: `
                <div @click="count += 1">{{count}}</div>`
        }
    
        const app = Vue.createApp({
            components: { counter},
            template: `
            <div>
                <counter />
            </div>`
        });
    
        const vm = app.mount('#heheApp');
    </script>
    
    效果:

    局部组件再例

    <script>
    
        const counter = {
            data() {
                return {
                    count: 1
                }
            },
            template: `
                <div @click="count += 1">{{count}}</div>`
        }
    
        const heheda = {
            template: `
                <div>heheda</div>`
        }
    
        const app = Vue.createApp({
            components: { 
                counter, 
                hehedadom : heheda
            },
            template: `
            <div>
                <hehedadom />
                <counter />
            </div>`
        });
    
        const vm = app.mount('#heheApp');
    </script>
    
    效果:

    局部组件语法一重点

    为了将局部组件实例名 同 普通的js(驼峰命名法)变量区分开来,
    推荐使用首字母大写驼峰局部组件实例名进行命名,
    同时,
    Vue代码在template中引用局部组件时时,
    会忽略大小写和杠号 对components中定义的组件进行映射;
    如下,
    <counter />忽略了大小写 映射到 Counter
    <heheda-dom />忽略了横杆号和大小写 映射到 HehedaDom

    <script>
    
        const Counter = {
            data() {
                return {
                    count: 1
                }
            },
            template: `
                <div @click="count += 1">{{count}}</div>`
        }
    
        const HehedaDom = {
            template: `
                <div>heheda</div>`
        }
    
        const app = Vue.createApp({
            components: { 
                Counter, HehedaDom
            },
            template: `
            <div>
                <heheda-dom />
                <counter />
            </div>`
        });
    
        const vm = app.mount('#heheApp');
    </script>
    
    效果:

    全局组件、局部组件比较

    全局组件定以后,随处可用,方便快捷,任何地方都可以引用子组件,
    但性能不高(定以后 不用时也 挂载并占用内存),
    命名建议,小写字母 配合 横线隔开;

    局部组件 定义后 需注册才能使用才会占用资源,性能较高,
    但使用较麻烦,
    命名建议,大写字母 配合 驼峰命名法;

    父子组件间相互通信

    主要是借助props的方式:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Hello World! heheheheheheda</title>
        <script src="https://unpkg.com/vue@next"></script>
    </head>
    
    <body>
        <div id="heheApp"></div>
    </body>
    <script>
        const app = Vue.createApp({
            template: `
            <div><test content="heheda!!!"></div>`
        });
    
        app.component('test', {
            props: ['content'],
            template:`<div>{{content}}</div>`
        })
    
        const vm = app.mount('#heheApp');
    </script>
    </html>
    
    效果:

    动态参数传参 解决 number转string的问题

    静态传参,存在如题问题:

    <script>
        const app = Vue.createApp({
            template: `
            <div><test content = 123></div>`
        });
    
        app.component('test', {
            props: ['content'],
            template:`<div>{{content}}<br>
                {{typeof content}}</div>`
        })
    
        const vm = app.mount('#heheApp');
    </script>
    

    将数据写在data版块中,借用v-bind 动态传参,解决以上问题:

    <script>
        const app = Vue.createApp({
            data() {
                return {
                    num : 666
                }
            },
            template: `
            <div><test :content = 'num'></div>`
        });
    
        app.component('test', {
            props: ['content'],
            template:`<div>{{content}}<br>
                {{typeof content}}</div>`
        })
    
        const vm = app.mount('#heheApp');
    </script>
    

    传参类型校验

    传参类型校验支持:String、Boolean、Array、Object、Function、Symbol 等类型;

    关键:
    props位的值,从数组形式换为对象(键值)形式
    键为承接属性,值为期望值类型

    <script>
        const app = Vue.createApp({
            data() {
                return {
                    num : 666
                }
            },
            template: `
            <div><test :content = 'num' /></div>`
        });
    
        app.component('test', {
            props: {
                content : String,
            },
            template:`<div>{{content}}<br>
                {{typeof content}}</div>`
        })
    
        const vm = app.mount('#heheApp');
    </script>
    

    如上代码,期望得到一个String类型的参数,却传入一个number类型的参数,
    则运行时 会刷出报错警告:


    更正入参类型,则不再报错:
    <script>
        const app = Vue.createApp({
            data() {
                return {
                    num : "666"
                }
            },
            template: `
            <div><test :content = 'num' /></div>`
        });
    
        app.component('test', {
         ...
        })
    
        const vm = app.mount('#heheApp');
    </script>
    

    传参类型校验再例【Boolean例】

    <script>
        const app = Vue.createApp({
            data() {
                return {
                    num : "666"
                }
            },
            template: `
            <div><test :content = 'num' /></div>`
        });
    
        app.component('test', {
            props: {
                content : Boolean,
            },
            template:`<div>{{content}}<br>
                {{typeof content}}</div>`
        })
    
        const vm = app.mount('#heheApp');
    </script>
    

    传参类型校验再例【Function例】【传递函数型参数】

    <script>
        const app = Vue.createApp({
            data() {
                return {
                    num : "666"
                }
            },
            template: `
            <div><test :content = 'num' /></div>`
        });
    
        app.component('test', {
            props: {
                content : Function,
            },
            template:`<div>{{content}}<br>
                {{typeof content}}</div>`
        })
    
        const vm = app.mount('#heheApp');
    </script>
    

    更正类型【传递函数型参数】:
    <script>
        const app = Vue.createApp({
            data() {
                return {
                    num : () => {console.log("8888888")}
                }
            },
            template: `
            <div><test :content = 'num' /></div>`
        });
    
        app.component('test', {
            props: {
                content : Function,
            },
            methods: {
                handlerClick() {
                    console.log("666666");
                    this.content();
                }
            },
            template:`<div @click="handlerClick">{{content}}<br>
                {{typeof content}}</div>`
        })
    
        const vm = app.mount('#heheApp');
    </script>
    

    props块的required属性 配置必填效果

    props块的required属性配置true时,要求对应配置的属性要传参数
    没有传参数,则报错;

    如下案例,配置了required属性为true,但没有传参:

    <script>
        const app = Vue.createApp({
            data() {
                return {
                    num : 123
                }
            },
            template: `
            <div><test /></div>`
        });
    
        app.component('test', {
            props: {
                content: {
                    type : Number,
                    required: true
                }
            },
            methods: {
                handlerClick() {
                    console.log("666666");
                    this.content();
                }
            },
            template:`<div @click="handlerClick">{{content}}<br>
                {{typeof content}}</div>`
        })
    
        const vm = app.mount('#heheApp');
    </script>
    

    效果:


    传了参就好起来了:
    <script>
        const app = Vue.createApp({
            data() {
                return {
                    num : 123
                }
            },
            template: `
            <div><test :content = 'num' /></div>`
        });
    
        app.component('test', {
            props: {
                content: {
                    type : Number,
                    required: true
                }
            },
            methods: {
                ...
            },
            template:...
        })
    
        const vm = app.mount('#heheApp');
    </script>
    

    props块的default属性 配置默认值

    相关文章

      网友评论

          本文标题:Vue3 | 组件的定义及复用性、局部组件、全局组件、组件间传值

          本文链接:https://www.haomeiwen.com/subject/axduqltx.html