Vue组件使用

在大型应用开发的时候,页面可以划分成很多部分。往往不同的页面,也会有相同的部分。例如可能会有相同的头部导航。
但是如果每个页面都独自开发,这无疑增加了开发的成本。所以会把页面的不同部分拆分成独立的组件,然后在不同页面就可以共享这些组件,避免重复开发。

1、组件也是一个Vue实例,因此它在定义时也会接收:data、methods、生命周期函数等
2、不同的是组件不会与页面的元素绑定,否则就无法复用了,因此没有el属性。
3、但是组件渲染需要html模板,所以增加了template属性,值就是HTML模板。
4、data的定义方式比较特殊,必须是一个函数。

组件的复用:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>组件化</title>
    <script src="../assets/vue-2.6.12/dist/vue.js"></script>
</head>
<body>
<div id="app">
    <!--组件复用-->
    <counter></counter>
    <counter></counter>
    <counter></counter>
</div>
<script>
    //定义组件
    const counter1 = {
        template:"<button @click='num++'>你点击了{{num}}次</button>",
        data(){
            return { 
				num:0
 			}
        }
    }
    var app = new Vue({
        el:"#app",
        //局部注册组件
        components:{
            counter: counter1
        }
    });
</script>
</body>
</html>

效果图:
在这里插入图片描述

你会发现每个组件互不干扰,都有自己的值。这是怎么实现的?
因为组件的data属性必须是函数!
当定义组件时,它的data 并不是像这样直接提供一个对象:

data: {
 	num: 0
}

取而代之的是,一个组件的data选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝:

data: function () {
 	return {
  		num: 0
	}
}

如果 Vue 没有这条规则,点击一个按钮就会影响到其它所有实例!

组件局部注册:
一旦全局注册,就意味着即便不使用这个组件时,它依然会随着Vue的加载而加载。
因此,对于一些并不频繁使用的组件,会采用局部注册。

<div id="app">
	<!--使用定义好的全局组件-->
  	<counter></counter>
 	<counter></counter>
 	<counter></counter>
</div>
<script>
//定义组件
const counter = {
	template: "<button @click='num++'>你点击了{{num}}次;我记住了</button>",
	data(){
		return {num: 0}
	}
};

var app = new Vue({
	el:"#app",
	//局部注册组件
	components:{
		//counter: counter
		//组件名称与定义组件对象名称一致可简写为:
		counter
	}
});
</script>

components就是当前vue对象子组件集合,key就是子组件名称,值就是组件对象属性。
注意:局部注册的组件只能在当前的Vue实例中使用,比如加上

<div id="app111">
	<counter></counter>
</div>

该div是无法使用该组件的(不会报错),但如果还想实例化这个Vue实例,就必须注册组件 或 把没定义的组件删掉,不然会引起报错!如:

var app1 = new Vue({
    el:"#app1"
});

在这里插入图片描述

正确写法:

var app1 = new Vue({
    el:"#app1",
    //局部注册组件
    components:{
        counter: counter1
    }
});

组件全局注册:
全局组件定义完毕,任何vue实例都可以直接在HTML中通过组件名称来使用组件了。
比如刚刚的代码,当用了全局注册组件就不用每个vue实例都去注册了

<div id="app">
    <counter></counter>
    <counter></counter>
    <counter></counter>
</div>
<br>
<div id="app1">
    <counter></counter>
    <counter></counter>
    <counter></counter>
</div>
<script>
    //定义组件
    const counter1 = {
        template:"<button @click='num++'>你点击了{{num}}次</button>",
        data(){
            return {num:0}
        }
    }

    //全局注册组件:在所有的vue实例中都可以使用组件
    //参数1:组件名称,参数2:具体的组件
    Vue.component("counter", counter1);

    var app = new Vue({
        el:"#app",
        /*components:{
            counter: counter1
        }*/    
});

    var app1 = new Vue({
        el:"#app1",
    });
</script>

效果图:
在这里插入图片描述

同理我们可以利用全局注册组件,对组件进行封装,以达到在不同页面使用该组件的效果。
定义一个名为components的js文件,在里面写需要封装的组件

//定义组件
const counter1 = {
    template:"<button @click='num++'>你点击了{{num}}次</button>",
    data(){
        return {num:0}
    }
}
//全局注册组件
Vue.component("counter", counter1);

需要使用时,引进该js并把使用了该组件的vue实例实例化后即可使用:

<!DOCTYPE html>
<head>
    <meta charset="UTF-8">
    <script src="../assets/vue-2.6.12/dist/vue.js"></script>
    <script src="../assets/js/components.js"></script>
