组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。是可复用的Vue实例。
组件树
局部组件
局部组件分为声子,挂子,用子
1.声子,声明一个组件 Vue 中组件的名字首字母要大写 跟标签区分,组件中的data必须是个函数,一定要有返回值 2.挂子,挂载组件components 挂载哪个组件,这个组件就是我的父组件 3.用子,用组件 <组件名/> template中的模板一定要有一个根标签包裹 如果仅仅是实例化vue对象中既有el 又有template,如果template中定义模板的内容,那么template模板的优先级大于el,
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <!-- //如果template也定义这个msg属性,这块不会在显示--> <h4>{{ msg }}</h4> </div> <script src="../vue.js"></script> <script> // Vue 中组件的名字首字母要大写 跟标签区分,组件中的data必须是个函数,一定要有返回值 // 1.声子,声明一个组件 let App = { data(){ return{ text:'天选之子' } }, //template定义模板中的内容 template: ` <div id="a"> <h3>{{ text }}</h3> </div> ` }; new Vue({ //如果仅仅是实例化vue对象中既有el 又有template,如果template中定义模板的内容, // 那么template模板的优先级大于el el:'#app', data(){ return{ msg:'wind' } }, template:` <div class="app"> <!-- <h1>{{ msg }}</h1>--> <!-- // 3.用子,用组件--> <App/> </div> `, // 2.挂子,挂载组件components components:{ //如果key和value一样,可以只写一个App,这里的value :App就是上面声明的App App:App } }) </script> </body> </html>
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <!-- 在这里调用--> <App></App> </div> <script src="../vue.js"></script> <script> let App = { data(){ return{ text:'天选之子' } }, template: ` <div id="a"> <h3>{{ text }}</h3> </div> ` }; new Vue({ //如果仅仅是实例化vue对象中既有el 又有template,如果template中定义模板的内容, // 那么template模板的优先级大于el el:'#app', data(){ return{ } }, // 2.挂子,挂载组件components components:{ App } }) </script> </body> </html>
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <App></App> </div> <script src="../vue.js"></script> <script> let Vheader = { data() { return {} }, template: ` <div> <h1>随风</h1> <h2>浪翻云</h2> </div> ` }; let App = { data() { return { text: '天选之子' } }, template: ` <div id="a"> <h3>{{ text }}</h3> <Vheader></Vheader> </div> `, components: { Vheader } }; new Vue({ el: '#app', data() { return {} }, // 2.挂子,挂载组件components components: { App } }) </script> </body> </html>
全局组件
Vue.component('',{})
全局组件第一个参数是组件的名字,第二个参数options,全局组件不需要挂载,
在哪个组件中使用这个全局组件,这个组件就是这个全局组件的父组件,当然可以有多个父组件哈
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <App></App> </div> <script src="../vue.js"></script> <script> // 全局组件第一个参数是组件的名字,第二个参数options,全局组件不需要挂载, // 在哪个组件中使用这个全局组件,这个组件就是这个全局组件的父组件,当然可以有多个父组件哈 Vue.component('Global',{ data(){ return{} }, template:`<button>按钮</button>` }) let Vheader = { data() { return {} }, template: ` <div> <h1>随风</h1> <h2>浪翻云</h2> <Global>登录</Global> <Global>注册</Global> <Global>关闭</Global> </div> ` }; let App = { data() { return { text: '天选之子' } }, template: ` <div id="a"> <h3>{{ text }}</h3> <Vheader></Vheader> <br> <Global></Global> </div> `, components: { Vheader } }; new Vue({ el: '#app', data() { return {} }, // 2.挂子,挂载组件components components: { App } }) </script> </body> </html>
slot内容分发
solt是vue的内置的,只需要在全局组件中加上slot标签,父组件就可以内容分发替换哈
Vue.component('Global',{ data(){ return{} }, template:`<button> <slot></slot> </button>` })
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <App></App> </div> <script src="../vue.js"></script> <script> // 全局组件第一个参数是组件的名字,第二个参数options,全局组件不需要挂载, // 在哪个组件中使用这个全局组件,这个组件就是这个全局组件的父组件,当然可以有多个父组件哈 Vue.component('Global',{ data(){ return{} }, template:`<button> <slot></slot> </button>` }) let Vheader = { data() { return {} }, template: ` <div> <h1>随风</h1> <h2>浪翻云</h2> <Global>登录</Global> <Global>注册</Global> <Global>关闭</Global> </div> ` }; let App = { data() { return { text: '天选之子' } }, template: ` <div id="a"> <h3>{{ text }}</h3> <Vheader></Vheader> <br> <Global>按钮</Global> </div> `, components: { Vheader } }; new Vue({ el: '#app', data() { return {} }, // 2.挂子,挂载组件components components: { App } }) </script> </body> </html>
父往子传值
1.props 属性,在子组件中定义props:[ ' 任意变量名' ] 来接收父组件传过来的值,可以在子组件中任意使用
2.父组件要定义自定义的属性,自定义的属性名字(key)要和子组件定义的props:['变量名']相同,自定义属性的值(value)要和父组件本身return
的属性名相同
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <App></App> </div> <script src="../vue.js"></script> <script> let Vheader = { data() { return {} }, props:['msg'], template: ` <div> <h1>随风</h1> <h3>{{ msg }}</h3> </div> ` }; let App = { data() { return { text: '我是父组件的数据' } }, template: ` <div id="a"> <h3>{{ text }}</h3> <Vheader :msg = 'text'></Vheader> </div> `, components: { Vheader } };
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <App></App> </div> <script src="../vue.js"></script> <script> let Vheader = { data() { return {} }, // 接收父组件传来的数据 props:['msg','post'], template: ` <div> <h1>随风</h1> <h1>{{ msg }}</h1> <h4>{{ post.title }}</h4> </div> ` }; let App = { data() { return { text: '我是父组件的数据', post:{ id:1, title:'vue太帅了' } } }, template: ` <div id="a"> <h5>{{ text }}</h5> <Vheader :msg = 'text' v-bind:post ="post"></Vheader> </div> `,
子往父传值
$emit()方法第一个参数:(父组件声明的自定义事件,第二参数是要传的值)
1. 先在父组件中,子组件用子的标签上,声明一个自定义的事件(名字不能和原生JS事件名重复),绑定一个自定义的方法.
2. 在子组件中声明一个事件,绑定一个自定义的方法.使用this.$emit('',)进行传值
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <App></App> </div> <script src="../vue.js"></script> <script> Vue.component('Global', { data() { return {} }, template: `<button @click ='clickHandler'> <slot></slot> <h1>{{ id }}</h1> </button>`, props: ['id'], methods: { clickHandler() { this.id++;//每点一次就让值+1 // $emit方法第一个参数:父组件声明的自定义事件,第二参数是要传的值 this.$emit('clickHand', this.id) } } }); let Vheader = { data() { return { post: {'id': 1, 'name': 'wind'} } }, // 接收父组件传来的数据 props: ['msg', 'post'], template: ` <div> <h1>我是head组件</h1> <h1>随风</h1> <h1>{{ msg }}</h1> <h4>{{ post.title }}</h4> <Global v-bind:id="post.id" @clickHand="func"></Global> </div> `, methods: { func(val) { alert(val); this.$emit('Father',666) } } }; let App = { data() { return { text: '我是父组件的数据', post: { id: 1, title: 'vue太帅了' } } }, template: ` <div id="a"> 我是父组件的 {{ post.id }} <Vheader :msg = 'text' v-bind:post ="post" @Father="father"></Vheader> </div> `, components: { Vheader }, methods: { father(value) { console.log(value); this.post.id = value } } }; new Vue({ el: '#app', data() { return {} }, components: { App } }) </script> </body> </html>
平行组件传值
$on 和 $emit
$on('Test1组件中声明的事件的名',function(val){})
$emit('Test1组件中声明的事件名','传的值')
1.实例化一个全局的Vue对象当作公交车 2.Test1 往Test2传值 ,Test2要声明事件 $on('Test1组件中声明的事件的名',function(val){}) 3.Test1 要触发事件用$emit('Test1组件中声明的事件名','传的值') 前提:这两个方法必须绑定在同一个实例化对象上
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <App></App> </div> <div></div> <script src="../vue.js"></script> <script> // 1.实例化一个全局的Vue对象当作公交车 let bus = new Vue(); // 2.Test1 往Test2传值 ,Test2要声明事件 $on('Test1组件中声明的事件的名',function(val){}) , // 3.Test1 要触发事件用$emit('Test1组件中声明的事件名','传的值') // 前提:这两个方法必须绑定在同一个实例化对象上 Vue.component('Test2', { data() { return { text: '' } }, template: ` <div>{{ text }}</div> `, methods: {}, created() { bus.$on('testdata', (val)=> { alert(val); this.text = val }) } }); // Vue.component('Test1', { data() { return { msg: '我是子组件数据' } }, template: ` <button @click="clickHandler">传递</button> `, methods: { clickHandler() { bus.$emit('testdata', this.msg) } } }); let Vhead = { data() { }, template: ` <div class="head"> <Test1></Test1> <Test2></Test2> </div> ` }; let App = { data() { return {} }, template: ` <div class="app"> <Vhead></Vhead> </div> `, components: { Vhead } }; new Vue({ el: '#app', data() { return {} }, components: { App } }) </script> </body> </html>