组件的注册
https://cn.vuejs.org/v2/guide/components-registration.html
<body> <div id="box"> <navbar></navbar> </div> <script type="text/javascript"> // vue 组件 :扩展html元素 //组件是一个孤岛,无法(直接)访问到外部的 data,methods....... //将来可以通过通信方式来进行沟通 //全局组件定义方式 Vue.component("navbar",{ template:` <div> <nav style="background:yellow;"> <button @click="handleClick()">返回</button> <navbarchild1></navbarchild1> //全局注册的子组件 <navbarchild2></navbarchild2> //局部注册的子组件 <ul> <li>11111</li> <li>22222</li> </ul> {{myname}} </nav> <div>最外层必须有root element</div> </div> `, components:{ //局部定义组件 navbarchild2:{ // data(){} watch: {}, template:`<div style="background:blue;">我是局部定义的,其他人休想得到我</div>` } }, methods: { handleClick(){ console.log("返回功能") } }, //组件中 data必须是一个方法, return 返回对象 //保证data不会相互影响 data(){ return { myname:"我是导航栏", } } }) //全局定义的 Vue.component("navbarchild1",{ template:` <div style="background:red;"> 1.不要吐槽此时的组件,我虽然没有高亮,虽然没有代码提示, 但是这个时间,能用上我,也是一种好的选择 2.样式这个时候只能先写行内样式 3.之后单文件组件 都会解决这些问题。 </div> ` }) new Vue({ el:"#box", methods: { }, watch: { }, computed: { }, }) </script> </body>
组件编写方式与Vue实例的区别
*自定义组件需要有一个root element
*父子组件的data是无法共享
*组件可以有data,methods,computed....,但是data 必须是一个函数
组件通信
(1)父传子
父传子的方式非常简单,在父组件上绑定一个属性,在子组件上用props接受就可以了
<body> <div id="box"> <!-- 首页中引入的 --> <navbar mytitle="home" :myshow="false" :mytext="text"></navbar> <!-- 列表页面引入的 --> <navbar mytitle="list" :myshow="true" :mytext="text"></navbar> <!-- 购物车页面引入的 --> <navbar mytitle="shopcar" :myshow="true" :mytext="text"></navbar> </div> <script> //home Vue.component("navbar",{ template:` <nav> <button v-if="myshow">返回</button> <span>我是导航--{{mytitle}}-{{mytext}}</span> <button v-show="myshow">主页</button> </nav> `, //接受父组件传来的属性 mytitle myshow // props:["mytitle","myshow"] //属性验证 props :{ mytext:String, mytitle:String, myshow:Boolean //接受的myshow必须是boolean类型 Array Number } }) // root compoennt new Vue({ el:"#box", data:{ text:"我是在父组件中定义" } }) </script> </body>
(2)子传父
子串父的实现方式是在父子身上绑定一个函数,在触发子组件身上的函数时,调起父组件的函数并为其传数据
<body> <div id="box"> <my-child @kerwinevent1="handleEvent1" @kerwinevent2="handleEvent2"></my-child> <!-- <myChild></myChild> --> </div> <script> Vue.component("myChild",{ template:` <div> child-<button @click="handleClick()">click</button> </div> `, data(){ return { text:"child定义的状态" } }, methods: { handleClick(){ //把text状态传到父组件中 //触发,分发 this.$emit("kerwinevent2",100000) this.$emit("kerwinevent1",this.text) } }, }) //root component new Vue({ el:"#box", data:{ }, methods:{ handleEvent1(data){ console.log("收到钱了-11111",data) }, handleEvent2(data){ console.log("收到钱了-22222",data) } } }) </script> </body>
(3)ref
ref放在标签上, 拿到的是原生节点
ref放在组件上, 拿到的是组件对象,通信功能
<body> <div id="box"> <input type="text" ref="mytext"/> <button @click="handleClick()">click</button> <child ref="mychild"></child> </div> <script type="text/javascript"> Vue.component("child",{ data(){ return { childtext:"child定义的" } }, template:`<div> child -{{childtext}} </div>` }) //子组件 new Vue({ el:"#box", methods: { handleClick(){ console.log(this.$refs.mychild.childtext) this.$refs.mychild.childtext= "22222222222" } }, }) </script> </body>
(4)中央事件总线-bus
<body> <div id="box"> <child1></child1> <child2></child2> </div> <script type="text/javascript"> //中央事件总线 var bus = new Vue() //中央事件总线 bus.$on bus.$emit Vue.component("child1",{ template:` <div> child1-<button @click="handleClick()">click</button> </div> `, methods: { handleClick(){ // bus.$emit("kerwinevent","来自child1的问候") console.log("emit触发bus事件") } }, }) Vue.component("child2",{ template:` <div> child2 </div> `, mounted() { console.log("自动被调用, 等child上树就会被执行 立即监听事件") bus.$on("kerwinevent",(data)=>{ console.log("child2函数被执行",data) }) }, }) var vm = new Vue({ el:"#box", methods: { }, }) </script> </body>
动态组件
https://cn.vuejs.org/v2/guide/components.html#%E5%8A%A8%E6%80%81%E7%BB%84%E4%BB%B6
<body> <div id="box"> <keep-alive> <component :is="type"></component> </keep-alive> <footer> <ul> <li @click="type='home'">首页</li> <li @click="type='list'">列表</li> <li @click="type='shopcar'">购物车</li> </ul> </footer> </div> <script type="text/javascript"> Vue.component("home",{ template:`<div> home -<input type="text"/> </div>` }) Vue.component("list",{ template:`<div> list </div>` }) Vue.component("shopcar",{ template:`<div> shopcar </div>` }) new Vue({ el:"#box", data:{ type:"home" } }) </script> </body>