组件

为什么使用组件???

  • 组件复用性强,可以更改几个参数等,就可以拿到其他地方用
  • 隔离(拆分),大型项目里,每个人只需要负责一部分,等

定义组件

定义全局组件

  • 使用 实例化的Vue对象调用组件方法component("组件名字" { template : 组件内容})
// 使用全局调用
Vue.component("Counter",{
	template : `
		<div>
			<button>按钮</button>
		</div>
	`
})

定义局部组件

  • 在Vue实例对象中使用components属性,components : { 组件名字 : { template : 组件内容}}
new Vue({
	el : "#app",
	data : {
		
	},
	components : {
		// 注册
		Counter : {
			template : `
				<div>
					<button>按钮</button>
				</div>
			`
		}
	}
})
  • 第二种方法 先声明 后注册
var Counters = {
		template : `
			<div>
				<button>按钮</button>
			</div>
		`
}
new Vue({
	el : "#app",
	data : {
	},
	// 注册组件
	components : { Counters },
})

调用

  • 组件的调用不区分首字符大小写
<Counter></Counter>
<counter></counter>
<Counters></Counters>
<counters></counters>
  • 组件的名字如果中间有大写字母调用时使用-来链接
<Counter-Item></Counter-Item>
<counter-item></counter-item>

组件内的属性,跟vue实例中的属性一样,但是有些是函数形式,有些是跟vue实例一样

  • 组件中有,data(函数),methods,created(函数),props(值可以为数组,对象形式),template,等

组件的参数

  • 在组件中自己定义data属性,但是值是函数 data : function() { return {}} 简写 data() {return {}}
components : {
	Counters : {
		template : `
			<div>
				<button @click="num++">{{num}}</button>
			</div>
		`,
		// 组件定义的参数
		data : function() {
			return {num : 1};
		},
	}
}

组件的传参-父传子

  • 在组件中调用时传递父组件的参数,但是,子组件去接收并且更改这个传递过来的数组
  • 传入使用 :传递数据的中间量的名字="父组件的数据"
  • 接收时:使用 props : ["传递数据的中间量的名字"],这个宽泛
  • 接收时也可用:props : { "传递数据的中间量的名字" : {type : 数据类型,defalut : 默认值}},这个比较严谨
    • 子组件接收父组件的数据,如果直接更改父组件传递过来的数据时会报错,
    • 因为:子组件很多,父组件的数据就一个,如果子组件都去改父组件的数据,会引发混乱
    • 所以父组件的参数,传递是单向的,只读的,尽量避免直接修改父组件数据
    • 为了解决这个问题,可以把传递过来的数据接,收到子组件自己的数据data() {}
    • 在生命周期函数最早能接收数据的阶段开始created() {}
<div id="app">
								<!-- 这里的count就是传递数据的中间量,item就是需要传输的数据 -->
	<Counters v-for="(item,index) in list" :key="index" :count="item"></Counter>
</div>
var Counters = {
		template : `
			<div>
			<!-- 这里就可以直接修改自己的数据了,不用因为直接修改父组件的数据而引发的错误混乱 -->
				<button @click="num++">{{num}}</button>
			</div>
		`,
		data : function() {
				return {num : 1};
			},
			// 接收, 这种不是很严格
			// props : ["count"],
			
			// 接收,设置默认值
			props : {
				"count" : {type : Number,default : 0}
			},
			
			// 子组件接收父组件的数据,如果更改时会报错,
			// 因为:子组件很多,父组件的数据就一个,如果子组件都去改父组件的数据,
			// 会引发混乱
			// 所以父组件的参数,传递是单向的,只读
			// 为了解决这个问题,可以把传递过来的数据接收到子组件自己的数据中
			// 在生命周期函数最早能接收数据的阶段开始created
			created : function() {
				// 在创建结束,挂载最早的阶段,把父组件的参数赋值给子组件自己的数据
				this.num = this.count;
			}
		}
}
new Vue({
	el : "#app",
	data : {
	},
	// 注册组件
	components : { Counters },
})

组件的传参-子传父

  • 子组件想要将自己的数据传递给父组件使用:this.$emit("传递数据的事件名",传递的数据);
  • 在组件上定义传递数据的事件:@传递数据的事件名="触发事件名($event)"$event是子组件传递过来的数据
  • 父组件接收时:因为就是一个事件,所以就可以写在methods里面,写事件方法,把传递过来的数据,再赋值给父组件的数据内
<div id="app">
<!-- @numchange就是传递的事件名 ,numbers就是需要父组件去执行获取子组件传递的数据的方法 ,$event就是子组件传递的数据-->
	<Step :min="20" :max="100" :count="5" @numchange="numbers($event)"></Step>
	<Step></Step>
	<!-- 这里获取父组件的数据显示子组件数据的变化 -->
	<p v-if="numberss">{{numberss}}</p>
</div>
<!-- 目标:当组件的数据放生改变时候,通知父组件 -->
var Step = {
	template : `
		<div class="step">
			<button :disabled="num <= min" @click="cal(-1)">-</button>
			<input type="text" v-model="num" @input="check()">
			<button :disabled="num >= max" @click="cal(+1)">+</button>
		</div>
	`,
	data : function() {
		return {num : 1};
	},
	props : {
		"count" : {type : Number,default : 1},
		"min" : {type : Number,default : 1},
		"max" : {type : Number,default : 999},
		"step" : {type : Number,default : 9},
	},
	created : function() {
		this.num = this.count
	},
	methods : {
		check() {
			if(this.num <= this.min) {
				this.num = this.min;
			}
			if(this.num >= this.max) {
				this.num = this.max
			}
			// 子组件将更改的num数据,发送一个numchange事件,用于父组件接收
			this.$emit("numchange",this.num);
			// 子组件为了传递数据,发送一个numchange方法,将this.num数据,发送给父组件
		},
		cal(type) {
			this.num += this.count*type;
			this.check()
		}
	}
}
new Vue({
	el : "#app",
	// 定义父组件的数据numberss
	data : {numberss : null},
	methods : {
		// 父组件执行触发的子组件的数据的额方法,e就是$event传递过来的数据
		numbers(e) {
			// 把子组件传递过来的数据赋值给父组件上的数据
			this.numberss = e;
		}
	},
	components : {Step},
})

