学习笔记-Vue 发表于 2022-11-26 | 更新于 2023-02-21
| 阅读量:
基本概念 MVVM设计模式 在MVVM设计模式中由3个部分组成:
M:Model,数据模型(保存数据,处理数据业务逻辑)
V:View,视图(展示数据,与用户交互)
VM:View Model,数据模型和视图的桥梁(M是中国人,V是美国人,VM就是翻译)
MVVM设计模式最大的特点就是支持数据的双向传递。数据可以从M => VM => V ;也可以从 V => VM =>M
Vue就是基于MVVM设计模式的
被控制的区域:View
Vue实例对象:View Model
实例对象中的data:Model
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <div id ="app" > <p v-once > 姓名:{{ name }}</p > </div > <script > const vue = new Vue({ el : '#app' , data : { name : "zs" , msg : "百度" } }); </script >
数据双向传递 默认情况下,Vue只支持数据单项传递M => VM => V。
但是由于Vue是基于MVVM设计模式的,所以也提供了双向传递的能力。
在 <input> <textarea> <select> 元素上可以用 v-model 指令创建双向数据绑定。
1 2 3 4 5 6 7 8 9 10 11 12 13 <div id ="app" > <input type ="text" v-model ="msg" > </div > <script > const vue = new Vue({ el : '#app' , data : { name : "zs" , msg : "百度" } }); </script >
Vue配置项 开始使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <script src ="https://cdn.jsdelivr.net/npm/vue@2" > </script > <div id ="app" > {{ name }}</div > <script > const vue = new Vue({ el : '#app' , data : { name : "zs" } }); </script >
methods 定义函数 用于存储监听事件回调函数
详见 指令 => v-on
directives 定义指令 用于定义局部指令
详见 指令 => 自定义指令
components 定义组件 用于定义局部组件
详见 组件 => 局部组件
watch 监听数据变化、监听路由变化
详见 Vue Router => 监听路由变化
render 渲染方式 Vue渲染组件的两种方式:
1.先定义注册组件,然后在Vue实例中当作标签来使用
2.先定义注册组件,然后通过Vue实例的render方法来渲染
两种渲染的区别:
1.当作标签来渲染,不会覆盖Vue实例控制区域
2.通过render方法来渲染,会覆盖Vue实例控制区域
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <div id ="app" > </div > <template id ="one" > <div > <h1 > 我是组件6666</h1 > </div > </template > <script > Vue.component("xyz" , { template : "#one" }); const vue = new Vue({ el : '#app' , render : function (createElement ) { return createElement("xyz" ); }, data : {}, methods : {} }); </script >
computed 计算属性 专门用于定义计算属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <div id ="app" > <p > {{msg}}</p > </div > <script > const vue = new Vue({ el : '#app' , data : {}, methods : {}, directives : {}, computed : { msg : function ( ) { let res = "abcdef" .split("" ).reverse().join("" ); return res; } } }); </script >
计算属性computed 和 函数methods 的区别
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 <div id ="app" > <p > {{msg1()}}</p > <p > {{msg1()}}</p > <p > {{msg1()}}</p > <p > {{msg2}}</p > <p > {{msg2}}</p > <p > {{msg2}}</p > </div > <script > const vue = new Vue({ el : '#app' , data : {}, methods : { msg1 ( ) { console .log("函数msg1()被执行了" ); let res = "abcdef" .split("" ).reverse().join("" ); return res; } }, directives : {}, computed : { msg2 : function ( ) { console .log("计算属性msg2被执行了" ); let res = "abcdef" .split("" ).reverse().join("" ); return res; } } }); </script >
filters 过滤器 过滤器和函数和计算属性一样都是用来处理数据的。但是过滤器一般用于格式化插入的文本数据
自定义全局过滤器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <div id ="app" > <p > {{name | chulidaxue}}</p > <p > {{name | chulidaxue | chulibaidu}}</p > </div > <script > Vue.filter("chulidaxue" , function (value ) { value = value.replace(/大学/g , "学院" ); return value; }); Vue.filter("chulibaidu" , function (value ) { value = value.replace(/百度/g , "淘宝" ); return value; }); const vue = new Vue({ el : '#app' , data : { name : "百度大学,JS大学,前端大学" } }); </script >
自定义局部过滤器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <div id ="app" > <p > {{name | chulidaxue}}</p > <p > {{name | chulidaxue | chulibaidu}}</p > </div > <script > const vue = new Vue({ el : '#app' , data : { name : "百度大学,JS大学,前端大学" }, filters : { "chulidaxue" : function (value ) { value = value.replace(/大学/g , "学院" ); return value; }, "chulibaidu" : function (value ) { value = value.replace(/百度/g , "淘宝" ); return value; } } }); </script >
案例:利用过滤器对时间进行格式化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 <div id ="app" > <p > {{time | dateFormart("yyyy-MM-dd")}}</p > <p > {{time | dateFormart()}}</p > </div > <script > Vue.filter("dateFormart" , function (value, fmStr ) { let date = new Date (value); let year = date.getFullYear(); let month = date.getMonth() + 1 + "" ; let day = date.getDate() + "" ; let hour = date.getHours() + "" ; let minute = date.getMinutes() + "" ; let second = date.getSeconds() + "" ; if (fmStr && fmStr === "yyyy-MM-dd" ) { return `${year} -${month.padStart(2 , "0" )} -${day.padStart(2 , "0" )} ` ; } return `${year} -${month.padStart(2 , "0" )} -${day.padStart(2 , "0" )} ${hour.padStart(2 , "0" )} :${minute.padStart(2 , "0" )} :${second.padStart(2 , "0" )} ` ; }); const vue = new Vue({ el : '#app' , data : { time : Date .now() }, }); </script >
生命周期方法 和wbpack生命周期方法一样,都是从生到死的特定阶段调用的方法。生命周期钩子=生命周期函数=生命周期事件
创建期间的生命周期方法:
beforeCreate:仅仅表示Vue实例刚被创建出来,还没有初始化好实例中的数据和方法,所以此时不能访问实例中的data和methods
created:能够访问实例中保存的data和methods
beforeMount:Vue已经编译好了最终模板,但是还没有渲染到界面上
mounted:完成了模板的渲染,可以拿到界面上渲染之后的内容了
运行期间的生命周期方法:
beforeUpdate: 调用beforeUpdate表示Vue实例中保存的数据被修改了(未修改不会调用); 此时界面的数据还没有更新
updated:数据被修改并且界面也同步了修改的数据。即:数据和界面都同步更新之后就会调用 updated
销毁期间的生命周期方法:
beforeDestroy:表示当前即将被销毁(未销毁不会调用);依然能访问data和methods
destroyed:表示当前组件已经被销毁。不要在这个生命周期方法中再去操作组件中的数据和方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <div id ="app" > <input v-model ="num" > </div > <script > const vue = new Vue({ el : '#app' , data : { num : 0 }, mounted :function ( ) { }, updated : function ( ) { console .log(this .num); }, }); </script >
指令 指令就是Vue内部提供的一些自定义属性,这些属性中封装好了Vue内部实现的一些功能,只要使用这些指令就可以使用Vue中实现的这些功能。通过这些指令可以让 Vue 对一个 DOM元素进行各种骚操作,如 v-once、 v-model 等指令。
Vue文档-指令
v-text 1 2 3 <span v-text ="msg" > 这里有文字也不会显示,只实现msg</span > <span > {{msg}}</span >
v-html 在你的站点上动态渲染任意的 HTML 是非常危险的,因为它很容易导致 XSS 攻击。请只对可信内容使用 HTML 插值,绝不要将用户提供的内容作为插值
1 2 3 4 5 6 7 8 9 10 11 12 13 <div id ="app" > <p v-html ="msg" > 这里写什么都不显示</p > </div > <script > const vue = new Vue({ el : '#app' , data : { name : "zs" , msg : "<div>我是div</div>" } }); </script >
v-if v-if v-else-if v-else 的元素必须紧跟在一起,否则不能识别。
如果取值为true,就渲染元素
取值为false就不会渲染元素(重点注意)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <div id ="app" > <p v-if ="name" > 写什么就显示什么</p > <p v-if > 写什么就显示什么</p > <p v-if > {{name}}</p > <p v-if =" fenshu>85 " > 优秀</p > <p v-else-if =" fenshu>60 " > 良好</p > <p v-else > 不及格</p > </div > <script > const vue = new Vue({ el : '#app' , data : { name : "zs" , fenshu : 59 } }); </script >
v-show v-show 和 v-if 一样,都是用来条件渲染的,取值为true就显示;取值为false就不显示。
v-show 取值为false也会创建元素,只是给该元素加了 display:none
v-if 取值为false不会创建该元素
频繁切换/显示时,v-if频繁创建/删除元素更消耗性能。所以企业开发中需要频繁切换显示元素,就是用v-show,否则使用v-if
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <div id ="app" > <p v-show > 错误写法,但不报错,只是不显示</p > <p v-show ="name" > 这里写什么就显示什么</p > <p v-show =" fenshu>85 " > 优秀</p > <p v-show =" fenshu>=60 " > 良好</p > <p v-show =" fenshu<60 " > 不及格</p > </div > <script > const vue = new Vue({ el : '#app' , data : { name : "zs" , fenshu : 60 } }); </script >
v-for 相当于js中的 for in 循环,可以根据数据多次渲染元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 <div id ="app" > <span v-for ="(value,index) in name" > ▮索引{{index}}对应值是{{value}}</span > <hr > <span v-for ="(value,index) in '字符串abc123'" > ▮索引{{index}}对应值是{{value}}</span > <hr > <span v-for ="(value,key) in obj" > ▮键{{key}}对应值{{value}}</span > </div > <script > const vue = new Vue({ el : '#app' , data : { name : ["张三" , "李四" , "王五" , "麻子" ], obj : { name : "zs" , age : 18 , web : "www.baidu.com" } } }); </script >
v-for注意点-数据混乱:
v-for为了提升性能,在更新已渲过的元素列表时,会采用“就地复用”策略。也正是因为这个策略,在某些时刻会导致我们的数据混乱。
为了解决这个问题,我们可以在渲染列表的时候给每一个元素加上一个独一无二的key。v-for在更新已渲染过的元素列表时,会先判断key是否相同,如果相同则复用,不同则重新创建
key属性注意点:不能用索引index作为key,因为当列表的内容新增或者删除时index都会发生变化。这就导致了不能很好地复用没有发生改变的元素,大大降低了渲染效率。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 <div id ="app" > <form > <input type ="text" v-model ="name" > <input type ="submit" value ="添加" @click.prevent ="add" > </form > <ul > <li v-for ="(person,index) in persons" :key ="person.id" > <input type ="checkbox" > <span > {{index}} --- {{person.name}}</span > </li > </ul > </div > <script > let vue = new Vue({ el : '#app' , data : { persons : [ { name : "zs" , id : 1 }, { name : "ls" , id : 2 }, { name : "ww" , id : 3 } ], name : "" }, methods : { add ( ) { let lastPerson = this .persons[this .persons.length - 1 ]; let newPerson = { name : this .name, id : lastPerson.id + 1 }; this .persons.unshift(newPerson); this .name = "" ; } }, computed : {} }); </script >
v-bind 在企业开发中想要给“元素”绑定数据,可以使用{{}},v-text,v-html。但是如果想给“元素的属性”绑定数据,就必须使用v-bind。v-bind 的作用就是专门用于给“元素的属性”绑定数据的
对于大部分的属性而言,我们只需要直接赋值就可以,例如: :value="name"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <div id ="app" > <input type ="text" v-bind:value ="name" > <input type ="text" :value ="name" > <input type ="text" :value ="age" > <input type ="text" :value ="age+1" > </div > <script > const vue = new Vue({ el : '#app' , data : { name : "zs" , age : 18 } }); </script >
绑定类名 class
格式: :class="['类名',...]"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <style > .size {font-size : 48px ;} .color {color : red;} .bg {background : blue;} </style > <div id ="app" > <p :class ="size" > 我是段落</p > <p :class =[ 'size ','color ','bg ']> 我是段落</p > </div > <script > const vue = new Vue({ el : '#app' , data : { flag :true } }); </script >
绑定样式 style
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <div id ="app" > <p :style ="{color:'red'}" > 段落P</p > <p :style ="{'font-size':'100px'}" > 段落P</p > <p :style ="obj1" > 段落P</p > <p :style ="[obj1,obj2]" > 段落P</p > </div > <script > const vue = new Vue({ el : '#app' , data : { obj1 : { "font-size" : "50px" , "color" : "red" }, obj2 : { "background" : "blue" } } }); </script >
v-on 绑定监听事件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 <div id ="app" > <button v-on:click ="fn1" > 我是按钮</button > <button @click.once ="fn1" > 我是fn1</button > ] <button @click ="fn2('zs',18)" > 我是fn2</button > <button @click ="fn3($event)" > 我是fn3</button > <button @click ="fn4" > 我是fn4</button > </div > <script > const vue = new Vue({ el : '#app' , data : { name : "zs" }, methods : { fn1 ( ) { alert("fn1被点击了" ) }, fn2 (name, age ) { console .log(name, age); }, fn3 (e ) { console .log(e); }, fn4 ( ) { console .log(this .name); } } }); </script >
事件修饰符
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <button @click.once ="fn1" > 我是fn1</button > .once ——最多触发一次处理函数。 .prevent ——调用 event.preventDefault();默认事件不会执行,比如a链接跳转 .stop ——调用 event.stopPropagation();阻止事件冒泡 .self ——只有事件从元素本身发出才触发处理函数。 .capture ——在捕获模式添加事件监听器;事件冒泡变成事件捕获 .passive ——通过 { passive: true } 附加一个 DOM 事件。 ###鼠标按键修饰符 .left ——只在鼠标左键事件触发处理函数。 .right ——只在鼠标右键事件触发处理函数。 .middle ——只在鼠标中键事件触发处理函数。 .{keyAlias} ——只在某些按键下触发处理函数。
按键修饰符:监听特定按键触发的事件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 .enter .tab .delete (捕获“删除”和“退格”键) .esc .space .up .down .left .right <div id ="app" > <input type ="text" @keyup.enter ="fn1" > <input type ="text" @keyup.f2 ="fn1" > </div > <script > Vue.config.keyCodes.f2 = 113 const vue = new Vue({ el : '#app' , methods : { fn1 ( ) { alert("按键事件触发了" ) } } }); </script >
v-model 数据双向传递,只有 <input> <textarea> <select> 元素上可以使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <div id ="app" > <input type ="text" v-model ="name" > <p > 我的姓名是{{name}}</p > </div > <script > const vue = new Vue({ el : '#app' , data : { name : "zs" } }); </script >
v-once vue默认数据绑定:当数据发生变化,界面也会随着变化。v-once可以控制该元素和组件只渲染一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <span v-once > {{msg}}</span > <div v-once > <h1 > comment</h1 > <p > {{msg}}</p > </div > <MyComponent v-once :comment ="msg" /> <ul > <li v-for ="i in list" v-once > {{i}}</li > </ul >
v-cloak 1 2 3 4 5 6 7 8 9 10 <p > {{msg}}</p > <style > [v-cloak] {display : none;} </style > <p v-cloak > {{msg}}</p >
自定义指令 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 <div id ="app" > <p v-color ="'red'" > 自定义指令</p > </div > <script > Vue.directive("color" , { bind : function (el, binding ) { el.style.color = binding.value; } }) const vue = new Vue({ el : '#app' , data : {}, methods : {}, directives : { "color" : { bind : function (el, binding ) { el.style.color = binding.value; } } } }); </script >
过度动画 使用默认类名CSS 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 <style > .box { width : 100px ; height : 100px ; background-color : bisque; } .v-enter { opacity : 0 ; } .v-enter-to { opacity : 1 ; } .v-enter-active { transition : all 3s ; } .v-leave { opacity : 1 ; } .v-leave-to { opacity : 0 ; } .v-leave-active { transition : all 2s ; } .one-enter { opacity : 0 ; } .one-enter-to { opacity : 1 ; } .one-enter-active { transition : all 10s ; } .one-leave { opacity : 1 ; } .one-leave-to { opacity : 0 ; } .one-leave-active { transition : all 10s ; } </style > <div id ="app" > <button @click ="toggle" > 我是按钮</button > <transition > <div class ="box" v-show ="isShow" > </div > </transition > <transition appear > <div class ="box" v-show ="isShow" > </div > </transition > <transition appear name ="one" > <div class ="box" v-show ="isShow" > </div > </transition > <transition appear name ="one" > <div class ="box" v-show ="isShow" > </div > </transition > </div > <script > const vue = new Vue({ el : '#app' , data : { isShow : false }, methods : { toggle ( ) { this .isShow = !this .isShow; } } }); </script >
JavaScript 钩子 1 2 3 4 5 6 7 8 9 10 11 12 13 <transition v-on:before-enter ="beforeEnter" v-on:enter ="enter" v-on:after-enter ="afterEnter" v-on:enter-cancelled ="enterCancelled" v-on:before-leave ="beforeLeave" v-on:leave ="leave" v-on:after-leave ="afterLeave" v-on:leave-cancelled ="leaveCancelled" > </transition >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 <div id ="app" > <button @click ="toggle" > 我是按钮</button > <transition v-bind:css ="false" v-on:before-enter ="beforeEnter" v-on:enter ="enter" v-on:after-enter ="afterEnter" > <div class ="box" v-show ="isShow" > </div > </transition > </div > <script > const vue = new Vue({ el : '#app' , data : { isShow : false }, methods : { toggle ( ) { this .isShow = !this .isShow; }, beforeEnter (el ) { el.style.opacity = "0" ; }, enter (el, done ) { el.offsetWidth; el.style.transition = "all 3s" ; done(); }, afterEnter (el ) { el.style.opacity = "1" ; } } }); </script >
Animate.css 自定义过度类名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 enter-class enter-active-class enter-to-class leave-class leave-active-class leave-to-class <style > .box { width : 100px ; height : 100px ; background-color : bisque; } .a {opacity : 0 ;} .c {opacity : 1 ;} .b {transition : all 3s ;} </style > <div id ="app" > <button @click ="toggle" > 我是按钮</button > <transition enter-class ="a" enter-active-class ="b" enter-to-class ="c" > <div class ="box" v-show ="isShow" > </div > </transition > </div >
结合Animate.css
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 <script src ="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js" > </script > <link href ="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel ="stylesheet" type ="text/css" > <div id ="app" > <button @click ="toggle" > 我是按钮</button > <transition enter-active-class ="animated bounce" > <div class ="box" v-show ="isShow" > </div > </transition > </div > <script > const vue = new Vue({ el : '#app' , data : { isShow : false }, methods : { toggle ( ) { this .isShow = !this .isShow; } } }); </script >
列表动画 transition只能添加一个元素,如果有多个元素,可以使用 transition-group
子元素必须要有唯一的key属性,且key不能为索引值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <div id ="app" > <button @click ="toggle" > 我是按钮</button > <transition-group enter-active-class ="animated bounce" tag ="div" > <div class ="box animated bounce" v-show ="isShow" :key ="1" > </div > <div class ="box animated bounce" v-show ="isShow" :key ="2" > </div > <div class ="box animated bounce" v-show ="isShow" :key ="3" > </div > </transition-group > </div > <script > const vue = new Vue({ el : '#app' , data : { isShow : false }, methods : { toggle ( ) { this .isShow = !this .isShow; } } }); </script >
组件 组件命名注意点 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 1.注册组件的时候使用了驼峰命名,那么在使用组件的时候需要转换成短横线分割命名 <use-com > </use-com > Vue.components("useCom",....) 2.传递数据的时候如果想使用驼峰命名,那么就必须写短横线分割命名 <son :father-name ="name" > </son > props: ["fatherName"] 3.传递方法的时候不能使用驼峰命名,只能使用短横线分割命名 <son @father-say ="say" > </son > this.$emit("father-say");
全局组件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 <div id ="app" > <news > </news > </div > <script > var Profile = Vue.extend({ template : ` <div> <img src = "abc.jpg"/> <p>我是描述信息</p> </div> ` }); Vue.component("news" , Profile); const vue = new Vue({ el : '#app' , data : { name : "zs" } }); </script > <div id ="app" > <news > </news > </div > <template id ="info" > <div > <img src ="abc.jpg" /> <p > 我是描述信息</p > </div > </template > <script > var Profile = Vue.extend({ template : "#info" }); Vue.component("news" , Profile); const vue = new Vue({ el : '#app' , data : { name : "zs" } }); </script >
简写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <div id ="app" > <news > </news > </div > <template id ="info" > <div > <img src ="abc.jpg" /> <p > 我是描述信息</p > </div > </template > <script > Vue.component("news" , { template : "#info" }); const vue = new Vue({ el : '#app' , data : { name : "zs" } }); </script >
局部组件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <div id ="app" > <abc > </abc > </div > <template id ="info" > <div > <img src ="abc.jpg" /> <p > 我是描述信息</p > </div > </template > <script > const vue = new Vue({ el : '#app' , data : {}, components : { "abc" : { template : "#info" } } }); </script >
组件中的data和methods vue实例控制的区域相当于一个大的组件,在大的组件中我们可以使用data和methods。
而我们自定义的组件也是一个组件,所以在自定义的组件中也能使用data和methods
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 <div id ="app" > <abc > </abc > </div > <template id ="info" > <div > <button @click ="appFn" > 我是按钮</button > <p > {{msg1}}</p > <img src ="abc.jpg" /> </div > </template > <script > Vue.component("abc" , { template : "#info" , methods : { appFn ( ) { alert("被点击了" ); } }, data : function ( ) { return { msg1 : "自定义组件中使用data必须赋值一个函数,然后通过函数的返回值来定义" , msg2 : "-------------------------------" , msg3 : "组件中的data如果不是通过函数返回的,那么多个组件就会共用一份数据,就会导致数据混乱。" , msg4 :"通过函数返回,那么每创建一个新的组件,都会调用一次这个方法" , msg5 :"将这个方法返回的数据和当前创建的组件绑定在一起,这样就有效的避免了数据混乱" } } }); const vue = new Vue({ el : '#app' , data : {}, }); </script >
组件切换 动态组件是专门用来切换组件的,也就是你让我显示谁,我就显示谁。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 <component v-bind:is ="需要显示组件的名称" > </component > <div id ="app" > <component v-bind:is ="'abc'" > </component > <button @click ="qiehuan" > 切换页面</button > <keep-alive > <component v-bind:is ="name" > </component > </keep-alive > </div > <template id ="home" > <div > <h1 > 我是首页</h1 > <input type ="checkbox" > </div > </template > <template id ="post" > <div > <h1 > 我是文章页</h1 > </div > </template > <script > Vue.component("abc" , { template : "#home" }); Vue.component("xyz" , { template : "#post" }); const vue = new Vue({ el : '#app' , data : { name : "abc" }, methods : { qiehuan ( ) { this .name = this .name === "abc" ? "xyz" : "abc" } } }); </script >
组件动画 给组件添加动画和过去给元素添加动画一样。如果是单个组件组件就使用,多个组件就使用
默认情况下进入动画和离开动画是同时执行的,如果想一个做完之后再做另一个,需要指定动画模式
in-out:新元素先进行过渡,完成之后当前元素过渡离开。
out-in:当前元素先进行过渡,完成之后新元素过渡进入。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 <div id ="app" > <button @click ="qiehuan" > 切换页面</button > <transition mode ="out-in" > <component v-bind:is ="name" > </component > </transition > </div > <template id ="home" > <div > <h1 > 我是首页</h1 > <input type ="checkbox" > </div > </template > <template id ="post" > <div > <h1 > 我是文章页</h1 > </div > </template > <script > Vue.component("abc" , { template : "#home" }); Vue.component("xyz" , { template : "#post" }); const vue = new Vue({ el : '#app' , data : { name : "abc" }, methods : { qiehuan ( ) { this .name = this .name === "abc" ? "xyz" : "abc" } } }); </script > <style > .v-enter { opacity : 0 ; } .v-enter-to { opacity : 1 ; } .v-enter-active { transition : all 3s ; } .v-leave { opacity : 1 ; } .v-leave-to { opacity : 0 ; } .v-leave-active { transition : all 2s ; } </style >
父子组件 在一个组件中又定义了其它组件,就是父子组件。
局部组件就是最简单的父子组件,因为Vue实例可以看做是一个大组件,在Vue实例中定义了局部组件,就相当于在大组件里定义了小组件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 <div id ="app" > <father > <son > </son > </father > </div > <template id ="father" > <div > <h1 > 我是father组件</h1 > <son > </son > </div > </template > <template id ="son" > <div > <h2 > 我是son组件</h2 > </div > </template > <script > Vue.component("father" , { template : "#father" , components : { "son" : { template : "#son" } } }); const vue = new Vue({ el : '#app' , data : { name : "abc" } }); </script > <div id ="app" > <father > <son > </son > </father > </div > <template id ="father" > <div > <h1 > 我是father组件</h1 > <son > </son > </div > </template > <template id ="son" > <div > <h2 > 我是son组件</h2 > </div > </template > <script > const vue = new Vue({ el : '#app' , data : { name : "abc" }, components : { "father" : { template : "#father" , components : { "son" : { template : "#son" } } } } }); </script >
父子组件-传递数据 Vue中子组件是不能访问父组件数据的。子组件想要访问父组件的数据,必须通过父组件传递
先在父组件中通过 v-bind 传递数据: v-bind:自定义接收名称 = “要传递数据”
然后在组件中中通过 props 接收数据: props:[“自定义接收名称”]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 <div id ="app" > <father > </father > </div > <template id ="father" > <div > <son v-bind:fathername ="name" v-bind:fathersite ="site" > </son > <son :fathername ="name" :fathersite ="site" > </son > </div > </template > <template id ="son" > <div > <p > {{fathername}}</p > <p > {{fathersite}}</p > </div > </template > <script > Vue.component("father" , { template : "#father" , data : function ( ) { return { name : "百度" , site : "www.baidu.com" } }, components : { "son" : { template : "#son" , props : ["fathername" , "fathersite" ] } } }); const vue = new Vue({ el : '#app' , data : { name : "abc" } }); </script >
父子组件-传递方法 和传递数据不同,传递方法子组件不需要接收。只需要在子组件中自定义一个方法,通过 this.$emit(‘自定义接收名称’) 的方法来触发父组件传递过来的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 <div id ="app" > <father > </father > </div > <template id ="father" > <div > <button @click ="say" > 我是父组件</button > <son v-on:fathersay ="say" > </son > <son @fathersay ="say" > </son > </div > </template > <template id ="son" > <div > <button @click ="sonsay" > 我是子组件</button > </div > </template > <script > Vue.component("father" , { template : "#father" , methods : { say ( ) { alert("hello" ); } }, components : { "son" : { template : "#son" , methods : { sonsay ( ) { this .$emit("fathersay" ); } } } } }); const vue = new Vue({ el : '#app' , data : { name : "abc" } }); </script >
子组件传递数据给父组件 既然父组件的方法可以传递给子组件,子组件可以调用父组件中的方法;那么我们就可以在调用方法的时候给方法传递参数,传递的参数就是我们需要传递的数据。
多级传递 在Vue中如果儿子要使用爷爷的数据和方法,必须一层一层往下传递
匿名插槽 多级组件中都可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 <div id ="app" > <father > <div > 我是新追加的内容</div > <p > 这里写多少就会显示多少,即这里N个内容对应下面一个slot</p > </father > </div > <template id ="father" > <div > <div > 我是头部</div > <slot > 我是匿名插槽默认内容</slot > <div > 我是底部</div > </div > </template > <script > Vue.component("father" , { template : "#father" , }); const vue = new Vue({ el : '#app' , data : { name : "abc" } }); </script >
具名插槽 多级组件中都可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 <div id ="app" > <father > <div slot ="1" > 百度</div > <p slot ="abc" > www.baidu.com</p > <p slot ="abc" > www.baidu.com</p > <p slot ="abc" > www.taobao.com</p > </father > </div > <template id ="father" > <div > <div > 头部</div > <slot name ="1" > 我是具名插槽1 默认内容</slot > <div > 内容</div > <slot name ="abc" > 我是具名插槽abc 默认内容</slot > <div > 底部</div > </div > </template > <script > Vue.component("father" , { template : "#father" , }); const vue = new Vue({ el : '#app' , data : { name : "abc" } }); </script >
v-slot 指令 Vue 2.6.0版本之后,新增了 v-slot 指令,用于替换具名插槽中的 slot 属性
必须写在template标签中
v-slot:1 可以简写成 #1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 <div id ="app" > <father > <template v-slot:1 > <div > 百度</div > <div > 淘宝</div > </template > <template #abc > <p > www.baidu.com</p > <p > www.taobao.com</p > </template > </father > </div > <template id ="father" > <div > <div > 头部</div > <slot name ="1" > 我是具名插槽1 默认内容</slot > <div > 内容</div > <slot name ="abc" > 我是具名插槽abc 默认内容</slot > <div > 底部</div > </div > </template > <script > Vue.component("father" , { template : "#father" , }); const vue = new Vue({ el : '#app' , data : { name : "abc" } }); </script >
作用域插槽 作用域插槽就是带数据的插槽,就是让父组件在填充子组件插槽内容时也能使用子组件的数据。
应用场景:子组件提供数据,父组件决定如何渲染
在子组件slot中通过 v-bind:数据名称="数据名称" 方式暴露数据
在父组件中通过 <template slot-scope="作用域名称"> 接收数据
2.6.0版本之后,v-slot 指令替换掉了 slot-scope
在父组件的 <template></template> 中通过 作用域名称.数据名称 方式使用数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 <div id ="app" > <father > </father > </div > <template id ="father" > <div > <son > <template #default ="abc" > <div > 我是填充内容 {{abc.sonname}}</div > <li v-for ="(xyz,index) in abc.sonname" > {{xyz}}</li > </template > </son > </div > </template > <template id ="son" > <div > <p > 我是头部{{name}}</p > <slot v-bind:sonname ="name" > 我是插槽默认内容{{name}}</slot > <p > 我是底部</p > </div > </template > <script > Vue.component("father" , { template : "#father" , components : { "son" : { template : "#son" , data : function ( ) { return { name : ["666" , "777" , 888 , 999 ] } } } } }); const vue = new Vue({ el : '#app' , data : { name : "abc" } }); </script >
vuex vuex是vue配套的公共数据管理工具,我们可以将共享的数据保存到vuex中,方便整个程序中的任何组件都可以获取和修改vuex中保存的公共数据。
state属性 用于保存共享数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 <script src ="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js" > </script > <script src ="https://unpkg.com/vuex@3" > </script > <div id ="app" > <grandfather > </grandfather > </div > <template id ="grandfather" > <div > <p > {{this.$store.state.name}}</p > <p > </p > <father > </father > </div > </template > <template id ="father" > <div > <p > {{this.$store.state.site}}</p > <son > </son > </div > </template > <template id ="son" > <div > <p > {{this.$store.state.name}}的网址是{{this.$store.state.site}}</p > </div > </template > <script > const store = new Vuex.Store({ state : { name : "百度" , site : "www.baidu.com" }, }); Vue.component("grandfather" , { template : "#grandfather" , store : store, components : { "father" : { template : "#father" , components : { "son" : { template : "#son" , } } } } }); const vue = new Vue({ el : '#app' , data : { name : "abc" } }); </script >
mutations属性 用于保存修改共享数据的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 <script src ="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js" > </script > <script src ="https://unpkg.com/vuex@3" > </script > <div id ="app" > <grandfather > </grandfather > </div > <template id ="grandfather" > <div > <button @click ="add" > 增加</button > <button @click ="sub" > 减少</button > <input type ="text" :value ="this.$store.state.age" > <father > </father > </div > </template > <template id ="father" > <div > <button @click ="add" > 增加</button > <button @click ="sub" > 减少</button > <input type ="text" :value ="this.$store.state.age" > </div > </template > <script > const store = new Vuex.Store({ state : { name : "百度" , age : 18 , }, mutations : { mAdd (state ) { state.age = state.age + 1 ; }, mSub (state ) { state.age = state.age - 1 ; } } }); Vue.component("grandfather" , { template : "#grandfather" , store : store, methods : { add ( ) { this .$store.commit("mAdd" ); }, sub ( ) { this .$store.commit("mSub" ); } }, components : { "father" : { template : "#father" , methods : { add ( ) { this .$store.commit("mAdd" ); }, sub ( ) { this .$store.commit("mSub" ); } }, } } }); const vue = new Vue({ el : '#app' , data : { name : "abc" } }); </script >
getters属性 用于保存计算属性。和Vue实例中的 computed 效果一样。以后想要把数据缓存起来:
组件中就用computed
Vuex中就用getters
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 <div id ="app" > <father > </father > </div > <template id ="father" > <div > <p > {{this.$store.getters.pinjie}}</p > <p > {{this.$store.getters.pinjie}}</p > <p > {{this.$store.getters.pinjie}}</p > </div > </template > <script > const store = new Vuex.Store({ state : { name : "百度" , }, mutations : {}, getters : { pinjie (state ) { console .log("getters方法被执行了" ); return state.name + "www.baidu.com" ; } } }); Vue.component("father" , { template : "#father" , store : store, }); const vue = new Vue({ el : '#app' , data : { name : "abc" } }); </script >
Vue Router Vue Router和 v-if/v-show 一样,是用来切换组件显示的。
v-if/v-show 是标记来切换(true/false)
Vue Router用哈希来切换(#/xxx)
比 v-if/v-show 强大的是,Vue Router不仅能够切换组件的显示,还能够在切换的时候传递参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 <script src ="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js" > </script > <script src ="https://unpkg.com/vue-router@3" > </script > <div id ="app" > <a href ="#/one" > 切换到第1个页面</a > <router-link to ="/one" tag ="button" > 切换到第1个页面</router-link > <router-link to ="/two" tag ="div" > 切换到第2个页面</router-link > <router-view > </router-view > </div > <template id ="one" > <div > <h1 > 我是第一个页面</h1 > </div > </template > <template id ="two" > <div > <h1 > 我是第二个页面</h1 > </div > </template > <script > const one = { template : "#one" }; const two = { template : "#two" } const routes = [ { path : "/" , redirect : '/one' }, { path : "/one" , component : one }, { path : "/two" , component : two }, ]; const router = new VueRouter({ routes : routes, linkActiveClass : "zdy-active" , }); const vue = new Vue({ el : '#app' , router : router, components : { one : one, two : two } }); </script >
传递参数 只要将Vue Router挂载到了Vue实例对象上,我们就可以通过vue.$route拿到路由对象;只要能拿到路由对象,就可以通过路由对象传递参数
方式1:通过URL参数(?key=value&key=value) 传递,通过 this.$route.query 获取
方式2:通过占位符传递(路由规则中 /:key/:key ,路径中 /value/value) ,通过 this.$route.params 获取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 <div id ="app" > <router-link to ="/one?name=百度&site=www.baidu.com" tag ="button" > 切换到第1个页面</router-link > <router-link to ="/two/淘宝/www.taobao.com" tag ="button" > 切换到第2个页面</router-link > <router-view > </router-view > </div > <template id ="one" > <div > <h1 > 我是第一个页面</h1 > </div > </template > <template id ="two" > <div > <h1 > 我是第二个页面</h1 > </div > </template > <script > const one = { template : "#one" , created : function ( ) { console .log(this .$route); console .log(this .$route.query.name); console .log(this .$route.query.site); } }; const two = { template : "#two" , created : function ( ) { console .log(this .$route); console .log(this .$route.params.name); console .log(this .$route.params.site); } } const routes = [ { path : "/" , redirect : '/one' }, { path : "/one" , component : one }, { path : "/two/:name/:site" , component : two }, ]; const router = new VueRouter({ routes : routes, }); const vue = new Vue({ el : '#app' , router : router, components : { one : one, two : two } }); </script >
嵌套路由 嵌套路由也称之为子路由,就是在被切换的组件中又切换其它子组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 <div id ="app" > <router-link to ="/one" tag ="button" > 切换到第1个页面</router-link > <router-link to ="/two" tag ="button" > 切换到第2个页面</router-link > <router-view > </router-view > </div > <template id ="one" > <div > <h1 > 我是第一个页面</h1 > <router-link to ="/one/onechildren1" tag ="button" > 切换到第一个子界面</router-link > <router-link to ="/one/onechildren2" tag ="button" > 切换到第二个子界面</router-link > <router-view > </router-view > </div > </template > <template id ="onechildren1" > <div > <h1 > 我是第一个页面的子页面1</h1 > </div > </template > <template id ="onechildren2" > <div > <h1 > 我是第一个页面的子页面2</h1 > </div > </template > <template id ="two" > <div > <h1 > 我是第二个页面</h1 > </div > </template > <script > const onechildren1 = { template : "#onechildren1" , }; const onechildren2 = { template : "#onechildren2" , }; const one = { template : "#one" , components : { onechildren1 : onechildren1, onechildren2 : onechildren2 } }; const two = { template : "#two" , } const routes = [ { path : "/one" , component : one, children : [ { path : "onechildren1" , component : onechildren1 }, { path : "onechildren2" , component : onechildren2 } ] }, { path : "/two" , component : two }, ]; const router = new VueRouter({ routes : routes, }); const vue = new Vue({ el : '#app' , router : router, components : { one : one, two : two } }); </script >
命名视图 命名视图和前面讲的插槽很像,都是让不同的出口显示不同的内容。命名视图就是当路由地址被匹配的时候指定多个出口,并且每个出口中显示的内容不同。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 <div id ="app" > <router-view name ="name1" > </router-view > <router-view name ="name2" > </router-view > </div > <template id ="one" > <div > <h1 > 我是第一个页面</h1 > </div > </template > <template id ="two" > <div > <h1 > 我是第二个页面</h1 > </div > </template > <script > const one = { template : "#one" , }; const two = { template : "#two" , } const routes = [ { path : "/" , components : { name1 : one, name2 : two } }, ]; const router = new VueRouter({ routes : routes, }); const vue = new Vue({ el : '#app' , router : router, components : { one : one, two : two } }); </script >
监听路由变化 Vue实例中,有一个watch属性,专门用于监听数据变化的,只要数据发生了变化,就会自动调用数据的回调方法
Watch属性还可以监听路由地址的变化;在企业开发中我们可以通过watch来判断当前界面是从哪个界面跳转过来的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 <div id ="app" > <input type ="text" v-model ="num1" > + <input type ="text" v-model ="num2" > = <input type ="text" disabled v-model ="res" > <router-link to ="/one" tag ="button" > 切换到第1个页面</router-link > <router-link to ="/two" tag ="button" > 切换到第2个页面</router-link > <router-view > </router-view > </div > <template id ="one" > <div > <h1 > 我是第一个页面</h1 > </div > </template > <template id ="two" > <div > <h1 > 我是第二个页面</h1 > </div > </template > <script > const one = { template : "#one" , }; const two = { template : "#two" , } const routes = [ { path : "/one" , component : one }, { path : "/two" , component : two }, ]; const router = new VueRouter({ routes : routes, }); const vue = new Vue({ el : '#app' , router : router, data : { num1 : 0 , num2 : 0 , res : 0 }, watch : { num1 : function ( ) { this .res = parseInt (this .num1) + parseInt (this .num2); }, num2 : function ( ) { this .res = parseInt (this .num1) + parseInt (this .num2); }, "$route.path" : function (newValue, oldValue ) { console .log(newValue, oldValue); } }, components : { one : one, two : two } }); console .log(vue.$route); </script >
ref操作DOM 不推荐原生的语法操作。推荐
在元素或者组件中,添加 ref=xxx 属性
在使用的地方通过 this.$refs.xxx 获取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 <div id ="app" > <button @click ="myFn" > 按钮</button > <input v-model ="num" ref ="myInput" > <one ref ="myOne" > </one > </div > <template id ="one" > <div > <h1 > 我是组件</h1 > </div > </template > <script > Vue.component("one" , { template : "#one" , data : function ( ) { return { msg : "百度" , } } }); const vue = new Vue({ el : '#app' , data : { num : 0 }, methods : { myFn ( ) { console .log(this .$refs); console .log(this .$refs.myInput); console .log(this .$refs.myInput.value); console .log(this .$refs.myOne); console .log(this .$refs.myOne.msg); } } }); </script >
Vue-CLI Vue-CLI是官方提供的脚手架工具,默认已经帮我们安装好了一套利用webpack管理vue的项目结构。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 npm install -g @vue/cli vue --version vue create xxx npm run serve npm run build
项目结构解读:
node_modules:存储了相关的依赖包
public:任何放置在public文件夹的静态资源都会被简单的复制,而不经过webpack。一般用于存储一些永远不会改变的静态资源或者webpack不支持的第三方库
src:代码文件夹
assets:存储项目中自己的一些静态文件(图片/字体等)
components:存储项目中的自定义组件(小组件、公共组件)
views:存储项目中的自定义组件(大组件、页面级组件、路由级别组件)
router:存储VueRouter相关文件
store:存储Vuex相关文件
App.vue:根组件
main.js :整个项目的入口文件