vue组件(一)
组件嵌套:
1.全局嵌套:
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <script src="vue.js"></script> <script> Vue.component("aaa",{ template:`<div>组件A <bbb></bbb></div>` });//子组件放在父组件的模板里 Vue.component("bbb",{ template:`<div>组件B</div>` }); window.onload = function(){ let vm = new Vue({ el:"#app" }); }; </script> </head> <body> <div id="app"> <aaa></aaa> </div> </body> </html>
res:
2.局部嵌套:
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <script src="vue.js"></script> <script> window.onload = function(){ let vm = new Vue({ el:"#app", components:{ "aaa":{ template:`<div>组件A<bbb></bbb></div>`, //子组件必须放在父组件的属性里 components:{ "bbb":{ template:`<div>组件B</div>` } } }, /*"bbb":{ template:`<div>组件B</div>` } */ //错误 } }); }; </script> </head> <body> <div id="app"> <aaa></aaa> </div> </body> </html>
res:
组件通信(重要)
==1、props/$emit==
1.数据的双向绑定:
v-model后的变量名相同
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <script src="vue.js"></script> <script> window.onload = function(){ let vm = new Vue({ el:"#app", data:{ msg:"abc" } }); }; </script> </head> <body> <div id="app"> <input v-model="msg" type="text" value=""/><br /> <input v-model="msg" type="text" value=""/><br /> {{msg}}<br /> </div> </body> </html>
res:
2.父传子,子传父props/$emit, 用ev.target.value或事件监听
(1)ev.target.value
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <script src="vue.js"></script> <script> Vue.component("mycomponent",{ props:["msg"], template:`<div><input @input="show" type="text" :value="msg"/>{{msg}}</div>`, methods:{ show(ev){ console.log(22222); this.$emit("abc",ev.target.value); //传子组件value值 } } }); window.onload = function(){ let vm = new Vue({ el:"#app", data:{ msg:"abc" }, methods:{ fn(data){ console.log(11111,data); this.msg = data; } } }); }; </script> </head> <body> <div id="app"> <input v-model="msg" type="text" value=""/>{{msg}}<br /> <hr /> <mycomponent :msg="msg" @abc="fn"></mycomponent> </div> </body> </html>
res:
(2)事件监听
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <script src="vue.js"></script> <script> Vue.component("mycomponent",{ props:["msg"], template:`<div><input v-model="msg2" type="text" value=""/>{{msg}}</div>`, data(){ return {msg2:this.msg} }, watch:{ msg(){ this.msg2 = this.msg; }, msg2(){ this.$emit("abc",this.msg2); } } }); window.onload = function(){ let vm = new Vue({ el:"#app", data:{ msg:"abc" }, methods:{ fn(data){ console.log(11111,data); this.msg = data; } } }); }; </script> </head> <body> <div id="app"> <input v-model="msg" type="text" value=""/>{{msg}}<br /> <hr /> <mycomponent :msg="msg" @abc="fn"></mycomponent> </div> </body> </html>
res:
2.对象—— 引用
==子与父操控同一个对象==
1.父传子,子传父props,value
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <script src="vue.js"></script> <script> Vue.component("mycomponent",{ props:["msg"], template:`<div><input v-model="msg.value" type="text" value=""/>{{msg.value}}</div>` }); window.onload = function(){ let vm = new Vue({ el:"#app", data:{ //msg:"abc" msg:{value:"abc"} //对象--msg.value引用 } }); }; </script> </head> <body> <div id="app"> <input v-model="msg.value" type="text" value=""/>{{msg.value}}<br /> <hr /> <mycomponent :msg="msg"></mycomponent> </div> </body> </html>
res:
3.$children / $parent / $root
1. $children
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <script src="vue.js"></script> <script> Vue.component("aaa",{ template:`<div>组件A----{{a}}</div>` , data(){ return {a:"a"} } }); Vue.component("bbb",{ template:`<div>组件B</div>` }); window.onload = function(){ let vm = new Vue({ el:"#app", methods:{ show(){ //$children console.log(this.$children); this.$children[0].$el.style.background = "red" this.$children[0].a = "abc" } } }); }; </script> </head> <body> <div id="app"> <input @click="show" type="button" value=" 按钮" /> <aaa></aaa> <bbb></bbb> </div> </body> </html>
res:
2.$parent
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <script src="vue.js"></script> <script> Vue.component("aaa",{ template:`<div @click="show">组件A----{{a}}</div>`, data(){ return {a:"a"} }, methods:{ show(){ //parent/root console.log(this.$parent == this.$root); //this.$parent.msg = "哈哈哈"; this.$root.msg = "哈哈哈"; } } }); Vue.component("bbb",{ template:`<div>组件B</div>` }); window.onload = function(){ let vm = new Vue({ el:"#app", data:{ msg:"Vue" }, methods:{ show(){ } } }); }; </script> </head> <body> <div id="app"> <input @click="show" type="button" value=" 按钮" />{{msg}} <hr /> <aaa></aaa> <bbb></bbb> </div> </body> </html>
res:
3.$root
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <script src="vue.js"></script> <script> Vue.component("aaa",{ template:`<div @click="show">组件A----{{a}} <bbb></bbb></div>`, data(){ return {a:"a"} }, methods:{ show(){ //parent/root console.log(this.$parent == this.$root); //this.$parent.msg = "哈哈哈"; this.$root.msg = "哈哈哈"; } } }); Vue.component("bbb",{ template:`<div @click.stop="show">组件B</div>`, methods:{ show(){ //parent/root console.log(this.$parent == this.$root); this.$parent.a = "aa"; this.$root.msg = "嘻嘻嘻"; } } }); window.onload = function(){ let vm = new Vue({ el:"#app", data:{ msg:"Vue" }, methods:{ show(){ } } }); }; </script> </head> <body> <div id="app"> <input @click="show" type="button" value=" 按钮" />{{msg}} <hr /> <aaa></aaa> </div> </body> </html>
res:
4、ref/$refs
this.$refs以数组的形式获取全部的ref
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <script src="vue.js"></script> <script> //ref Vue.component("aaa",{ template:`<div>组件A----{{a}} </div>`, data(){ return {a:"a"} } }); Vue.component("bbb",{ template:`<div>组件B</div>`, }); window.onload = function(){ let vm = new Vue({ el:"#app", data:{ msg:"Vue" }, methods:{ show(){ console.log(this.$refs); //this.$refs以数组的形式获取全部的ref this.$refs.aaa.$el.style.background = "pink"; this.$refs.aaa.a = "pink"; } } }); }; </script> </head> <body> <div id="app"> <input @click="show" type="button" value=" 按钮" />{{msg}} <hr /> <aaa ref="aaa"></aaa> <bbb ref="bbb"></bbb> </div> </body> </html>
res:
5、eventBus事件总线
let eventBus = new Vue();
eventBus.$emit(sEv,data);
eventBus.$on(sEv,data=>{})
exp:
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <script src="vue.js"></script> <script> //事件总线——eventBus emit/on Vue.component("aaa",{ template:`<div @click="show">组件A----{{a}} </div>`, data(){ return {a:"a"} }, created(){ eventBus.$on("chagnea",data=>{ this.a = data; }); }, methods:{ show(){ eventBus.$emit("chagneb","我想你了"); } } }); Vue.component("bbb",{ template:`<div @click="show">组件B----{{b}}</div>`, data(){ return {b:"b"} }, created(){ eventBus.$on("chagneb",data=>{ this.b = data; }); }, methods:{ show(){ eventBus.$emit("chagnea","我也想你了"); } } }); let eventBus = new Vue(); window.onload = function(){ let vm = new Vue({ el:"#app", data:{ msg:"Vue" }, methods:{ show(){ } } }); }; </script> </head> <body> <div id="app"> <aaa></aaa> <bbb></bbb> </div> </body> </html>
res:
6、sync
sync --> this.$emit("updata:xxx",data);
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <script src="vue.js"></script> <script> //sync Vue.component("mycomponent",{ props:["msg"], template:`<div><input @input="show" v-model="msg2" type="text" value=""/>{{msg}}</div>`, data(){ return {msg2:this.msg} }, methods:{ show(){ this.$emit("update:msg",this.msg2); } } }); window.onload = function(){ let vm = new Vue({ el:"#app", data:{ msg:"abc" }, methods:{ fn(data){ this.msg = data; } } }); }; </script> </head> <body> <div id="app"> <input v-model="msg" type="text" value=""/>{{msg}}<br /> <hr /> //@update:msg="fn",事件 <mycomponent :msg="msg" @update:msg="fn" ></mycomponent> // :msg.sync="msg",固定写法 <mycomponent :msg.sync="msg" ></mycomponent> </div> </body> </html>
res:
7、v-model
v-model --> this.$emit("input",data);
exp:自增
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <script src="vue.js"></script> <script> //sync Vue.component("mycomponent",{ template:`<div><input @click="show" type="button" value="plus"/></div>`, data(){ return {count:0} }, methods:{ show(){ //"input"固定写法 this.$emit("input",++this.count); } } }); window.onload = function(){ let vm = new Vue({ el:"#app", data:{ count:0 }, methods:{ show(data){ console.log(1,data); this.count = data; } } }); }; </script> </head> <body> <div id="app"> {{count}} <hr /> <mycomponent v-model="count" ></mycomponent> </div> </body> </html>
res:
vue组件(二)
1.创建组件
1、全局 Vue.component
2、局部 new Vue({components:{}});
3、Vue.extend
let VueComponent = Vue.extend(options);
Vue.component("名字",VueComponent);
返回值:Vue.extend、Vue.component 返回的都是VueComponent
new VueComponent().$mount("#app");
Vue.extend可以没有参数
let VueComponent = Vue.extend();
new VueComponent(options).$mount("#app");
获取模板元素:
let tmp = new VueComponent([options]).$mount().$el;
document.body.appendChild(tmp);
exp:
==++Vue.extend++==
全局组件:
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <script src="vue.js"></script> <script> //Vue.extend //VueComponent let mycomponent = Vue.extend({ template:`<div>Vue.extend组件</div>` }); Vue.component("mycomponent",mycomponent);//("组件名",VueComponent) window.onload = function(){ let vm = new Vue({ el:"#app", }); }; </script> </head> <body> <div id="app"> <mycomponent></mycomponent> </div> </body> </html>
局部组件:
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <script src="vue.js"></script> <script> //Vue.extend let mycomponent = Vue.extend({ template:`<div>Vue.extend组件</div>` }); //new Vue({components:{}}); window.onload = function(){ let vm = new Vue({ el:"#app", components:{mycomponent} }); }; </script> </head> <body> <div id="app"> <mycomponent></mycomponent> </div> </body> </html>
//最大组件 Vue
let VueComponent = Vue.extend(options);//new时不带参数
let VueComponent = Vue.extend();//new时带参数
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <script src="vue.js"></script> <script> let Comp1 = Vue.extend({ template:`<div>Vue.extend组件</div>` }); let Comp2 = Vue.extend(); console.log(1,Comp1); console.log(2,Comp2); window.onload = function(){ //let oDiv = new Comp1().$mount().$el; //获取模板元素: let oDiv = new Comp2({ template:`<div>new Comp2组件</div>` }).$mount().$el; console.log(3,oDiv); document.body.appendChild(oDiv); }; </script> </head> <body> <div id="app"> </div> </body> </html>
静态组件 动态组件
==必须有is==
静态--> is="组件的名称"
动态--> :is="变量或者值 '组件的名称'"
<div is="组件的名称"></div> <div :is="变量或者值 '组件的名称'"></div>
exp:
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <script src="vue.js"></script> <script> Vue.component("aaa",{ template:`<div>组件A</div>` }); Vue.component("bbb",{ template:`<div>组件B</div>` }); window.onload = function(){ let vm = new Vue({ el:"#app", data:{ comp:"aaa" }, methods:{ toggle(){ this.comp = this.comp=="aaa"?"bbb":"aaa"; } } }); }; </script> </head> <body> <div id="app"> <input @click="comp='aaa'" type="button" value="组件A"/> <input @click="comp='bbb'" type="button" value="组件B"/> <input @click="toggle" type="button" value="toggle"/> <!-- 动态--> <div :is="comp"></div> </div> </body> </html>
3.异步组件
Vue.component(组件名称,(resolve,reject)=>{ axios.get(url).then(res=>{ resolve({ template:res.data }); }); });
exp:
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <script src="vue.js"></script> <script src="axios.js"></script> <script> Vue.component("mycomp",(resolve,reject)=>{ axios.get("abc2.html").then(res=>{ setTimeout(()=>{ console.log(res.data); let oDiv = document.createElement("div"); oDiv.innerHTML = res.data; //读取成功放到template resolve({ //template:res.data //template:oDiv.children[0].innerHTML template:oDiv.children[0] }); },2000); }); }); window.onload=function(){ let vm = new Vue({ el:"#app", }) } </script> </head> <body> <div id="app"> <mycomp></mycomp> </div> </body> </html>
4.组件的生命周期
activated //激活
deactivated //休眠
必须跟 keep-alive标签
<keep-alive> <div :is="'组件名称'"></div> </keep-alive>
exp:
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <script src="vue.js"></script> <script> Vue.component("aaa",{ template:`<div>组件A</div>`, activated(){ console.log("A-----activated");//激活 }, deactivated(){ console.log("A-----deactivated");//休眠 }, beforeDestroy(){ console.log("A-----beforeDestroy"); }, destroyed(){ console.log("A-----destroyed"); }, }); Vue.component("bbb",{ template:`<div>组件B</div>`, activated(){ console.log("B-----activated");//激活 }, deactivated(){ console.log("B-----deactivated");//休眠 }, beforeDestroy(){ console.log("B-----beforeDestroy"); }, destroyed(){ console.log("B-----destroyed"); }, }); window.onload = function(){ vm = new Vue({ el:"#app", data:{ a:"aaa" }, methods:{ toggle(){ this.a = this.a == "aaa"?"bbb":"aaa"; } } }); }; </script> </head> <body> <div id="app"> <input @click="toggle" type="button" value="toggle"/> <keep-alive> <div :is="a"></div> </keep-alive> </div> </body> </html>
res:
错误的生命周期
errorCaptured
执行条件:
只能捕获子组件的异常,无法捕获自己发生的错误!
异常会冒泡!
exp:
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <script src="vue.js"></script> <script> //异常会冒泡 Vue.component("aaa",{ template:`<div>组件A <bbb></bbb></div>`, errorCaptured(){//捕获异常 console.log("A-----errorCaptured"); }, }); Vue.component("bbb",{ template:`<div>组件B</div>`, data(){ return { a //a is not defined } }, errorCaptured(){ console.log("B-----errorCaptured"); } }); window.onload = function(){ vm = new Vue({ el:"#app", data:{ //a }, errorCaptured(){ console.log("Vue-----errorCaptured"); } }); }; </script> </head> <body> <div id="app"> <aaa></aaa> </div> </body> </html>
冒泡:bbb-->aaa-->app
res:
5.组件渲染:
Vue 推荐在绝大多数情况下使用 template 来创建你的 HTML。然而在一些场景中,你真的需要 JavaScript 的完全编程的能力,这就是 render 函数,它比 template 更接近编译器。
render(createElement){ return createElement( "h1", // tag name 标签名称 "标题" //内容: {属性:{属性值}}} ) }
exp:
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <script src="vue.js"></script> <script> window.onload = function(){ let vm = new Vue({ el:"#app", render(createElement){ return createElement( "ul", // tag name 标签名称 { attrs: { id: 'ul1' }, 'class': { foo: true, bar: false }, style: { color: 'red', fontSize: '14px' }, }, [ createElement("li","111"), createElement("li","222"), createElement("li","333"), ] ) } }); }; </script> </head> <body> <div id="app"> <!-- <ul> <li>111</li> <li>222</li> <li>333</li> </ul> --> </div> </body> </html>
res:
6.混入
合并.
exp:
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <script src="vue.js"></script> <script> let json1 = { data:{ msg:"abc", a:"a", b:"b", }, methods:{ fn(){ console.log("fn"); } } }; let json2 = { data:{ c:"c", }, computed:{ computedXXX(){ console.log("computedXXX"); } } , watch:{ c(){ console.log("watch c"); } } } window.onload = function(){ let vm = new Vue({ //mixins: [json], el:"#app", data:{ msg:"Vue", }, methods:{ show(){ console.log("show"); } }, mixins: [json1,json2], }); console.log(vm); }; </script> </head> <body> <div id="app"> </div> </body> </html>
res:
对与父组件已存在的实例,不会被改变
7.自定义指令
v-xxx
Vue.directive("xxx", function (el, binding) { console.log(el,binding); el.style.color = "xxx"; })
v-red 字体变红
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <script src="vue.js"></script> <script> Vue.directive("red", function (el, binding) { console.log(el,binding); el.style.color = "red"; }) window.onload = function(){ let vm = new Vue({ el:"#app", }); console.log(vm); }; </script> </head> <body> <div id="app"> <div v-red>自定义指令</div> </div> </body> </html>
res:
v-color="'red'" 字体变红
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <script src="vue.js"></script> <script> Vue.directive("color", function (el, binding) { console.log(el,binding); el.style.color = binding.value; }) window.onload = function(){ let vm = new Vue({ el:"#app", }); }; </script> </head> <body> <div id="app"> <div v-color="'red'">自定义指令</div> </div> </body> </html>
res:
自定义样式style
v-style="{width:'200px',height:'200px',background:'green'}"
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <script src="vue.js"></script> <script> /* Vue.directive("style", function (el, binding) { console.log(el,binding); for(let name in binding.value){ el.style[name] = binding.value[name]; } }) */ window.onload = function(){ let vm = new Vue({ el:"#app", directives:{ style(el, binding){ console.log(el,binding); for(let name in binding.value){ el.style[name] = binding.value[name]; } } } }); }; </script> </head> <body> <div id="app"> <div v-style="{width:'200px',height:'200px',background:'green'}">自定义指令</div> </div> </body> </html>
res:
自定义拖拽:v-drag
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <script src="vue.js"></script> <script> Vue.directive("drag",{ bind(el, binding){ console.log("bind"); el.style.position = "absolute"; el.style.left = 0; el.style.top = 0; el.style.width = "100px"; el.style.height = "100px"; el.style.background = "red"; }, inserted(el, binding){ el.onmousedown = function(ev){ let disX = ev.clientX - el.offsetLeft; let disY = ev.clientY - el.offsetTop; document.onmousemove = function(ev){ el.style.left = ev.clientX - disX + "px"; el.style.top = ev.clientY - disY + "px"; }; document.onmouseup = function(){ document.onmousemove = null; document.onmouseup = null; }; return false; }; }, update(el, binding){ console.log("update"); }, componentUpdated(el, binding){ console.log("componentUpdated"); }, unbind(el, binding){ console.log("unbind"); }, }) window.onload = function(){ let vm = new Vue({ el:"#app", data:{ msg:"Vue", a:true, }, methods:{ show(){ this.a = false; this.msg = Math.random(); } } }); }; </script> </head> <body> <div id="app"> <div v-if="a" @click="show" v-drag>自定义指令 {{msg}}</div> </div> </body> </html>
res:
v-if: 与unbind
8.过滤器
过滤器:
https://cn.vuejs.org/v2/api/?#Vue-filter
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <script src="vue.js"></script> <script> //首字母大写 Vue.filter("capitalize", function (str) { return str.charAt(0).toUpperCase() + str.substring(1); }); //字符串反转 /*Vue.filter("reverse", function (str) { return str.split("").reverse().join(""); });*/ window.onload = function(){ let vm = new Vue({ el:"#app", data:{ msg:"vue", }, //字符串反转 filters:{ reverse(str){ return str.split("").reverse().join(""); } } }); }; </script> </head> <body> <div id="app"> <input v-model="msg" type="text" value=""/><br /> {{msg}}<br /> {{msg|capitalize}}<br /> {{msg|reverse}}<br /> {{msg|reverse|capitalize}}<br /> {{msg|capitalize|reverse}}<br /> </div> </body> </html>
res:
9.nextTick
nextTick https://cn.vuejs.org/v2/api/#Vue-nextTick
将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。它跟全局方法 Vue.nextTick 一样,不同的是回调的 this 自动绑定到调用它的实例上。
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <script src="vue.js"></script> <script> window.onload = function(){ let vm = new Vue({ el:"#app", data:{ msg:"vue", }, methods:{ show(){ this.msg = Math.random(); this.$nextTick(function(){ let oSpan = document.getElementById("s1"); console.log(oSpan.innerHTML); }); } } }); }; </script> </head> <body> <div id="app"> <input @click="show" type="button" value="按钮"/><br /> <span id="s1">{{msg}}</span> </div> </body> </html>
res:
++不加nextTick,console.log(oSpan.innerHTML)中的结果是上一次的内容.++
来源:https://www.cnblogs.com/zhongchao666/p/9463005.html