Vue2(组件开发)

目录

前言

上一章博客我们讲解了Vue生命周期,列表过滤,计算属性和监听器
这一章我们来讲Vue组件开发

一,组件的使用

创建组件两种方式

javascript 复制代码
var Header = { 
    template:'模板' , 
    data是一个函数,
    methods:功能,
    components:子组件们 
}//局部声明

Vue.component('组件名',组件对象);//全局注册 等于注册加声明了

组件的分类

  • 通用组件(例如表单、弹窗、布局类等) (多个项目都可以复用)
  • 业务组件(抽奖、机器分类)(本项目中复用)
  • 页面组件(单页面开发程序的每个页面的都是一个组件、只完成功能、不复用)

组件开发三部曲:声明、注册、使用

注意:子组件的命名,如果有驼峰命名,在使用子组件标签时用"-"隔开

javascript 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        大家好,{{name}}
        <hello></hello>
        <saybyebye></saybyebye>
    </div>


    <template id="myhello">
        <div>hello,{{name}}</div>
    </template>
</body>
<script src="../js/vue2.7.js"></script>
<script>

    // 注册了一个全局组件,名字叫hello
    Vue.component('hello',{
        template:`#myhello`,
        data(){
            return{
                name:'我是hello'
            }
        }
    })

    // 定义一个局部组件
    var saybyebye={
        template:`<div>你好</div>`
    }

    var app = new Vue({
        el:'#app',
        data(){
            return{
                name:"张三",
            }
        },
        // 注册局部组件
        components:{
            saybyebye
        }
    })

</script>
</html>

二,插槽slot

slot就是在声明子组件时给DOM留下的坑位,以便于父组件在使用子组件的时候可以在坑位里动态的插入自己的内容。

​ 并且,坑位是可以命名的,也就是说,子组件在声明的时候命名坑位,方便父组件在指定的坑位中插入内容

​ slot是动态的DOM

  • 插槽的使用:
    • 步骤有两步:a.子组件上留坑。b.父组件使用子组件的时候,给坑里赋值.
    • 要有父子组件作为前提。
    • 目的是让子组件成为动态的组件。

匿名插槽

  • 匿名插槽就是在声明的时候没有声明name,会把全部内容都显
javascript 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        大家好,{{name}}
        <hello></hello>
        <saybyebye>
            <div>我是插槽的内容</div>
        </saybyebye>
    </div>


    <template id="myhello">
        <div>hello,{{name}}</div>
    </template>
</body>
<script src="../js/vue2.7.js"></script>
<script>

    // 注册了一个全局组件,名字叫hello
    Vue.component('hello',{
        template:`#myhello`,
        data(){
            return{
                name:'我是hello'
            }
        }
    })

    // 定义一个局部组件
    var saybyebye={
        template:`
        <div>
            <div>你好</div>
            // 插槽内容
            <slot></slot>    
        </div>
        `
    }

    var app = new Vue({
        el:'#app',
        data(){
            return{
                name:"张三",
            }
        },
        // 注册局部组件
        components:{
            saybyebye
        }
    })

</script>
</html>


具名插槽

  • 具名插槽会在声明时,指定name。会在子组件中有选择的进行展示
javascript 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        大家好,{{name}}
        <hello></hello>
        <saybyebye>
            <div slot="niu1">我是插槽的内容</div>
            <template #niu2>
                <div>你好niu2</div>
            </template>
            <template v-slot:niu3>
                <div>你好niu3</div>
            </template>
        </saybyebye>
    </div>


    <template id="myhello">
        <div>hello,{{name}}</div>
    </template>
</body>
<script src="../js/vue2.7.js"></script>
<script>

    // 注册了一个全局组件,名字叫hello
    Vue.component('hello',{
        template:`#myhello`,
        data(){
            return{
                name:'我是hello'
            }
        }
    })

    // 定义一个局部组件
    var saybyebye={
        template:`
        <div>
            <slot name="niu1"></slot>   
            <div>你好niu1</div>
            // 插槽内容
            <slot name="niu2"></slot>    
            <slot name="niu3"></slot>    
        </div>
        `
    }

    var app = new Vue({
        el:'#app',
        data(){
            return{
                name:"张三",
            }
        },
        // 注册局部组件
        components:{
            saybyebye
        }
    })