组件插槽-slot

  • 可以进行组件的嵌套

匿名插槽

  • <组件名> <任何标签>内容</任何标签></组件名>,这个任何标签中的内容因为有插槽的存在可以插入到了组件<slot></slot>
  • <slot></slot> 再组件中放入一个这个标签,可以将组件,标签等插入打组件内部
<div id="app">
	<h1>组件插槽</h1>
	// parent是一个组件,
	<Parent>
	// p是 加的内容,可以插入组件内部
		<p>我是组件里面的p</p>
		// parent 还是刚刚的组件,发现组件内部嵌套组件
		<Parent>
			<Parent>
				
			</Parent>
		</Parent>
	</Parent>
</div>
var Parent = {
	template : `
		<div class="parent">
			<p>parent组件里的</p>
			<slot></slot>
			<!-- slot这个标签可以插入内容 -->
		</div>
	`,
}
new Vue({
	el : "#app",
	data : {},
	components : {Parent}
})

具名插槽

  • 将内容插入到对应名字的插槽中
  • <任何标签 slot="名字"></任何标签>,需要传递的内容
  • <slot name="名字"></slot>,将对应的内容插入到与名字对应相等的地方
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
		<style type="text/css">
			* {
				margin: 0;
				padding: 0;
			}
			body {
				padding: 50px;
			}
			.model {
				background-color: rgba(0,0,0,.3);
				position: absolute;
				z-index: 1000;
				height: 100vh;
				width: 100%;
				left: 0;
				right: 0;
				top: 0;
				display: flex;
				align-items: center;
				justify-content: center;
			}
			.model-content {
				width: 400px;
				height: 300px;
				background-color: #fff;
				display: flex;
				flex-direction: column;
			}
			.model-title{
				line-height: 44px;
				background-color: #fafafa;
				display: flex;
				justify-content: space-between;
				padding-left: 15px;
			}
			.close{ width: 44px; text-align: center; color:coral;}
			.model-foot{ height: 44px; padding: 0 15px; text-align: right;}
			.model-body{flex:1}
		</style>
	</head>
	<body>
		<div id="app">
			<h1>具名插槽</h1>
			<button @click="flag = true">弹出</button>
			<Model :title="'你确定要离开吗'" :visible="flag" @close="flag=$event">
				<div slot="foot">
					<button @click="flag = false">取消</button>
					<button @click="flag = false">确定</button>
				</div>
			</Model>
		</div>
	</body>
	<script type="text/javascript">
		var Model = {
			template : `
				<div class="model" v-if="visible">
					<div class="model-content">
						<div class="model-title">
							<div class="title">{{title}}</div>
							<div class="close" @click="$emit('close',false)">×</div>
						</div>
						<div class="model-body">内容</div>
						<div class="model-foot" v-if="$slots.foot">
							<slot name="foot"></slot>
						</div>
						<div class="model-foot" v-else>
							<p @click="$emit('close',false)">确定</p>
						</div>
					</div>
				</div>
			`,
			props : {
				"title" : {type : String,default : ''},
				"visible" : {type : Boolean,default : false}
			}
		}
		new Vue({
			el : "#app",
			data : {
				flag : false
			},
			components : {Model}
		})
	</script>
</html>

组件分离案例—todoList

  • 数据在那个组件那个组件操作数据(尽量)
  • 子组件传递数据,不操作数据
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			
			<Inp @add="add($event)"></Inp>
			<List :list="list" @del="del($event)"></List>
		</div>
	</body>
	<script type="text/javascript">
		var Item = {
			template : `
				<div>
					<input type="checkbox"  :checked="item.done">
					{{item.title}}
					<button @click="$emit('del',item)">删除</button>
				</div>
			`,
			props : {
				"item" : {type : Object,default : {}}
			}
		};
		var List = {
			template : `
				<div>
					<Item 
						v-for="(item,index) in list" 
						:item="item" 
						:key="index"
						@del="$emit('del',$event)"
					></Item>
				</div>
			`,
			props : {
				"list" : {type : Array,default : []},
			},
			components : {Item}
		};
		var Inp = {
			template : `
				<div>
					<input type="text" v-model="temp" @keydown.enter="addHd()" />
				</div>
			`,
			data : function() {
				return {temp : ""}
			},
			methods : {
				addHd() {
					this.$emit("add",this.temp);
					this.temp = '';
				}
			}
		};
		new Vue({
			el : "#app",
			data : {
				list : [
					{done : true,title : "吃饭"},
					{done : true,title : "睡觉"},
					{done : true,title : "打豆豆"}
				]
			},
			components : {List,Inp},
			methods : {
				del(e) {
					var index = this.list.indexOf(e);
					this.list.splice(index,1);
				},
				add(val) {
					this.list.unshift({
						done : false,
						title : val
					})
				}
			}
		})
	</script>
</html>

Logo

前往低代码交流专区

更多推荐