00.组件入门
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="../js/vue.js"></script> </head> <body> <div id="app"> <!-- 3.使用组件 --> <my-cpn></my-cpn> <my-cpn></my-cpn> </div> <script> //1.创建组件 var cpnC=Vue.extend({ // template模板 template:`<div> <h2>标题</h2> <p>内容内容内容</p> </div>` }) // 2.注册组件,my-cpn组件名称,cpnC创建的组件 Vue.component('my-cpn',cpnC); var app=new Vue({ el:'#app', data:{ } }) </script> </body> </html>
01.全局组件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="../js/vue.js"></script> </head> <body> <div id="app"> <cpn></cpn> </div> <div id="app1"> <cpn></cpn> </div> <script> // 1.创建组件 var cpnC=Vue.extend({ template:`<div> <h1>标题</h1> <p>内容内容</p> </div>` }) // 2.注册组件(全局组件,意味着可以在多个Vue实例中使用) Vue.component('cpn',cpnC) var app=new Vue({ el:'#app', data:{ } }) var app1=new Vue({ el:'#app1', data:{ } }) </script> </body> </html>
02.局部组件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="../js/vue.js"></script> </head> <body> <div id="app"> <cpn></cpn> </div> <div id="app1"> <cpn></cpn> </div> <script> // 1.创建组件 var cpnC=Vue.extend({ template:`<div> <h1>标题</h1> <p>内容内容</p> </div>` }) var app=new Vue({ el:'#app', data:{ }, // 2.注册组件(局部组件,意味着不能在其他实例中使用) components:{ // cpn使用组件时的标签名 cpn:cpnC } }) var app1=new Vue({ el:'#app1', data:{ } }) </script> </body> </html>
03.父组件和子组件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="../js/vue.js"></script> </head> <body> <div id="app"> <!-- 要想使用组件,必须在全局中注册或者在跟组件中注册 --> <cpn2></cpn2> </div> <script> // 组件1(子组件) var cpnC1=Vue.extend({ template:`<div> <h1>标题1</h1> <p>内容内容1</p> </div>` }) // 组件2(父组件) var cpnC2=Vue.extend({ template:`<div> <h1>标题2</h1> <p>内容内容2</p> <cpn1></cpn1> </div>`, // 将组件1在组件2中注册,并在组件2中使用 components:{ cpn1:cpnC1 } }) var app=new Vue({ el:'#app', data:{ }, // 将组件2在根组件中注册 components:{ cpn2:cpnC2 } }) </script> </body> </html>
04.组件语法糖
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="../js/vue.js"></script> </head> <body> <div id="app"> 全局组件语法糖 <cpn1></cpn1> 局部组件语法糖 <cpn2></cpn2> </div> <script> // 全局注册组件语法糖 Vue.component('cpn1',{ template:`<div> <h1>标题</h1> <p>内容</p> </div>` }) var app=new Vue({ el:'#app', data:{ }, // 注册局部组件语法糖 components:{ 'cpn2':{ template:`<div> <h1>标题</h1> <p>内容</p> </div>` } } }) </script> </body> </html>
05.组件模板抽离写法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="../js/vue.js"></script> </head> <body> <div id="app"> <cpn></cpn> </div> <!-- 1.方法一:将组件的模板写在下面的script中 --> <script type="text/x-template" id="cpn1"> <div> <h1>标题</h1> <p>内容</p> </div> </script> <!-- 1.方法二:使用template --> <template id="cpn2"> <div> <h2>标题2</h2> <p>内容2</p> </div> </template> <script> Vue.component('cpn',{ // 2.引用上面script中的组件模板 template:'#cpn1' }) var app=new Vue({ el:'#app', data:{ } }) </script> </body> </html>
06.props
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="../js/vue.js"></script> </head> <body> <div id="app"> <!-- 2.将父组件的数据动态的赋值给子组件的变量;如果不使用v-bind,gather就会是一个字符串,而不是变量--> <cpn1 v-bind:comvies="gather"></cpn1> </div> <template id="menu"> <div> <!-- 3.使用父组件传来的数据 --> <h1 v-for="item,index in comvies">{{item}}</h1> </div> </template> <script> var cpn1={//子组件 template:'#menu', props:['comvies'],//1.定义一个变量名,用于存储父组件中传来的数据 // props的写法 // props:{ // props的写法a,类型限制 // comvies:Array, // comvies:String, // props的写法b,提供默认值,以及必传值 // comvies:{ // type:String,//类型 // default:'aaaaa',//默认值 // }, // props的写法c,类型是对象或者数组时,默认值必须是一个函数 // comvies:{ // type:Array, // default(){ // return [] // } // } // } } var app=new Vue({//父组件 el:'#app', data:{ gather:['悟空','八戒','沙和尚'] }, components:{//在父组件中注册子组件 cpn1//相当于cpn1=cpn1 } }) </script> </body> </html>
07.子组件向父组件传值
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="../js/vue.js"></script> </head> <body> <div id="app"> <!-- 步骤二:添加事件监听:@itemclick=cpnclick,意思是,一旦监听到子组件中的itemclick事件就会触发父组件中cpnclick;--> <cpn1 @itemclick="cpnclick"></cpn1> </div> <!-- 子模版 --> <template id="menu"> <div> <button v-for="item,index in categories" @click="btnclick(item)">{{item.name}}</button> </div> </template> <script> var cpn1={//子组件 template:'#menu', data(){ return{ categories:[ {id:'aaa',name:'热门推荐'}, {id:'bbb',name:'手机数码'}, {id:'ccc',name:'家用电器'}, {id:'ddd',name:'电脑办公'} ] } }, methods:{ btnclick(item){//这个函数名和item参数都是从子模版中传来的 // 步骤一:想要将子组件的数据传递给父组件,需要自定义触发事件,实现数据的传值; //事件$emit的名称叫itemclick,参数是item this.$emit('itemclick',item) } } } var app=new Vue({//父组件 el:'#app', components:{ cpn1 }, methods:{ // 步骤三:添加cpnclick函数 cpnclick:function(item){//item是$emit事件传来的 console.log(item.name); } } }) </script> </body> </html>
08.子组件和父组件数据双向绑定
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="../js/vue.js"></script> </head> <body> <div id="app"> <!-- 4.监听事件 --> <cpn v-bind:number1="num1" v-bind:number2="num2" v-on:num1change="num1change1" v-on:num2change="num2change2"> </cpn> </div> <!--子组件的模块 --> <template id="menu"> <div> <h2>number1:{{number1}}</h2> <h2>data:{{dnumber1}}</h2> <!-- 1.如果使用v-mode="number1",直接在子组件修改props中的number1,vue官方是不建议的,因为props中的值应该是由父组件更改 --> <!-- <input type="text" v-model="dnumber1"> --> <!-- 将v-mode换一个写法即原理 --> <input type="text" v-bind:value="dnumber1" v-on:input="num1Input1"> <h2>number2:{{number2}}</h2> <h2>data:{{number2}}</h2> <!-- <input type="text" v-model="dnumber2"> --> <input type="text" v-bind:value="number2" v-on:input="num2Input2"> </div> </template> <script> var app=new Vue({ el:'#app', data:{ num1:1, num2:0 }, methods:{ // 5.使用,此时number1==num1 num1change1:function(value){ // 【注意】:因为value是string类型,要改为number类型,不然会报错 this.num1=parseInt(value); }, num2change2:function(value){ this.num2=parseInt(value); } }, //下面是新建组件内容 components:{//直接在父组件中注册一个组件 cpn:{ template:'#menu', props:{ number1:Number, number2:Number }, data:function(){//data在组件中必须是函数形式 return{// 2.因为子组件中的props值需要由父组件更改,想要通过子组件更改,就要通过data函数 dnumber1:this.number1, dnumber2:this.number2 } }, methods:{ num1Input1:function(event){ this.dnumber1=event.target.value; //3.通过子组件向父组件传数据的方法修改num1和num2的值 this.$emit('num1change',this.dnumber1) }, num2Input2:function(event){ this.dnumber2=event.target.value; this.$emit('num2change',this.dnumber2) } } } } }) </script> </body> </html>
09.父访问子组件值
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="../js/vue.js"></script> </head> <body> <div id="app"> <cpn></cpn> <cpn ref="aaa"></cpn> <button v-on:click="btnclick">按钮</button> </div> <template id="menu"> <div> <h1>我是子组件</h1> </div> </template> <script> var app=new Vue({ el:'#app', data:{ }, methods:{ btnclick:function(){//【注意】:这个函数在父组件中, // 1.children console.log(this.$children); // 2.$refs => 对象类型, 默认是一个空的对象 ref='aaa' console.log(this.$refs.aaa.showMessage()); console.log(this.$refs.aaa.name); } }, components:{ cpn:{ template:'#menu', data:function(){ return{ name:'张三' } }, methods:{ showMessage:function(){ console.log('showMessage'); } } } } }) </script> </body> </html>
10.子访问父中的值
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="../js/vue.js"></script> </head> <body> <div id="app"> <cpn></cpn> </div> <template id="menu1"> <div> <h2>cpn组件</h2> <ccpn></ccpn> </div> </template> <template id="menu2"> <div> <h2>ccpn组件</h2> <button v-on:click="btnclick">按钮</button> </div> </template> <script> var app=new Vue({//根组件 el:'#app', data:{ name:'张三' }, components:{ cpn:{//子组件(此时cpn是ccpn的父组件) template:'#menu1', data:function(){ return{ name:'李四' } }, components:{ ccpn:{//子组件 template:'#menu2', methods:{ btnclick:function(){//【注意】:这个函数是在子组件中 // 1.访问父组件$parent console.log(this.$parent.name); // 2.访问根组件$root console.log(this.$root); } } } } } } }) </script> </body> </html>
11.插槽
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="../js/vue.js"></script> </head> <body> <div id="app"> <!-- 2.在使用同一个组件时,给同一个组件添加不同的内容 --> <cpn><button>首页</button> </cpn> <cpn><button>新闻中心</button> </cpn> <!-- 默认在里面添加了button按钮 --> <cpn></cpn> <cpn></cpn> </div> <template id="menu"> <div> <h1>我是组件</h1> <!-- 1.这里添加一个空的slot;另外给slot添加一个默认值即button按钮,当上面的cpn没有添加内容时,就自动添加默认值 --> <slot><button>按钮</button></slot> </div> </template> <script> var app=new Vue({ el:'#app', data:{ }, components:{ cpn:{ template:'#menu', } } }) </script> </body> </html>
12.具名插槽
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="../js/vue.js"></script> </head> <body> <div id="app"> <!-- 1.如果直接这样写,会修改所有没有name的slot --> <!-- <cpn><span>内容</span></cpn> --> <!-- 2.修改其中一个带有name的slot --> <cpn><span slot="center">中间</span></cpn> </div> <template id="menu"> <div> <h2>标题</h2> <slot name="left"><span>左边</span></slot> <slot name="center"><span>中心</span></slot> <slot name="right"><span>右边</span></slot> </div> </template> <script> var app=new Vue({ el:'#app', data:{ }, components:{ cpn:{ template:'#menu' } } }) </script> </body> </html>
13.作用域
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="../js/vue.js"></script> </head> <body> <div id="app"> 官方:父组件中的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子级作用域内编译 <div> <!-- 1.这里的show使用的是vue实例组件中的 --> <h2 v-if="show">vue实例组件</h2> <cpn></cpn> </div> </div> <template id="menu"> <div> <!-- 2.这里的show使用的是子组件中的 --> <h2 v-if="show">子组件</h2> </div> </template> <script> var app=new Vue({ el:'#app', data:{ show:true }, components:{ cpn:{ template:'#menu', data:function(){ return{ show:false } } } } }) </script> </body> </html>
14.作用域与插槽的使用
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="../js/vue.js"></script> </head> <body> 功能:由于父组件对子组件的数据展示效果不满意,通过父组件获取子组件的数据,重新再次展示; <div id="app"> <cpn></cpn> <cpn> <!-- 2.在父组件里面创建一个template,目的是获取子组件中的数据,slot-scope是为了拿到插槽对象,然后通过slot.abc就可以拿到子组件中的:abc; --> <template slot-scope="slot"> <span v-for="item,index in slot.abc">{{item}}——</span> </template> </cpn> </div> <template id='menu'> <div> <!-- 1.通过子组件中的“:data”,将language数据传到父组件中的template中 --> <slot :abc="language"> <ul v-for="item,index in language"> <li>{{item}}</li> </ul> </slot> </div> </template> <script> var app=new Vue({ el:'#app', data:{ }, components:{ cpn:{ template:'#menu', data:function(){ return{ language:['html','cookie','ajax'] } } } } }) </script> </body> </html>