</script>
</html>

三,refs和parent

这两个属性的作用是获取到子组件实例数组和父组件实例。
有了实例,就可以很方便的操作组件的属性和方法。

  • refs
javascript 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        大家好{{name}}
        <button @click="ouda">打一顿</button>
        <Myheader ref="dawa"></Myheader>
    </div>
</body>
<script src="../js/vue2.7.js"></script>
<script>
    Vue.prototype.$middleBus = new Vue();
    var Myheader = {
        template:`
            <div>
                子组件
                {{xingming}}--{{Hp}}
            </div>
        `,
        
        data(){
            return{
                xingming:'林宇豪',
                Hp:100,
            }
        },
    }


    var app = new Vue({
        el:'#app',
        data(){
            return{
                name:'小豪',
            }
        },

        methods:{
            ouda(){
                console.log("孽子,打一顿");
                this.$refs.dawa.Hp = this.$refs.dawa.Hp - 10
            },
        },
        components:{
            Myheader
        }

    })

    
</script>
</html>
  • parent

$refs的使用需要,在子元素上通过ref属性声明自己的引用名称

javascript 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        大家好,我是{{name}}
        <Myheader ref="dawa"></Myheader>
        <Myheadererwa ref="erwa" ></Myheadererwa>
    </div>
</body>
<script src="../js/vue2.7.js"></script>
<script>
    Vue.prototype.$middleBus = new Vue();
    var Myheader = {
        template:`
            <div>
                   
            </div>
        `,
        
    }

    var Myheadererwa = {
        template:`
            <div>
                <button @click="jiao">叫爷爷</button>  
            </div>
        `,
        data(){
            return{ 
            }
        },
        methods:{
            jiao(){
                this.$parent.name="爷爷"
            },  
        },
    }

    var app = new Vue({
        el:'#app',
        data(){
            return{
                name:'小豪',
            }
        },
        components:{
            Myheader,
            Myheadererwa

        }

    })

    
</script>
</html>

四,父子组件间的通信

4.1,父传子 :父传子的时候,通过属性传递

  • 在子组件标签中,自定义属性和值
dart 复制代码
<Myheader ref="header" age="18" :sex="sex"></Myheader>
  • 在子组件内部,通过props属性,获取所有的值
javascript 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        大家好{{name}}
        <button @click="ouda">打一顿</button>
        <button @click="anwei">安慰</button>
        <button @click="xiaodao">看看导哥在干嘛</button>
        <Myheader ref="dawa"></Myheader>
        <Myheadererwa ref="erwa" age="2" :nengli="nengli2"></Myheadererwa>
        <div id="mydiv"></div>
    </div>
</body>
<script src="../js/vue2.7.js"></script>
<script>
    Vue.prototype.$middleBus = new Vue();
    var Myheader = {
        template:`
            <div>
                子组件
                {{xingming}}--{{Hp}}
            </div>
        `,
        
        data(){
            return{
                xingming:'林宇豪',
                Hp:100,
            }
        },
    }

    var Myheadererwa = {
        template:`
            <div>
                子组件
                {{xingming}}--{{Hp}}
                <button @click="jiao">叫爷爷</button>  
                二娃 = {{age}} -- {{nengli}}
            </div>
        `,
        data(){
            return{ 
                xingming:'王导',
                Hp:0,
            }
        },
        methods:{
            see(){
                console.log("再看岛国动作片");
            },
            jiao(){
                this.$parent.name="爷爷"
            },
            
        },
        mounted(){
            this.$middleBus.$on('jieshou',val=>{
                // 使用箭头函数,可以不改变this的指向,仍然和外部的this保持一致,指向child01
                console.log(val);
            });
        },
        props:['age','nengli'],
    }

    var app = new Vue({
        el:'#app',
        data(){
            return{
                name:'小豪',
                nengli2:"千里眼,顺风耳"
            }
        },

        methods:{
            ouda(){
                console.log("孽子,打一顿");
                this.$refs.dawa.Hp = this.$refs.dawa.Hp - 10
                // if(this.$refs.dawa.Hp<=0){
                //     document.getElementById("#mydiv").innerHTML="已经死了不能在死了爹"
                // }
            },
            anwei(){
                console.log("抽了一巴掌,安慰了一下");
                this.$refs.erwa.Hp = this.$refs.erwa.Hp + 10
            },
            xiaodao(){
                this.$refs.erwa.see()            
            },
            
        },
        components:{
            Myheader,
            Myheadererwa

        }

    })

    
