08: vue组件
1.1 初识组件
1、什么是组件
1. Html中有组件,是一段可以被复用的结构代码
2. Css中有组件,是一段可以被复用的样式
3. Js中有组件,是一段可以被复用的功能
4. Vue中也有组件,指的就是一个模块,是一个独立的,完整的(包含html,css,js等),可以直接拿来用的
2、使用组件分成三步
1、第一步 定义组件容器(定义自定义元素)
2、第二步 定义组件Vue.extend方法
1. 参数是组件对象,对象属性跟vue实例化时候传递的参数对象的属性是一样的,例如 data,methods,computed
2. 在vue实例化时候,data属性的属性值是一个对象,在组件中,data属性值是一个函数,返回值是一个对象
3. 组件中,可以通过template定义模板,通常模板写在一个根元素内
3、第三步 将组件注册到页面中 Vue.component
第一个参数表示容器元素的名称
第二个参数表示组件类
3、组件特性
1. 组件的实例化对象,跟vue实例化对象一样,因此,我们也可以将vue实例化对象看成组件
2. 组件间是独立的,因此数据要独立存储,方法要独立定义,彼此间不能共享。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Title</title> </head> <body> <div id="app"> <Home></Home> </div> <script src="vue.js"></script> <script> var Home = Vue.extend({ template:"<h1>I am h1!! 显示变量: {{msg}}</h1>", data:function () { return { 'msg':'I am msg' } } }); Vue.component('home',Home); var app = new Vue({ el:'#app', data:{} }) </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <div id="app"> <input type="text" v-model="msg"> <h1 v-on:click="clickH1">{{msg}}</h1> <!-- 第一步 定义容器元素 --> <ickt></ickt> </div> <script type="text/javascript" src="vue.js"></script> <script type="text/javascript"> // 第二步 定义组件类 var Ickt = Vue.extend({ template: '<div><input type="text" v-model="msg" /><h1 v-on:click="clickH1">{{msg}}</h1></div>', // 定义模板 data: function() { // 绑定数据 return { msg: 'ickt' // 返回值才是真正绑定的数据 } }, methods: { // 定义方法 clickH1: function() { console.log(222, this) } } }); // 第三步 注册组件 Vue.component('ickt', Ickt); // vue实例化对象 var app = new Vue({ el: '#app', data: { msg: 'hello' }, methods: { // 定义方法 clickH1: function() { console.log(111) } } }) </script> </body> </html>
1.2 父组件向子组件间的通信
1、组件间的通信说明
1. 组件间通信就是指组件之间是如何传递数据的
父组件:vue实例化对象
子组件:自定义组件
2. 组件的tempalte属性,除了可以是字符串,还可以是元素的id
3. 我们在页面中定义模板的时候,除了可以定义在script模板标签中,还可以定义在template模板中
父组件子组件:如果你在一个组件A里面,用到了另外一个组件B,那么B就是A的子组件,A就是B的父组件
2、父组件向子组件通信:分为以下两步
1. 第一步
1. 在组件容器元素上,定义自定义属性,属性值可以传递父组件中的数据
2. 如果属性使用了v-bind指令,属性值就是js环境
3. 如果属性没有使用v-bind指令,属性值就是字符串
<ickt demo="hello" v-bind:parent-msg="msg"></ickt> # hello 是字符串, msg是变量
2. 第二步
1. 在组件中定义props属性,属性值是数组,每一个成员代表组件容器元素上的一个属性
2. 作用:将属性作为变量,注册在子组件中,可以在子组件中使用(包括模板)
3. 注意: 如果属性名称,出现了-, 注册的变量要使用驼峰式命名法
3、例子说明
1. 在当页面中注册了子组件:Ickt,在子组件中是无法使用父组件中定义的数据 msg 的
2. 如果想要在子组件Ickt中使用父组件的 msg 变量,可以使用 <ickt v-bind:parent-msg="msg"></ickt>
3. 在子组件中 使用{{parent-msg}} 就可以访问父组件的msg变量了
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <div id="app"> <input type="text" v-model="msg"> <h1 @click="clickH1">vue:{{msg}}</h1> <!-- 1 容器 第一步 绑定属性 demo 没有使用v-bind所以是字符串 --> <ickt demo="hello" v-bind:parentmsg="msg"></ickt> </div> <template id="tpl"> <div> <input type="text" v-model="childMsg"> <h1 @click="clickChildH1">demo: {{childMsg}}</h1> <h2>{{demo}}</h2> <!-- demo 是父组件中的字符串 --> <h3>{{parentmsg}}</h3> <!-- parentmsg 是父组件中的变量 --> </div> </template> <script type="text/javascript" src="vue.js"></script> <script type="text/javascript"> // 2 组件类 var Ickt = Vue.extend({ // 第二步 注册属性变量 props: ['demo', 'parentmsg'], template: '#tpl', data: function() { // 绑定数据 return { childMsg: '' } }, methods: { // 绑定事件 clickChildH1: function() { console.log(222) } } }); // 3 注册 Vue.component('ickt', Ickt); // 创建vue实例化对象: 父组件 var app = new Vue({ el: '#app', data: { msg: '' }, methods: { // 定义方法 clickH1: function() { console.log(1111) } } }) </script> </body> </html>
1.3 子组件向父组件通信
1、1.0中子组件向父组件通信分以下两步
1. 第一步:注册事件
在父组件的events属性中 注册消息,参数就是触发是传递的数据,作用域是组件实例化对象
2.第二步:触发事件
在子组件中,通过$dispatch方法触发消息
2、2.0中改变
1. 将$dispatch, $broadcast 移除了,新增了$emit, $on, $off
$emit发布消息
$on 注册消息: 参数就是$emit传递的数据,作用域就是组件实例化对象
$off 注销消息
2. 每一个组件相当于一个事件对象,只能在自身订阅,触发,以及发布
3. 注意:工作中,注册事件通常在组件生命周期方法中注册,例如created
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <div id="app"> <input type="text" v-model="msg"> <h1 @click="clickH1">vue:{{msg}}</h1> <!-- 1 容器 第一步 绑定属性 --> <ickt demo="hello" v-bind:parent-msg="msg"></ickt> </div> <template id="tpl"> <div> <input type="text" v-model="childMsg"> <h1 @click="clickChildH1">demo: {{childMsg}}</h1> <h2>{{demo}}</h2> <h3>{{parentMsg}}</h3> </div> </template> <script type="text/javascript" src="vue.js"></script> <script type="text/javascript"> // 2 组件类 var Ickt = Vue.extend({ props: ['demo', 'parentMsg'], // 第二步 注册属性变量 template: '#tpl', data: function() { // 绑定数据 return { childMsg: '' } }, methods: { // 绑定事件 clickChildH1: function() { this.$parent.$emit('icktmsg', 'hello', 'everyone') //2、触发消息 } } }); // 3 注册 Vue.component('ickt', Ickt); var app = new Vue({ // 创建vue实例化对象: 父组件 el: '#app', data: { msg: '' }, methods: { // 定义方法 clickH1: function() { this.$on('icktmsg', function() { //1、注册消息 console.log(arguments, this) }) } } }) </script> </body> </html>
1.4 组件的生命周期
1、说明
1. Vue将组件看成是一个有生命的个体,跟人一样,定义了各个阶段,
2. 组件的生命周期:组件的创建过程
3. 组件生命周期钩子函数:当组件处在某个阶段,要执行某个方法,来通知我们,组件进入某个阶段,这个方法就是组件生命周期的钩子函数
4. 组件的创建过程:这些方法在组件中直接定义,会按照顺序执行,没有参数,作用域都是组件实例化对象
2、组件生命周期中依次执行的八个钩子函数
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Title</title> </head> <body> <div id="app"> <Home></Home> </div> <script src="vue.js"></script> <script> var Home = Vue.extend({ template:"<h1>I am h1!! 显示变量: {{msg}}</h1>", data:function () { return { 'msg':'I am msg' } }, // 方法1:组件实例被创建,组件属性计算之前,如data属性等 beforeCreate: function () { console.log(111, this, arguments) }, // 方法2:组件实例创建完成,属性已经绑定,但DOM还未生成,$el 属性还不存在 created: function () { console.log(222, this, arguments) }, // 方法3:模板编译/挂载之前 beforeMount: function () { console.log(333, this, arguments) }, // 方法4:模板编译/挂载之后(不保证组件已在document中) mounted: function () { console.log(444, this, arguments) }, // 方法5:组件更新之前 beforeUpdate: function () { console.log(555, this, arguments) }, // 方法6:组件更新之后 updated: function () { console.log(666, this, arguments) }, // 方法9:组件销毁前调用 beforeDestory: function () { console.log(777, this, arguments) }, // 方法10:主键销毁后调用 destoryed: function () { console.log(888, this, arguments) }, // 方法7:组件被激活时调用(用的少) // activated: function() { // console.log(777, this, arguments) // }, // 方法8:组件被移除时调用(用的少) // deactivated: function () { // console.log(888, this, arguments) // }, }); Vue.component('home',Home); var app = new Vue({ el:'#app', data:{ 'isShow':true, } }) </script> </body> </html>
3、图片展示
4、组件生命周期 常用的两个过程
1)created: 实例已经创建完成,并且已经进行数据观测和事件配置
2)mounted:模板编译之后,已经挂载,此时才会渲染页面,才能看到页面上数据的展示
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Vue生命周期</title> <script src="js/vue.js"></script> <script> window.onload=function(){ let vm=new Vue({ el:'#itany', data:{ msg:'welcome to itany' }, methods:{ update(){ this.msg='欢迎来到南京网博!'; }, destroy(){ // this.$destroy(); vm.$destroy(); } }, beforeCreate(){ alert('组件实例刚刚创建,还未进行数据观测和事件配置'); }, created(){ //常用!!! alert('实例已经创建完成,并且已经进行数据观测和事件配置'); }, beforeMount(){ alert('模板编译之前,还没挂载'); }, mounted(){ //常用!!! alert('模板编译之后,已经挂载,此时才会渲染页面,才能看到页面上数据的展示'); }, beforeUpdate(){ alert('组件更新之前'); }, updated(){ alert('组件更新之后'); }, beforeDestroy(){ alert('组件销毁之前'); }, destroyed(){ alert('组件销毁之后'); } }); } </script> </head> <body> <div id="itany"> {{msg}} <br> <button @click="update">更新数据</button> <button @click="destroy">销毁组件</button> </div> </body> </html>
作者:学无止境
出处:https://www.cnblogs.com/xiaonq
生活不只是眼前的苟且,还有诗和远方。