</head>
<body>
<div id="app">
    <counter></counter>
    <counter></counter>
    <counter></counter>
</div>
<div id="app1">
    <counter></counter>
    <counter></counter>
    <counter></counter>
</div>
<script>
    var app = new Vue({
        el:"#app"
    });

    var app1 = new Vue({
        el:"#app1",
    });
</script>
</body>
</html>

组件通信:
各个组件之间以嵌套的关系组合在一起,那么这个时候不可避免的会有组件间通信的需求。

1、父组件向子组件通信:

比如有一个子组件

Vue.component("introduce",{
	// 直接使用props接收到的属性来渲染页面
	template:'<h3>{{title}}</h3>',
	props:[title] // 通过props来接收一个父组件传递的属性
})

这个子组件中要使用title属性渲染页面,但是自己并没有title属性
通过props来接收父组件属性,名为title

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>父组件向子组件通信</title>
    <script src="../assets/vue-2.6.12/dist/vue.js"></script>
</head>
<body>
<div id="app">
    <!--使用组件-->
    <introduce :title="mag"></introduce>
</div>
<script>
    //定义组件
    const introduce1 = {
		//使用props属性title的值渲染模版
        template:"<h2>{{title}}</h2>",
        //定义接收父组件的属性
        props:['title'],
    }
    //全局注册组件:参数1:组件名称,参数2:组件
    Vue.component("introduce", introduce1);

    var app = new Vue({
        el:"#app",
        data:{
            mag:"父组件的msg属性数据内容"
        }
    });
</script>
</body>
</html>

效果图:
在这里插入图片描述

也可以传递一些复杂的数据,如数组对象等:

定义一个子组件可以对 items 进行迭代,并输出到页面,但是组件中并未定义items属性,通过props来定义需要从父组件中接收的属性

items:是要接收的属性名称
type:限定父组件传递来数据类型;type的值可以是Array或者Object(传递对象的
时候使用)
default:默认值,

<div id="app">
    <!--使用组件(不能写成myList因为有大写字母需改成小写并在它前面加-)-->
    <my-list :items="lessons"></my-list>
</div>
<script>
//定义组件
const myList = {
	//可以使用双引号、单引号或者如下使用的 ` 飘号
    template:`
       	<ul>
          	<li v-for="item in items" :key="item.id">{{item.id}}--{{item.name}}</li>
      	</ul>
      	`,
      	//定义接收父组件的属性
    	props: {
		//定义模版中使用的属性
        items:{
            type:Array,//数据类型,如果是数组则是Array,如果是对象则是Object
            default:[],//默认值
            //default(){return[];}
        }
    }
}

var app = new Vue({
    el:"#app",
    data:{
        mag:"父组件的msg属性数据内容",
        lessons:[
            {"id":1,"name":"Java"},
            {"id":2,"name":"C#"},
            {"id":3,"name":"C++"},
        ],
    },
    //局部注册组件
    components:{
        myList
    }
});
</script>

效果图:
在这里插入图片描述

2、子组件向父组件通信:

<div id="app">
    <h2>num = {{num}}</h2>
    <!--点击按钮是在子组件中,那就是说需要子组件来调用父组件的函数;可以通过v-on指令(简写'@')将父组件的函数绑定到子组件上-->
    <counters @plus="numPlus" @reduce="numReduce"></counters>
</div>
<script>
    //定义组件
    const counter2 = {
        //可以使用双引号、单引号或者如下使用的 ` 飘号
        //组件只能是一个元素里面包裹其他元素;如下面,一个div包含两个按钮
        template:`
            <div>
                <button @click='incrNum'>+</button>
                <button @click='decrNum'>-</button>
            </div>
        `,
        methods: {
            //点击按钮调用自身点击事件,递增
            incrNum(){
                return this.$emit("plus");//调用到父组件的方法
            },
            //递减
            decrNum(){
                return this.$emit("reduce");
            },
        }
    }
    var app = new Vue({
        el:"#app",
        components:{ counters: counter2 },//局部注册组件
        data:{ num:0 },
        methods:{
            //父组件中定义操作num的方法
            numPlus(){
                this.num++;
            },
            numReduce(){
                this.num--;
            }
        }
    });
</script>

效果图:
在这里插入图片描述

总结:
组件通信意义:父子组件之间数据的交换,能够及时更新组件内容。
父向子传递:子组件使用props属性来定义需要从父组件中接收的数据。
子向父传递:子组件使用$emit来调用父组件的方法。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值