</script>
</html>

4.2,父组件监听自定义事件

dart 复制代码
      <Myheadererwa @to-parent-event="bainian" ref="erwa" age="2" :nengli="nengli2"></Myheadererwa>
javascript 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        大家好{{changname}}
        <button @click="ouda">打一顿</button>
        <button @click="anwei">安慰</button>
        <button @click="xiaodao">看看导哥在干嘛</button>
        <Myheader ref="dawa"></Myheader>
        <Myheadererwa @to-parent-event="bainian" ref="erwa" age="2" :nengli="nengli2"></Myheadererwa>
        <div id="mydiv"></div>
    </div>
</body>
<script src="../js/vue2.7.js"></script>
<script>
    Vue.prototype.$middleBus = new Vue();
    var Myheader = {
        template:`
            <div>
                子组件
                {{xingming}}--{{Hp}}
                <button @click="chuanzhi">发送一条信息</button>    
            </div>
        `,
        
        data(){
            return{
                xingming:'林宇豪',
                Hp:100,
            }
        },
        methods:{
            chuanzhi(){
                this.$middleBus.$emit('jieshou','你好child01,我是child02');
            }
        }
    }

    var Myheadererwa = {
        template:`
            <div>
                子组件
                {{xingming}}--{{Hp}}
                <button @click="jiao">叫爷爷</button>  
                <button @click="happyNewYear">给爷爷拜年</button>  
                二娃 = {{age}} -- {{nengli}}
            </div>
        `,
        data(){
            return{ 
                xingming:'王导',
                Hp:0,
            }
        },
        methods:{
            see(){
                console.log("再看岛国动作片");
            },
            jiao(){
                this.$parent.name="爷爷"
            },
            happyNewYear(){
                // 触发自定义事件
                this.$emit('to-parent-event',this.xingming)
            }
            
        },
        mounted(){
            this.$middleBus.$on('jieshou',val=>{
                // 使用箭头函数,可以不改变this的指向,仍然和外部的this保持一致,指向child01
                console.log(val);
            });
        },
        props:['age','nengli'],
    }

    var app = new Vue({
        el:'#app',
        data(){
            return{
                changname:'小豪',
                nengli2:"千里眼,顺风耳"
            }
        },

        methods:{
            ouda(){
                console.log("孽子,打一顿");
                this.$refs.dawa.Hp = this.$refs.dawa.Hp - 10
                // if(this.$refs.dawa.Hp<=0){
                //     document.getElementById("#mydiv").innerHTML="已经死了不能在死了爹"
                // }
            },
            anwei(){
                console.log("抽了一巴掌,安慰了一下");
                this.$refs.erwa.Hp = this.$refs.erwa.Hp + 10
            },
            xiaodao(){
                this.$refs.erwa.see()            
            },
            bainian(xingming){
                console.log(xingming+"给您拜年了 ");
            }
            
        },
        components:{
            Myheader,
            Myheadererwa

        }

    })

    
</script>
</html>

五,非父子组件的通信

javascript 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        大家好{{changname}}
        <button @click="ouda">打一顿</button>
        <button @click="anwei">安慰</button>
        <button @click="xiaodao">看看导哥在干嘛</button>
        <Myheader ref="dawa"></Myheader>
        <Myheadererwa @to-parent-event="bainian" ref="erwa" age="2" :nengli="nengli2"></Myheadererwa>
        <div id="mydiv"></div>
    </div>
