1.全局组件

组件是一个特殊的实例。
全局组件通过Vue.component()方法定义

<div id="app">
	<!-- 组件使用:当自定义标签,真正渲染的是组件的template-->
	<!--dom元素的模版中必须用双标记,不可用单标记,因为有时会出问题-->
	<my-button></my-button>
	<my-button></my-button>
</div>
<script>
	// 全局组件 
	Vue.component("my-button",{
	    // 组件的数据是一个函数原因是为了数据的独立性。,如果是对象,会造成组件间数据的干扰
		data() {
			return {
				msg: "登录"
			}
		},
		template: `
			<button>{{msg}}</button>
		`
	});
	let vm = new Vue({
		el: "#app"
	});
</script>
2.局部组件

局部组件通过Vue实例的components选项定义

<div id="app">
	<my-comp></my-comp>
</div>

let vm = new Vue({
		el: "#app",
		components: {
			"MyComp": { // 组件名 组件本质是一个对象
				data() {
					return {
					}
				}
				template: `
					<div>自定义组件</div>
				`
			}
		}
	});
3.数据校验与组件通信

父传子、数据校验

<div id="app">
	<my-button a="1" b="2" :arr="[1,2,3]"></my-button> <!-- 使用时:小写字母短横线间隔 -->
</div>

<script>
	let vm = new Vue({
		el: "#app",
		data: {
			content: "点我"
		},
		components: {
			"MyButton": { // 大驼峰式命名
				// 父传子,数据不做校验
				// props:["a","b"], // 作为子组件,通过props接收父组件的数据
				
				// 对数据进行校验
				props: {
					a: {
						type: Number,  // 校验类型为数值类型
						// default: 10  // 定义默认值,父组件中没有写a这个属性时起作用
					},
					b: {  // b不做校验
						type: String,
						Validator(val) { // 对传的值进行 校验
							return val>0; 
						} // 返回true时,没有问题,返回false时,会报错
					},
					arr: { // 当传的值是数组时,用对象
							type: Array,
							default:()=>{[1]} // 当值是对象或数组时,default默认值要通过函数返回
					}
				},
				template: `
					<button>{{a}}{{b}}{{arr}}</button> // 在子组件中使用父组件的数据
				`
			}
		}
	});
</script>

父传子 — 给组件绑定原生事件

<div id="app">
	<!-- 想在父组件中绑定原生事件给子组件,需要加.native,不加就被当作一个属性。
	.native使事件绑定到组件模版的根元素上-->
	<my-button @click.native="fn"></my-button>   
</div>

<script>
	let vm = new Vue({
		el: "#app",
		data: {
			content: "点我"
		},
		methods: {
			fn() {
				console.log("fn()被调用了");
			}
		},
		components: {
			"MyButton": { // 大驼峰式命名
				template: `
					<button>点我</button>
				`
			}
		}
	});
</script>

子传父

<div id="app">
	<my-button @click="fn" @mouseup="fn"></my-button>   
</div>
<script>
	let vm = new Vue({
		el: "#app",
		data: {
			content: "点我"
		},
		methods: {
			fn(num) {
				console.log(num,"fn()被调用了");
			}
		},
		components: {
			"MyButton": { 
				mounted() {
					// 绑定所有的方法
					console.log(this.$listeners); //  存储的是父组件的@click属性的值,就是一个函数 {click: f}
				}
				template: `
					<button @click="$listeners.click(123);">点我</button>
					<button @click="$listeners.click(123);" @mouseup="$listeners.mouseup(123)">点我</button>
					<button @click="$emit('click',23)">点我</button> // 直接触发父亲的事件
				`
			}
		}
	});
</script>

组件通信手段:

  • props
  • $emit
  • $attrs
  • $listeners
常用的组件通信总结

父传子: 子组件添加props

子传父:

  • 在子组件中调用$emit()方法发布一个事件
  • 在父组件中提供一个在子组件内部发布的事件处理函数
  • 在父组件订阅子组件内部发布的事件