定义

为了拆分vue实例的代码量,能够让我们以不同的组件,来划分不同的功能模块,将来需要功能,就可以去调用对应的组件;

组件化和模块化的区别:
1、模块化:是从代码逻辑的角度进行划分的;
2、组件化:是从UI界面的角度进行划分的;方便ui组件的重用;

方式1

使用过程:

  1. 使用vue.extend 来创建全局的vue组件(通过template属性,指定了组件要展示的html结构)
  2. 使用vue.component(‘组件的名称’,创建出来的组件模板对象)
  3. 使用组件,以html标签的的形式,引入到页面中(如果模板的命名为驼峰方式,在使用时需要修改为-连接;如myCom my-com);
<body>
	<div class = "app ">
		<m_com></m_com>
	</div>
</body>

<script type="text/javascript">
	var com1 = Vue.extend({
		template:'<h3>h3模板组件</h3>'
	})
	Vue.component('m_com',com1);

	var vm = new Vue({
		el:'.app'
	})
</script>

同样可以将定义的两步合并:

	Vue.component('m_com',Vue.extend({
		template:'<h3>h3模板组件</h3>'
	}));
	//第一个参数,引用的标签的名称
	//第二个参数,创建的组件,

方式2

以上形式的缩略:

Vue.component('m_com',{
	template:'<h3>h3模板组件</h3>'
});

注意:
根元素必须只有一个:

Vue.component('m_com',{
	template:'<div><h3>h3模板组件</h3><h2>h2</h2></div>'
});

最外层的div如果舍弃的话,将会报错

方式3

在被控制的app的外面 使用template元素,定义组件的模板结构

<body>
	<div class = "app ">
		<m_com></m_com>
	</div>
	<template id="temp1">
		<div>
			<h1>外围定义的组件结构</h1>
			<h2>可以使用</h2>
		</div>
	</template>

</body>

<script type="text/javascript">
	Vue.component('m_com',{
		template:'#temp1'
	});
	var vm = new Vue({
		el:'.app'
	})
</script>

私有组件

在vue实例内部定义私有组件

	var vm = new Vue({
		el:'.app',
		components:{
			//定义实例内部私有组件
			com4:{
				template:'<h1>私有组件</h1>'
			}
		}
	})

template的值同样也可以是在app实例外部的template标签的id。

组件中的数据

  1. 组件可以有自己的data数据
  2. 组件中的data不能为对象,必须为一个方法
  3. 组件中的data必须返回一个对象
  4. 组件中的数据使用方式和实例中的一样
<body>
	<div class = "app ">
		<m_com></m_com>
	</div>
	<template id="temp1">
		<div>
			<h1>外围定义的组件结构</h1>
			<h2>{{msg}}</h2>
		</div>
	</template>
</body>

<script type="text/javascript">
	Vue.component('m_com',{
		template:'#temp1',
		data:function(){
			return {
				msg:"组件中的data"
			}
		}
	});
	var vm = new Vue({
		el:'.app',
	})
</script>

data中数据为了不影响其他组件使用的对象数据,所以将数据以函数返回对象的方式实现。
例如计数组件:

	<template id="count">
		<div>
			<input type="button" value="+1" @click="increace" name="">
			<h2>{{count}}</h2>
		</div>
	</template>


<script type="text/javascript">
	Vue.component('counter',{
		template:"#count",
		data:function(){
			return {
				count:"0"
			}
		},
		methods:{
			increace(){
				this.count++;	
			}
		}
	})
</script>

组件切换

v-if和v-else


<body>
	<div class = "app ">
		<a href="" @click.prevent="flag=true">登录</a>
		<a href="" @click.prevent="flag=false">注册</a>
		<login v-if="flag"></login>
		<register v-else="flag"></register>
	</div>

	<template id="login">
		<div>
			<h1>登录</h1>
		</div>
	</template>

	<template id="register">
		<div>
			<h2>注册</h2>
		</div>
	</template>
</body>

<script type="text/javascript">
	Vue.component('login',{
		template:'#login',
		data:function(){
			return {
			}
		}
	});

	Vue.component('register',{
		template:"#register",
		data:function(){
			return {
			}
		}
	})

	var vm = new Vue({
		el:'.app',
		data:{
			flag:true,
		}

	})
</script>

在这里插入图片描述

component标签

  1. vue提供的component元素,展示对应名称的组件;
  2. component是一个占位符,:is属性为要展示的组件的名称

<body>
	<div class = "app ">
		<a href="" @click.prevent="comName='login'">登录</a>
		<a href="" @click.prevent="comName='register'">注册</a>
		<component :is="comName"></component>
	</div>

	<template id="login">
		<div>
			<h1>登录</h1>
		</div>
	</template>

	<template id="register">
		<div>
			<h2>注册</h2>
		</div>
	</template>
</body>

<script type="text/javascript">
	Vue.component('login',{
		template:'#login'
	});

	Vue.component('register',{
		template:"#register"
	})

	var vm = new Vue({
		el:'.app',
		data:{
			comName:"login",
		}
	})
</script>

切换的动画

通过component的mode属性设置组件的切换的模式

<style type="text/css">
	.v-enter,
	.v-leave-to{
		opacity:0;
		transform:translateX(150px);
	}

	.v-enter-active,
	.v-leave-active{
		transition:all 0.5s ease;
	}