</body>
<script src="../js/vue2.7.js"></script>
<script>
    Vue.prototype.$middleBus = new Vue();
    var Myheader = {
        template:`
            <div>
                子组件
                {{xingming}}--{{Hp}}
                <button @click="chuanzhi">发送一条信息</button>    
            </div>
        `,
        
        data(){
            return{
                xingming:'林宇豪',
                Hp:100,
            }
        },
        methods:{
            chuanzhi(){
                this.$middleBus.$emit('jieshou','你好child01,我是child02');
            }
        }
    }

    var Myheadererwa = {
        template:`
            <div>
                子组件
                {{xingming}}--{{Hp}}
                <button @click="jiao">叫爷爷</button>  
                <button @click="happyNewYear">给爷爷拜年</button>  
                二娃 = {{age}} -- {{nengli}}
            </div>
        `,
        data(){
            return{ 
                xingming:'王导',
                Hp:0,
            }
        },
        methods:{
            see(){
                console.log("再看岛国动作片");
            },
            jiao(){
                this.$parent.name="爷爷"
            },
            happyNewYear(){
                // 触发自定义事件
                this.$emit('to-parent-event',this.xingming)
            }
            
        },
        mounted(){
            this.$middleBus.$on('jieshou',val=>{
                // 使用箭头函数,可以不改变this的指向,仍然和外部的this保持一致,指向child01
                console.log(val);
            });
        },
        props:['age','nengli'],
    }

    var app = new Vue({
        el:'#app',
        data(){
            return{
                changname:'小豪',
                nengli2:"千里眼,顺风耳"
            }
        },

        methods:{
            ouda(){
                console.log("孽子,打一顿");
                this.$refs.dawa.Hp = this.$refs.dawa.Hp - 10
                // if(this.$refs.dawa.Hp<=0){
                //     document.getElementById("#mydiv").innerHTML="已经死了不能在死了爹"
                // }
            },
            anwei(){
                console.log("抽了一巴掌,安慰了一下");
                this.$refs.erwa.Hp = this.$refs.erwa.Hp + 10
            },
            xiaodao(){
                this.$refs.erwa.see()            
            },
            bainian(xingming){
                console.log(xingming+"给您拜年了 ");
            }
            
        },
        components:{
            Myheader,
            Myheadererwa

        }

    })

    
</script>
</html>
  • 创建一个公共组件
dart 复制代码
Vue.prototype.$middleBus = new Vue();
  • 发送方,在公共组件上,触发一个事件
dart 复制代码
this.$middleBus.$emit('sendMsg','你好child01,我是child02');
  • 接收方,监听公共组件上的这个事件,并接受数据
dart 复制代码
this.$middleBus.$on('sendMsg',val=>{
     // 使用箭头函数,可以不改变this的指向,仍然和外部的this保持一致,指向child01
     this.msg = val;
});

六,混入(mixin)

  • 定义

    • 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被"混合"进入该组件本身的选项
  • 写法

    • 局部
      • 定义个混入对象
dart 复制代码
var myMixin = {
  data() {
    return {
      mixinname: '混入姓名',
    };
  },
  mounted() {
    console.log('我是混入的组件');
  },
};
  • 项目
dart 复制代码
mixins: [myMixin],
javascript 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        大家好{{changname}}
        <button @click="ouda">打一顿</button>
        <button @click="anwei">安慰</button>
        <button @click="xiaodao">看看导哥在干嘛</button>
        <Myheader ref="dawa"></Myheader>
        <Myheadererwa @to-parent-event="bainian" ref="erwa" age="2" :nengli="nengli2"></Myheadererwa>
        <div id="mydiv"></div>
    </div>
