vue组件化开发
1.什么是组件化开发?
组件(Component)是自定义封装的功能。在前端开发过程中,经常出现多个网页的功能是重复的,而且很多不同的网站之间,也存在同样的功能。
而在网页中实现一个功能,需要使用html定义功能的内容结构,使用css声明功能的外观样式,还要使用js来定义功能的特效,因此就产生了把一个功能相关的[HTML、css和javascript]代码封装在一起组成一个整体的代码块封装模式,我们称之为“组件”。
所以,组件就是一个html网页中的功能,一般就是一个标签,标签中有自己的html内容结构,css样式和js特效。
这样,前端人员就可以在开发时,只需要书写一次代码,随处引入即可使用。
我们在进行vue开发的时候,还记得我们自己创建的vm对象吗,这个vm对象我们称为一个大组件,根组件(页面上叫Root),在一个网页的开发中,根据网页上的功能区域我们又可以细分成其他组件,或称为子组件
组件有两种:默认组件[全局组件] 和 单文件组件[局部组件]
局部组件 :
注意:每个组件中的template对应的标签,都必须有一个外层标签包裹
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>todolist</title> </head> <body> <div id="app"> <!-- 3.使用子组件 用子 --> <!-- <xx></xx>--> <!-- <xx2></xx2>--> <Vheader></Vheader> <xxx></xxx> <Kk></Kk> <!-- content header footer aside section nav H5有一些新标签,注意,组件名称尽量不要和标签名称冲突 --> </div> </body> <script src="vue.js"></script> <script src="axios.js"></script> <script> // 组件化开发(将页面的每块功能,单独封装为一个组件,哪个页面用哪些组件,就直接拿到这几个组件,拼到页面上展示) // 1.声明子组件 声子 let Vheader = { data(){ return { nav_list:['个人中心','登录','注册'] } }, template:'<h1>{{nav_list}}</h1>', }; let xxx = { data(){ return { content_list:['xxx','ooo',] } }, template:'<h1 style="color:red;">{{content_list}}</h1>', }; // 全局组件 不需要挂载,直接使用 Vue.component('Kk',{ data(){ return { name:'全局组件!!!' } }, template:'<h1 style="color:tan;">{{name}}</h1>', }) let vm = new Vue({ el:'#app', data(){ return { data:'', } }, created(){ }, components:{ Vheader, //2.挂载子组件 挂子 // Content:Content, xxx, // 键和值相同,就可以简写 } }) </script> </html>
全局组件
局部组件使用时需要挂载,全局组件使用时不需要挂载。那么他们两个什么时候用呢,局部组件就在某个局部使用的时候,全局组件是大家公用的,或者说每个页面都有这么一个功能的时候,在哪里可能都会用到的时候。
<div id="app"> <Kk></Kk> </div> <script> // 全局组件 不需要挂载,直接使用 Vue.component('Kk',{ data(){ return { name:'全局组件!!!' } }, template:'<h1 style="color:tan;">{{name}}</h1>', }) var vm = new Vue({ el:"#app", data:{ } }) </script>
2.组件传值
通过prop属性进行传值,父组件往子组件传值分为2步.
1.父组件在使用子组件时要定义自定义的属性:比如:<Vheader :ff="num"></Vheader>
动态传值
静态传值:<Vheader ff="123"></Vheader>
2.在子组件中使用props属性声明:比如:props:['ff', ],然后子组件就可以将ff作为一个数据属性来使用了,比如:
template:`<div> <h1>{{nav_list}}</h1> <h2>{{nav_list}}</h2> <h4 style="color:green;">{{ff}}</h4> </div>`,
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>todolist</title> </head> <body> <div id="app"> <!-- 3.使用子组件 用子 --> <!-- <xx></xx>--> <!-- <xx2></xx2>--> <App></App> <!-- content header footer aside section nav H5有一些新标签,注意,组件名称尽量不要和标签名称冲突 --> </div> </body> <script src="vue.js"></script> <script src="axios.js"></script> <script> // 父组件往子组件传值: let Vheader = { data(){ return { nav_list:['个人中心','登录','注册','username'] } }, template:`<div> <h1>{{nav_list}}</h1> <h2>{{nav_list}}</h2> <h4 style="color:green;">{{ff}}</h4> </div>`, props:['ff', ], }; let xxx = { data(){ return { content_list:['xxx','ooo',] } }, template:'<h1 style="color:red;">{{content_list}}</h1>', }; let App = { data(){ return { 'xxx':'ooo', num:1000, } }, // <Vheader ff="123"></Vheader> 静态传值 template: ` <div class="app"> <Vheader :ff="num"></Vheader> <xxx></xxx> </div> `, components: { Vheader, xxx, } } let vm = new Vue({ el:'#app', components:{ App, } }) </script> </html>
注意点:
使用父组件传递数据给子组件时, 注意一下几点:
-
传递数据是变量,则需要在属性左边添加冒号.
传递数据是变量,这种数据称之为"动态数据传递"
传递数据不是变量,这种数据称之为"静态数据传递"
-
父组件中修改了数据,在子组件中会被同步修改,但是,子组件中的数据修改了,是不是影响到父组件中的数据.
这种情况,在开发时,也被称为"单向数据流"
示例代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>todolist</title> </head> <body> <div id="app"> <!-- 3.使用子组件 用子 --> <!-- <xx></xx>--> <!-- <xx2></xx2>--> <App></App> <!-- content header footer aside section nav H5有一些新标签,注意,组件名称尽量不要和标签名称冲突 --> </div> </body> <script src="vue.js"></script> <script src="axios.js"></script> <script> // 父组件往子组件传值: let Vheader = { data(){ return { nav_list:['个人中心','登录','注册','username'] } }, template:`<div> <h1>{{nav_list}}</h1> <h2>{{nav_list}}</h2> <h4 style="color:green;">{{ff}}</h4> <input type="text" v-model="ff"> #修改input标签的值,不会影响父级标签的数据 </div>`, props:['ff', ], }; let xxx = { data(){ return { content_list:['xxx','ooo',] } }, template:'<h1 style="color:red;">{{content_list}}</h1>', }; let App = { data(){ return { 'xxx':'ooo', num:1001, } }, // <Vheader ff="123"></Vheader> 静态传值 template: ` <div class="app"> <Vheader :ff="num"></Vheader> <xxx></xxx> <h3 style="color:blue;">{{num}}</h3> </div> `, components: { Vheader, xxx, } } let vm = new Vue({ el:'#app', components:{ App, } }) </script> </html>
子组件父组件传值
两步:
a.子组件中使用this.$emit('fatherHandler',val);fatherHandler是父组件中使用子组件的地方添加的绑定自定义事件,注意,如果fatherHandler报错了,那么可能是你的vue版本不支持自定义键名称fatherHandler中有大写字母,所以我们改成father-handler或者直接就全部小写就可以了
<Vheader @fatherHandler="appFatherHandler"></Vheader>
b.父组件中的methods中写一个自定义的事件函数:appFatherHandler(val){},在函数里面使用这个val,这个val就是上面子组件传过来的数据
示例代码:
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="vue.js"></script> </head> <body> <div id="app"> <div class="vheader"> 这是头部{{msg}} -- {{sondata}} </div> <App @son="sonDataHandler"/> </div> </body> <script> let App = { data(){ return { 'appmsg':'hello app!' } }, template:` <div class="content"> 内容部分{{appmsg}} <button @click="xH"></button> </div> `, methods:{ xH(){ this.$emit('son',this.appmsg) } } }; let vm = new Vue({ el:'#app', data(){ return { 'msg':'hello', 'sondata':'xxx', } }, components:{ App, }, methods:{ sonDataHandler(val){ console.log(val); this.sondata = val; } } }) </script> </html>
平行组件传值
什么是平行组件?
声明两个全局组件T1和T2,T1组件将数据传送给T2组件
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="vue.js"></script> </head> <body> <div id="app"> <div class="vheader"> 这是头部{{msg}} -- {{sondata}} </div> <!--<App :xx="msg"/>--> <App @sonHa="sonDataHandler"/> </div> </body> <script> let bus = new Vue(); Vue.component('T1',{ data(){ return { 't1num':100, } }, template:` <div class="t1"> {{t1num}} <button @click="f1">走你</button> </div> `, methods:{ f1(){ // console.log(this.t1num); bus.$emit('TestData',this.t1num) } } }); Vue.component('T2',{ data(){ return { 't2num':200, 't1n':0, } }, template:` <div class="t2"> <h1>{{t2num}}</h1> <h2 style="color:red;">{{t1n}}</h2> </div> `, created(){ // console.log(this.t1n); bus.$on('TestData',(val)=>{ console.log(val); this.t1n = val; }) } }); let App = { data(){ return { 'appmsg':'hello app!' } }, template:` <div class="content"> 内容部分{{appmsg}} <button @click="xH">点击</button> <T1></T1> <T2></T2> </div> `, methods:{ xH(){ this.$emit('sonHa',this.appmsg) } // console.log(this); } // props:['xx',] }; let vm = new Vue({ el:'#app', data(){ return { 'msg':'hello', 'sondata':'xxx', } }, components:{ App, }, methods:{ sonDataHandler(val){ console.log(val); this.sondata = val; } } }) </script> </html>