</style>

<transition mode="out-in">
	<component :is="comName"></component>
</transition>

组件父子数据传递

  1. 默认vue实例中定义的私有组件中,无法访问vue实例data中的数据和methods
  2. 父组件通过属性绑定的方式,把数据传递给子组件;
  3. 需要在子组件props中把父组件传递的属性先定义一遍,才能使用(最好不用大写),props里面的数据都是父中传递的
  4. 子组件data是子组件私有的数据,可读可写
  5. props中的数据只能读
<body >
	<div class = "app ">
		<com1 v-bind:parentmsg="msg"></com1>
	</div>
	<template id="forcom1">
		<h1>子组件:{{parentmsg}}</h1>
	</template>
</body>
<script type="text/javascript">
	var vm = new Vue({
		el:'.app',
		data:{
			msg:"父中的数据",
		},
		components:{
			com1:{
				data(){
					return{
						msg:"123"
					}
				},
				template:"#forcom1",
				// template:'<h1>子组件:{{parentmsg}}</h1>',
				props:['parentmsg'],
				methods:{}
			}
		}
	})
</script>

父组件传递方法

  1. 父组件传递方法,使用v-on:的方式绑定(也可简写@)
  2. 子组件通过$emit()出发父传递的方法
  3. $emit()方法的第一个参数为父组件绑定的名称,之后的参数为传递给函数的参数;
  4. 子组件可以通过传参的方式向父组件传递数据;
<body >
	<div class = "app ">
		<com1 v-on:parentfunc="show"></com1>
	</div>
	<template id="forcom1">
		<input type="button" value="show" @click="click" name="">
	</template>
</body>
<script type="text/javascript">
	var vm = new Vue({
		el:'.app',
		data:{
			msg:"父中的数据",
			sonData:{}
		},
		methods:{
			show(msg,data){
				console.log("父组件的函数" + msg);
				this.sonData = data;
				console.log(this.sonData);
			}
		},
		components:{
			com1:{
				data(){
					return {
						name:"Tom",
						id:1,
						ability:{
							des:10,
							life:100
						}
					}
				},
				template:"#forcom1",
				methods:{
					click(){
						this.$emit('parentfunc',123,this.ability);
					}
				}
			}
		}
	})
</script>

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

组件练习

<link rel="stylesheet" type="text/css" href="./bootstrap.css">
<body >
	<div class = "app ">
		<com1 v-on:parentfunc="load"></com1>
		<ul class="list-group" v-for="(item,index) in list" :key="item.id">
			<li class="list-group-item">
				<span class="badge">评论人:{{item.user}}</span>
				{{item.content}}
			</li>
		</ul>

	</div>

	<template id="forcom1">
		<div>
			<div class="form-group">
				<label>评论人:</label>
				<input type="text" class="form-control" name="" v-model="user">
			</div>
			<div class="form-group">
				<label>评论内容:</label>
				<textarea class="form-control" v-model="content"></textarea>
			</div>
			<div class="form-group">
				<input type="button" name="" value="发表评论" class="btn btn-primary" @click="click">
			</div>
		</div>
	</template>

</body>
<script type="text/javascript">
	var vm = new Vue({
		el:'.app',
		data:{
			list:[
				{id:Date.now()+1,user:'Trump',content:'fake news'},
				{id:Date.now()+2,user:'Biden',content:'please,emm'},
				{id:Date.now()+3,user:'King',content:'i have a dream'},
			]
		},
		methods:{
			load(){
				var list = JSON.parse(localStorage.getItem('cmts') || '[]');
				this.list = list;
			}
		},
		components:{
			com1:{
				data(){
					return {
						user:"",
						content:""
					}
				},
				template:"#forcom1",
				methods:{
					click(){
						var newContent = {id:Date.now(),user:this.user,content:this.content};
						var list = JSON.parse(localStorage.getItem('cmts') || '[]');
						list.unshift(newContent);
						localStorage.setItem('cmts',JSON.stringify(list));
						this.user = this.content = "";
						this.$emit('parentfunc');
					}
				}
			}
		},
		created(){
			this.load();
		}
	})
</script>

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

获取Dom元素

可通过引用获取dom元素,为标签的ref属性赋值string,通过$refs.string获取对应的标签dom;

<body >
	<div class = "app ">
		<com1 ref="com1t"></com1>
		<input type="button" value="get" @click="getEle" name="">
		<h1  ref="myh1">h1标签</h1>
	</div>
	<template id="forcom1">
		<input type="button" value="show" name="">
	</template>
</body>
<script type="text/javascript">
	var vm = new Vue({
		el:'.app',
		data:{
		},
		methods:{
			getEle(){
				console.log(this.$refs.myh1.innerText);
				console.log(this.$refs.com1t.name);
				this.$refs.com1t.hello();
			}
		},
		components:{
			com1:{
				data(){
					return {
						name:"tom"
					}
				},
				methods:{
					hello(){
						console.log("hello")
					}
				},
				template:"#forcom1",
			}
		}
	})
</script>

同样也可以通过ref属性获取组件,并访问组件中的数据及方法。

文化建设

题金陵渡
金陵津渡小山楼
一宿行人自可愁
潮落夜江斜月里
两三星火是瓜洲
Logo

基于 Vue 的企业级 UI 组件库和中后台系统解决方案,为数万开发者服务。

更多推荐