</body>
<script src="../js/vue2.7.js"></script>
<script>
    Vue.prototype.$middleBus = new Vue();

    var commonMixin = {
        data(){
            return{
                mixinName:'葫芦'
            }
        },
        mounted(){
            console.log( "混入对象" +this.mixinName);
        }
    }

    var Myheader = {
        template:`
            <div>
                子组件
                {{xingming}}--{{Hp}}---{{mixinName}}
                <button @click="chuanzhi">发送一条信息</button>    
            </div>
        `,
        
        data(){
            return{
                xingming:'林宇豪',
                Hp:100,
            }
        },
        methods:{
            chuanzhi(){
                this.$middleBus.$emit('jieshou','你好child01,我是child02');
            }
        },
        mixins:[commonMixin]
    }

    var Myheadererwa = {
        template:`
            <div>
                子组件
                {{xingming}}--{{Hp}}
                <button @click="jiao">叫爷爷</button>  
                <button @click="happyNewYear">给爷爷拜年</button>  
                二娃 = {{age}} -- {{nengli}}
            </div>
        `,
        data(){
            return{ 
                xingming:'王导',
                Hp:0,
            }
        },
        methods:{
            see(){
                console.log("再看岛国动作片");
            },
            jiao(){
                this.$parent.name="爷爷"
            },
            happyNewYear(){
                // 触发自定义事件
                this.$emit('to-parent-event',this.xingming)
            }
            
        },
        mounted(){
            this.$middleBus.$on('jieshou',val=>{
                // 使用箭头函数,可以不改变this的指向,仍然和外部的this保持一致,指向child01
                console.log(val);
            });
        },
        props:['age','nengli'],
    }

    var app = new Vue({
        el:'#app',
        data(){
            return{
                changname:'小豪',
                nengli2:"千里眼,顺风耳"
            }
        },

        methods:{
            ouda(){
                console.log("孽子,打一顿");
                this.$refs.dawa.Hp = this.$refs.dawa.Hp - 10
                // if(this.$refs.dawa.Hp<=0){
                //     document.getElementById("#mydiv").innerHTML="已经死了不能在死了爹"
                // }
            },
            anwei(){
                console.log("抽了一巴掌,安慰了一下");
                this.$refs.erwa.Hp = this.$refs.erwa.Hp + 10
            },
            xiaodao(){
                this.$refs.erwa.see()            
            },
            bainian(xingming){
                console.log(xingming+"给您拜年了 ");
            }
            
        },
        components:{
            Myheader,
            Myheadererwa

        }

    })

    
</script>
</html>

全局混入

  • 定义个混入对象
  • 引入使用
dart 复制代码
Vue.mixin(myMixin);

注意

  • 当组件和混入对象含有同名选项时,这些选项将进行"合并"
  • 在选项发生冲突时以组件数据优先
  • 请谨慎使用全局混入,因为会使实例以及每个组件受影响

最后

dart 复制代码
祝大家: 愿每个人都能遵循自己的时钟,做不后悔的选择。
相关推荐
oicola6 小时前
Ant Design v5 vs Tailwind CSS:组件库与样式框架的终极对决
前端·css
溪语流沙6 小时前
【Web全栈进阶】Vue Router + Pinia:SPA路由与全局状态
前端·javascript·vue.js
ManageEngineITSM6 小时前
工单优先级怎么定?影响×紧急度矩阵的设计与落地方法
java·大数据·运维·前端·数据库·变更管理
智商网输送线配件6 小时前
电子制造零散耗材补货实战:小批量混批采购平台怎么选才不停机?
大数据·服务器·前端·数据库·自动化
梦帮科技6 小时前
Web 漏洞攻防深度:WAF 规则逃逸技术(畸形分块传输、双重编码)与对抗加固
linux·前端·网络安全·ssl·web
兰亭妙微UI设计公司7 小时前
兰亭妙微软件界面设计公司的解锁按钮设计10大密码
开发语言·前端·javascript
迪幻7 小时前
封装自己的 npm 依赖并存储到个人 GitHub
前端·npm·github
u0111026757 小时前
WebP 转成 PNG 后为什么更大?图片格式转换不等于压缩
前端·javascript·vue.js
万少7 小时前
Qoder sonus模型 20分钟,复刻 马斯克 飞天汽车
前端·后端·算法
seconp8 小时前
基于Spring Boot和Vue 3的智慧旅游网站:住宿预订、行程规划与千问接入
vue.js·spring boot·毕业设计·软件工程·课程设计·旅游·毕设