一、
1 组件是什么 扩展 HTML 元素,封装可重用的代码,目的是复用 -例如:有一个轮播,可以在很多页面中使用,一个轮播有js,css,html -组件把js,css,html放到一起,有逻辑,有样式,有html 2 分类 -全局组件 -局部组件 3 工程化以后 一个组件就是一个 xx.vue 4 element ui 其实就是写了一堆好看的组件,以后我们直接拿过来用就可以了
5 在vue中,实例就是对象
1.1
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script src="js/vue.js"></script> <title>Title</title> </head> <body> <div id="box"> <div @click="handleClick">我是根组件的div</div> <!-- 全局组件使用--> <child></child> <ul> <li v-for="i in 4">{{i}}</li> </ul> <div> <child></child> </div> </div> </body> <script> //创建组件对象(全局组件)---注意写法 Vue.component('child', { //组件的模板 template: ` <div> <div style="background: red" @click="handleClick">我是头部</div> <div v-if="isShow">显示消失</div> </div> `, // 组件的方法 methods:{ handleClick(){ console.log('我被点击了') this.isShow=!this.isShow } }, //组件的数据 data(){ return { isShow:true } }, }) var vm = new Vue({ el: '#box', data: { isShow:true, }, methods:{ handleClick(){ console.log('根组件我被点击了') } } }) </script> </html>
1.2
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script src="js/vue.js"></script> <title>Title</title> </head> <body> <div id="box"> <child></child> </div> </body> <script> //在根组件或全局组件 中定义出来局部组件(可定义多个,但必须注册) var vm = new Vue({ el: '#box', data: { isShow: true, }, methods: { handleClick() { console.log('根组件我被点击了') } }, //局部组件,对象里的key值是主键名 components:{ child:{ //child组件名 template:` <div @click="handleClick">{{name}}</div> `, //组件模板 methods:{ handleClick(){ console.log('我被点了') } }, data(){ return{ name:'lili' } }, }, } }) </script> </html>
二、
1 自定义组件需要有一个root element(即根element),一般包裹在一个div中,跟vue实例(对象)一样 2 父子组件的data是无法共享 3 组件可以有data,methods,computed....,但是data 必须是一个函数 总结:全局组件可以定义局部组件,局部组件只能在这个全局组件里使用;data返回的必须是个函数;数据或函数都是不共享的
代码演示
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script src="js/vue.js"></script> <title>Title</title> </head> <body> <div id="box"> <navbar></navbar> </div> </body> <script> Vue.component('navbar', { template: ` <div> <button @click="handleClick">返回</button> 我是NavBar{{aa}} <button style="background: red">主页</button> <br> <child></child> </div> `, methods: { handleClick() { console.log('nav nav') }, }, components: { child: { template: `<button>儿子</button>`, } }, data() { return { aa: 'lili' } }, }) var vm = new Vue({ el: '#box', data: { isShow: true, }, methods: { handleClick() { console.log('根组件我被点击了') } }, }) </script> </html>
在全局组件中自定义属性(注意三种方式的不同): <global myname="name" myage="18"></global> <global :myname="name" :myage="19"></global> <global :myname="'Alice'" :myage="20"></global> 在组件中获取:{{myname}} {{myage}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>组件</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="box"> <!-- myName是自定义属性 --> <global myname="name" myage="18"></global> <global :myname="name" :myage="19"></global> <global :myname="'Alice'" :myage="20"></global> </div> </body> <script> // 创建1个组件对象(全局组件/子组件) Vue.component('global', { template: ` <div> <div style="background: red">全局组件/子组件</div> {{myname}} {{myage}} </div> `, props: ['myname', 'myage'] }) // 父组件 let vm = new Vue({ el: '#box', data: { name: 'lili' }, }) </script> </html>
3.1属性验证
#限制父传子的变量类型 props: { myname: String, isshow: Boolean } #父传子时候注意以下区别 <global :myname="name" :is_show="'false'"></global> <global :myname="name" :is_show="false"></global> <global :myname="name" :is_show="is_show"></global>
代码演示
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>组件</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="box"> <!-- myName是自定义属性 --> <!-- <global :myname="name" :is_show="'false'"></global>--> <global :my_name="name" :is_show="is_show"></global> <global :my_name="name" :is_show="false"></global> </div> </body> <script> // 创建1个组件对象(全局组件/子组件) Vue.component('global', { template: ` <div> <div style="background: red">我是子组件:{{is_show}}</div> <span>{{my_name}}</span> </div> `, props: { my_name: String, is_show: Boolean } }) // 父组件 let vm = new Vue({ el: '#box', data: { name: 'lili', is_show: true }, }) </script> </html>
四、
子传父(控制子组件的显示和隐藏)
点击子组件,就会触发父组件的某个函数执行
代码演示
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>子传父</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="box"> <global @my_event="handleClick($event)"></global> </div> </body> <script> // 创建1个组件对象(全局组件/子组件) Vue.component('global', { template: ` <div> <div style="background: red">全局组件/子组件</div> <button @click="handleNav">点我</button> </div> `, data() { return { name: 'lili' } }, methods: { handleNav() { console.log('我是子组件的函数') this.$emit('my_event', 666, 777, this.name) } } }) // 父组件 let vm = new Vue({ el: '#box', data: {}, methods: { handleClick(a,b,c) { console.log('我是父组件的函数') console.log(a) console.log(b) console.log(c) } } }) </script> </html>
- 子组件有1个按钮和1个输入框,子组件输入完内容后,数据在父组件中展示
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>子传父 小案例</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="box"> <global @my_event="handleShow($event)"></global> <br> <div>父组件接收到的数据:{{name}}</div> </div> </body> <script> // 创建1个组件对象(全局组件/子组件) Vue.component('global', { template: ` <div> <input type="text" v-model="myText"> <button @click="handleClick">点我传数据</button> </div> `, data() { return { myText: '' } }, methods: { handleClick() { this.$emit('my_event', this.myText) } } }) // 父组件 let vm = new Vue({ el: '#box', data: { name: '' }, methods: { handleShow(a) { this.name = a } } }) </script> </html>
五、
#ref属性(也可实现组件间通信,子父,父子都可以使用) ref放在标签上,拿到的是 原生的DOM节点 ref放在组件上,拿到的是 组件对象 通过这种方式实现子传父(this.$refs.mychild.text) 通过这种方式实现父传子(调用子组件方法传参数)
代码演示
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>ref属性</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="box"> <input type="text" ref="myRef"> <button @click="handleButton">点我</button> </div> </body> <script> // 创建1个组件对象(全局组件/子组件) Vue.component('global', { template: ` <div> <input type="text" v-model="myText"> </div> `, data() { return { myText: '' } }, methods: { handleClick() { this.$emit('my_event', this.myText) this.$emit('my_event', this.innerHTML) } } }) // 父组件 let vm = new Vue({ el: '#box', data: { name: '' }, methods: { handleShow(a) { this.name = a }, handleButton() { console.log(this.$refs) console.log(this.$refs.myRef) console.log(this.$refs.myRef.value) } } }) </script> </html>
即:不同层级的不同组件通信
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>事件总线</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="box"> <global1></global1> <hr> <global2></global2> </div> </body> <script> // 定义1个时间总线 let bus = new Vue({}) // 组件1 Vue.component('global1', { template: ` <div> <h3>组件1</h3> <input type="text" v-model="myText"> <button @click="handleClick1">点我传递数据到另一个组件</button> </div> `, data() { return { myText: '' } }, methods: { handleClick1() { console.log(this.myText) bus.$emit('any', this.myText) // 通过事件总线发送 } } }) // 组件2 Vue.component('global2', { template: ` <div> <h3>组件2</h3> 收到的消息是:{{recvText}} </div> `, data() { return { recvText: '' } }, mounted() { // 组件的挂载(生命周期钩子函数中的1个),开始监听时间总线上的:any bus.$on('any', (item) => { console.log('收到了', item,) this.recvText = item }) }, methods: {} }) // 父组件 let vm = new Vue({ el: '#box', data: {}, }) </script> </html>
keep-alive可以让输入框内有的内容一致保持,不会因为切换而重置
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> <title>Title</title> </head> <body> <div id="box"> <ul> <li @click="who='child1'">首页</li> <li @click="who='child2'">商品</li> <li @click="who='child3'">订单</li> </ul> <!--<component :is="who"></component>--> <keep-alive> <component :is="who"></component> </keep-alive> </div> </body> <script> var vm = new Vue({ el: '#box', data: { who: 'child1' }, components: { child1: { template: ` <div>我是首页 <input type="text"> </div> `, }, child2: { template: ` <div>我是商品 </div> `, }, child3: { template: ` <div>我是订单 </div> `, } } }) </script> </html>
keep-alive
可以让输入框内有的内容一致保持,不会因为切换而重置