数据绑定 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 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <meta http-equiv ="X-UA-Compatible" content ="IE=edge" > <meta name ="viewport" content ="width=device-width, initial-scale=1.0" > <script src ="../vue.js" > </script > <title > Demo1</title > </head > <body > <div id ="root" > <h1 > hello:{{name.toUpperCase()}} !</h1 > <h4 > <input v-bind:value ="url" > <br > 单项数据绑定:<input :value ="url" > <br > <input v-model:value ="url" > <br > 双向数据绑定:<input v-model ="url" > <br > </h4 > </div > <script > Vue .config .productionTip = false ; new Vue ({ el : "#root" , data : { name : "zhangsan" , url : "http://gdpolar.top" } }); </script > </body > </html >
el与 data 的另外一种写法 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 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <meta http-equiv ="X-UA-Compatible" content ="IE=edge" > <meta name ="viewport" content ="width=device-width, initial-scale=1.0" > <script src ="../vue.js" > </script > <title > Document</title > </head > <body > <div id ="root" > <h1 > hello, {{name}}</h1 > </div > </body > <script > vm = new Vue ({ data ( ) { return { name : "zhangsan" } } }); vm.$mount("#root" ); </script > </html >
MVVM 模型
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 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <meta http-equiv ="X-UA-Compatible" content ="IE=edge" > <meta name ="viewport" content ="width=device-width, initial-scale=1.0" > <script src ="../vue.js" > </script > <title > Document</title > </head > <body > <div id ="root" > <h1 > hello, {{name}}</h1 > </div > </body > <script > vm = new Vue ({ data ( ) { return { name : "zhangsan" } } }); vm.$mount("#root" ); </script > </html >
Object.defineProperty 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 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <meta http-equiv ="X-UA-Compatible" content ="IE=edge" > <meta name ="viewport" content ="width=device-width, initial-scale=1.0" > <title > Document</title > <script > let person = { name : "zhangsan" }; Object .defineProperty (person, "name" , { value : "zhangsan" , configurable : true , writable : true , enumerable : true }); let myCar = {}; Object .defineProperty (myCar, "band" , { value : "wuling" }); Object .defineProperty (myCar, "band" , { value : "wuling" , configurable : false , writable : false , enumerable : false }); let agenumber = 18 ; let st = { name : "lisi" }; Object .defineProperty (st, "age" , { get ( ) { return agenumber; }, set (v ) { agenumber = v; } }); console .log (st); </script > </head > <body > </body > </html >
数据代理
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 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <meta http-equiv ="X-UA-Compatible" content ="IE=edge" > <meta name ="viewport" content ="width=device-width, initial-scale=1.0" > <title > Document</title > <script src ="../vue.js" > </script > </head > <body > <div id ="root" > <h1 > hello, {{name}}</h1 > </div > </body > <script > let data = { name : "zhangsan" }; let vm = new Vue ({ el : "#root" , data }); alert (vm._data === data); alert (vm.name === vm._data .name ); </script > </html >
事件处理
Vue中的事件修饰符:
1、prevent:阻止默认事件(常用);
2、stop:阻止事件冒泡(常用);
3、once:事件只触发一次(常用);
4、capture:使用事件的捕获模式(捕获顺序与冒泡相反,即从外向内);
5、self:只有 event.target 是当前操作的元素时才触发事件;
6、passive:事件的默认行为立即执行,无需等待事件回调执行完毕。
Vue中常用的按键别名:
回车 => enter
删除 => delete (捕获“删除”和“退格”键)
退出 => esc
空格 => space
换行 => tab (特殊,必须配合keydown去使用,因为tab键按下后会跳出聚焦)
上 => up
下 => down
左 => left
右 => right
对于 Vue 未提供别名的按键,可以使用按键原始的 key 值去绑定,但注意要转为 kebab-case(短横线命名)。eg:若需要CapsLock,则需要写为 caps-lock
系统修饰键(用法特殊):ctrl、alt、shift、meta (1)配合 keyup 使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。 (2)配合 keydown 使用:正常触发事件。
也可以使用 keyCode 去指定具体的按键(不推荐)
Vue.config.keyCodes.自定义键名 = 键码,可以定制按键别名
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 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <meta http-equiv ="X-UA-Compatible" content ="IE=edge" > <meta name ="viewport" content ="width=device-width, initial-scale=1.0" > <title > Document</title > <script src ="../vue.js" > </script > </head > <body > <div id ="root" > <h1 > hello, {{name}}</h1 > <button v-on:click.once ="showInfo1(123, $event)" > click only once</button > <div @click ="showInfo2" > <button @click.stop ="showInfo2" > click stopPropagation</button > </div > <a href ="http://www.baidu.com" v-on:click.prevent.stop ="showInfo3" > go to baidu</a > </div > <script > const vm = new Vue ({ el : "#root" , data : { name : "san" }, methods : { showInfo3 (e ) { alert (e); }, showInfo1 (age, event ) { console .log (age); console .log (event); }, showInfo2 (event ) { console .log (this === vm); console .log (event); } } }); </script > <div id ="r" > <input type ="text" placeholder ="按下回车提交" @keyup.enter ="showMsg" > <input type ="text" placeholder ="按下大小写切换键提交" @keyup.caps-lock ="showCapsLock" > </div > <script > new Vue ({ el : "#r" , data : { }, methods : { showMsg (e ) { alert (e.target .value ); }, showCapsLock (e ) { alert (e.key + " " + e.keyCode ); } } }); </script > </body > </html >
计算属性
定义:要用的属性不存在,要通过已有属性计算得来。
原理:底层借助了 Objcet.defineproperty 方法提供的 getter 和 setter。
get 函数什么时候执行? (1)初次读取时会执行一次; (2)当依赖的数据发生改变时会被再次调用。
优势:与 methods 实现相比,内部有缓存机制(复用),效率更高,调试方便。
注意: 1、计算属性最终会出现在 vm 上,直接读取使用即可。 2、如果计算属性要被修改,那必须写 set 函数去响应修改,且 set 中要引起计算时依赖的数据发生改变。
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 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <meta http-equiv ="X-UA-Compatible" content ="IE=edge" > <meta name ="viewport" content ="width=device-width, initial-scale=1.0" > <title > Document</title > <script src ="../vue.js" > </script > </head > <body > <div id ="root" > 姓:<input type ="text" v-model:value ="firstName" > <br > 名:<input type ="text" v-model ="lastName" > <br > 全名: <span > {{fullName}}</span > <br > 全名2: <span > {{simpFullName}}</span > <br > 全名3:<span > {{fullName | getFirstName | changeFirstName}}</span > </div > <script > Vue .filter ("mySlice" , function (val ) { return val.slice (0 ,2 ); }); const vm = new Vue ({ el : "#root" , data : { firstName : "张" , lastName : "三" }, computed : { fullName : { get ( ) { console .log ("getter 被调用" ); return this .firstName + "·尼古拉斯·" + this .lastName ; }, set (value ) { console .log ("setter 被调用" + " : value = " + value); const arr = value.split ('-' ); console .log (arr); this .firstName = arr[0 ]; this .lastName = arr[1 ]; } }, simpFullName ( ) { return this .firstName + "·尼古拉斯·" + this .lastName ; } }, filters : { getFirstName (val, firstNameLength = 1 ) { return val.slice (0 ,firstNameLength); }, changeFirstName ( ) { return "刘" ; } } }); </script > </body > </html >
侦听属性
侦听属性 watch: 1、当被监视的属性变化时,回调函数自动调用,进行相关操作 2、监视的属性必须存在,才能进行监视!! 3、监视的两种写法: (1)new Vue 时传入 watch 配置 (2)通过 vm.$watch 监视
深度监视: (1)Vue 中的 watch 默认不监测对象内部值的改变(一层)。 (2)配置 deep:true 可以监测对象内部值改变(多层)。
注意: (1)Vue 自身可以监测对象内部值的改变,但 Vue 提供的 watch 默认不可以! (2)使用 watch时根据数据的具体结构,决定是否采用深度监视。
computed 和 watch 之间的区别:
1、computed 能完成的功能,watch 都可以完成。 2、watch 能完成的功能,computed 不一定能完成,例如:watch 可以进行异步操作。
两个重要的小原则: 1、所被 Vue 管理的函数,最好写成普通函数,这样 this 的指向才是 vm 或 组件实例对象。 2、所有不被 Vue 所管理的函数(定时器的回调函数、ajax 的回调函数等、Promise 的回调函数),最好写成箭头函数,这样 this 的指向才是 vm 或 组件实例对象。
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 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <meta http-equiv ="X-UA-Compatible" content ="IE=edge" > <meta name ="viewport" content ="width=device-width, initial-scale=1.0" > <title > Document</title > <script src ="../vue.js" > </script > <script > console .log ("********************************************************************" ); </script > </head > <body > <div id ="root" > <h1 > 天气很{{info}}</h1 > <button @click ="changeWeather" > 切换天气</button > <h1 > a 的值: {{numbers}}</h1 > <button @click ="aPlus" > a++</button > </div > </body > <script > const vm = new Vue ({ el : "#root" , data : { ishot : true , numbers : { a : 1 , b : 2 } }, computed : { info ( ) { return this .ishot ? "炎热" : "凉爽" ; } }, methods : { changeWeather ( ) { this .ishot = !this .ishot ; }, aPlus ( ) { this .numbers .a ++; } }, watch : { ishot : { handler (newValue, oldValue ) { console .log ("ishot: newValue:" + newValue + ", oldValue:" + oldValue); }, immediate : true }, "numbers.a" (newValue, oldValue) { console .log ("numbers.a: newValue:" + newValue + ", oldValue:" + oldValue); }, numbers : { deep : true , handler (newValue, oldValue ) { console .log ("numbers's handler is called" ); }, } } }); vm.$watch("info" ,{ handler (newValue, oldValue ) { console .log ("info: newValue:" + newValue + ", oldValue:" + oldValue); } }); </script > </html >
样式绑定
class 样式
写法 :class="xxx",xxx 可以是字符串、对象、数组。
字符串写法适用于:类名不确定,要动态获取。
数组写法适用于:要绑定多个样式,个数不确定,名字也不确定。
对象写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。
style 样式
:style="{fontSize: xxx}",其中 xxx 是动态值。
:style="[a,b]",其中 a、b 是样式对象。
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 87 88 89 90 91 92 93 94 95 96 97 98 99 100 <!DOCTYPE html > <html > <head > <meta charset ="UTF-8" /> <title > 绑定样式</title > <style > .basic { width : 400px ; height : 100px ; border : 1px solid black; } .happy { border : 4px solid red;; background-color : rgba (255 , 255 , 0 , 0.644 ); background : linear-gradient (30deg ,yellow,pink,orange,yellow); } .sad { border : 4px dashed rgb (2 , 197 , 2 ); background-color : gray; } .normal { background-color : skyblue; } .myStyle1 { background-color : yellowgreen; } .myStyle2 { font-size : 30px ; text-shadow :2px 2px 10px red; } .myStyle3 { border-radius : 20px ; } </style > <script type ="text/javascript" src ="../vue.js" > </script > </head > <body > <div id ="root" > <div class ="basic" :class ="mood" @click ="changeMood" > {{name}}</div > <br /> <br /> <div class ="basic" :class ="classArr" > {{name}}</div > <br /> <br /> <div class ="basic" :class ="classObj" > {{name}}</div > <br /> <br /> <div class ="basic" :style ="styleObj" > {{name}}</div > <br /> <br /> <div class ="basic" :style ="styleArr" > {{name}}</div > </div > </body > <script type ="text/javascript" > Vue .config .productionTip = false const vm = new Vue ({ el :'#root' , data :{ name :'at' , mood :'normal' , classArr :['myStyle1' ,'myStyle2' ,'myStyle3' ], classObj :{ myStyle1 :false , myStyle2 :false , }, styleObj :{ fontSize : '40px' , color :'red' , }, styleObj2 :{ backgroundColor :'orange' }, styleArr :[ { fontSize : '40px' , color :'blue' , }, { backgroundColor :'gray' } ] }, methods : { changeMood ( ){ const arr = ['happy' ,'sad' ,'normal' ] const index = Math .floor (Math .random ()*3 ) this .mood = arr[index] } }, }) </script > </html >
条件渲染
v-if 写法: (1)v-if=”表达式” (2)v-else-if=”表达式” (3)v-else=”表达式” 适用于:切换频率较低的场景。 特点:不展示的 DOM 元素直接被移除。 注意:v-if 可以和 :v-else-if、v-else 一起使用,但要求结构不能被“打断”
v-show 写法:v-show=”表达式” 适用于:切换频率较高的场景。 特点:不展示的 DOM 元素未被移除,仅仅是使用样式隐藏掉(display: none)
注意
使用 v-if 时,元素可能无法获取到,而使用 v-show 一定可以获取到。
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 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <meta http-equiv ="X-UA-Compatible" content ="IE=edge" > <meta name ="viewport" content ="width=device-width, initial-scale=1.0" > <title > Document</title > <script src ="../vue.js" > </script > </head > <body > <div id ="root" > <h2 > 当前的n值是:{{n}}</h2 > <button @click ="n++" > 点我n+1</button > <h2 v-show ="false" > 1欢迎{{name}}</h2 > <h2 v-show ="1 === 1" > 1欢迎{{name}}</h2 > <h2 v-if ="false" > 2欢迎{{name}}</h2 > <h2 v-if ="1 === 1" > 2欢迎{{name}}</h2 > <div v-if ="n === 1" > Angular</div > <div v-else-if ="n === 2" > React</div > <div v-else-if ="n === 3" > Vue</div > <div v-else > 哈哈</div > <template v-if ="n === 1" > <h2 > hello</h2 > <h2 > world</h2 > </template > </div > </body > <script > new Vue ({ el : "#root" , data : { n : 0 , name : "张三" } }) </script > </html >
列表渲染
v-for指令: 用于展示列表数据 语法:v-for=”(item, index) in xxx” :key=”yyy” 可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)
react、vue中的 key 有什么作用?(key 的内部原理)
虚拟 DOM 中 key 的作用: key 是虚拟 DOM 对象的标识,当数据发生变化时,Vue 会根据【新数据】生成【新的虚拟 DOM】, 随后 Vue 进行【新虚拟 DOM】与【旧虚拟 DOM】的差异比较,比较规则如下: (1)旧虚拟 DOM 中找到了与新虚拟 DOM 相同的 key: ① 若虚拟 DOM 中内容没变, 直接使用之前的真实 DOM! ② 若虚拟 DOM 中内容变了, 则生成新的真实 DOM,随后替换掉页面中之前的真实 DOM。 (2)旧虚拟 DOM 中未找到与新虚拟 DOM 相同的 key: 创建新的真实 DOM,随后渲染到到页面。
用 index 作为 key 可能会引发的问题: (1)若对数据进行:逆序添加、逆序删除等破坏顺序操作,会产生没有必要的真实 DOM 更新 ==> 界面效果没问题, 但效率低。 (2)如果结构中还包含输入类的 DOM,会产生错误 DOM 更新 ==> 界面有问题。
开发中如何选择 key? (1)最好使用每条数据的唯一标识作为 key, 比如 id、手机号、身份证号、学号等唯一值。 (2)如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用 index 作为 key 是没有问题的。
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 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <meta http-equiv ="X-UA-Compatible" content ="IE=edge" > <meta name ="viewport" content ="width=device-width, initial-scale=1.0" > <title > Document</title > <script src ="../vue.js" > </script > </head > <body > <div id ="root" > <h2 > 遍历数组</h2 > <button @click ="add" > 添加赵六</button > <input placeholder ="查询" v-model:value ="keyWord" > <ul > <li v-for ="(p,index) in filPersons" :key ="index" > {{index}}.{{p.name}}-{{p.age}} <input type ="text" > </li > </ul > <h2 > 遍历对象</h2 > <ul > <li v-for ="(v,k) in car" :key ="k" > {{k}}-{{v}} </li > </ul > <h2 > 测试遍历字符串(用得少)</h2 > <ul > <li v-for ="(char,index) in str" :key ="index" > {{index}}-{{char}} </li > </ul > <h2 > 测试遍历指定次数(用得少)</h2 > <ul > <li v-for ="(number,index) in 5" :key ="index" > {{index}}-{{number}} </li > </ul > </div > </body > <script > const vm = new Vue ({ el : "#root" , data : { persons : [ {id : "001" , name : "张三" , age : 18 }, {id : "002" , name : "李四" , age : 20 }, {id : "003" , name : "王五" , age : 21 } ], filPersons : [], car : { name : "五菱之光" , color : "白色" }, str : "test" , keyWord : "" }, methods : { add ( ) { this .persons .unshift ({id : "004" , name : "赵六" , age : 40 }); } }, watch : { keyWord : { immediate : true , handler (val ) { console .log (val == "" ); this .filPersons = this .persons .filter ((p )=> { return p.name .indexOf (val) != -1 ; }); } } }, }) </script > </html >
Vue.set() 的使用 Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括: push()、pop()、shift()、unshift()、splice()、sort()、reverse() 而直接操作数组元素不会成功,应该用 vm.arr.splice(x, 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 41 42 43 44 45 46 47 48 49 50 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <meta http-equiv ="X-UA-Compatible" content ="IE=edge" > <meta name ="viewport" content ="width=device-width, initial-scale=1.0" > <title > Document</title > <script src ="../vue.js" > </script > </head > <body > <div id ="root" > <h1 > 学生信息</h1 > <button @click ="addSex" > 添加性别、身高属性</button > <h1 > 姓名:{{student.name}}</h1 > <h1 > 年龄:{{student.age}}</h1 > <h1 v-if ="student.sex" > 性别:{{student.sex}}</h1 > <h1 v-show ="student.height" > 身高:{{student.height}}</h1 > <h1 > 爱好:</h1 > <ul > <li v-for ="(h, index) in student.hobbies" > 爱好{{index}}:{{h}} </li > </ul > </div > </body > <script > const vm = new Vue ({ el : "#root" , data : { student : { name : "张三" , age : 13 , hobbies : ["吃饭" , "睡觉" ] } }, methods : { addSex ( ) { Vue .set (this .student , "sex" , "男" ); this .$set(this .student , "height" , "199" ); this .$set(this .student .hobbies , 0 , "学习" ); } }, }) </script > </html >
数据监视
Vue 会监视 data 中所有层次的数据。
如何监测对象中的数据? 通过 setter 实现监视,且要在 new Vue 时就传入要监测的数据。 (1)对象中后追加的属性,Vue 默认不做响应式处理 (2)如需给后添加的属性做响应式,使用如下 API: Vue.set(target,propertyName/index,value) 或 vm.$set(target,propertyName/index,value)
如何监测数组中的数据? 通过包裹数组更新元素的方法实现,本质就是做了两件事: (1)调用原生对应的方法对数组进行更新。 (2)重新解析模板,进而更新页面。
在 Vue 修改数组中的某个元素一定要用如下方法: 1、push()、pop()、shift()、unshift()、splice()、sort()、reverse() 2、Vue.set() 或 vm.$set()
特别注意:Vue.set() 和 vm.$set() 不能给 vm 或 vm 的根数据对象添加属性!!!
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 <!DOCTYPE html > <html > <head > <meta charset ="UTF-8" /> <title > 总结数据监视</title > <style > button { margin-top : 10px ; } </style > <script type ="text/javascript" src ="../vue.js" > </script > </head > <body > <div id ="root" > <h1 > 学生信息</h1 > <button @click ="student.age++" > 年龄+1岁</button > <br /> <button @click ="addSex" > 添加性别属性,默认值:男</button > <br /> <button @click ="student.sex = '未知' " > 修改性别</button > <br /> <button @click ="addFriend" > 在列表首位添加一个朋友</button > <br /> <button @click ="updateFirstFriendName" > 修改第一个朋友的名字为:张三</button > <br /> <button @click ="addHobby" > 添加一个爱好</button > <br /> <button @click ="updateHobby" > 修改第一个爱好为:开车</button > <br /> <button @click ="removeSmoke" > 过滤掉爱好中的抽烟</button > <br /> <h3 > 姓名:{{student.name}}</h3 > <h3 > 年龄:{{student.age}}</h3 > <h3 v-if ="student.sex" > 性别:{{student.sex}}</h3 > <h3 > 爱好:</h3 > <ul > <li v-for ="(h,index) in student.hobby" :key ="index" > {{h}} </li > </ul > <h3 > 朋友们:</h3 > <ul > <li v-for ="(f,index) in student.friends" :key ="index" > {{f.name}}--{{f.age}} </li > </ul > </div > </body > <script type ="text/javascript" > Vue .config .productionTip = false const vm = new Vue ({ el :'#root' , data :{ student :{ name :'tom' , age :18 , hobby :['抽烟' ,'喝酒' ,'烫头' ], friends :[ {name :'jerry' ,age :35 }, {name :'tony' ,age :36 } ] } }, methods : { addSex ( ){ this .$set(this .student ,'sex' ,'男' ) }, addFriend ( ){ this .student .friends .unshift ({name :'jack' ,age :70 }) }, updateFirstFriendName ( ){ this .student .friends [0 ].name = '张三' }, addHobby ( ){ this .student .hobby .push ('学习' ) }, updateHobby ( ){ this .$set(this .student .hobby ,0 ,'开车' ) }, removeSmoke ( ){ this .student .hobby = this .student .hobby .filter ((h )=> { return h !== '抽烟' }) } } }) </script > </html >
表单数据收集
若:<input type="text"/>
,则 v-model 收集的是 value 值,用户输入的就是 value 值。
若:<input type="radio"/>
,则 v-model 收集的是 value 值,且要给标签配置 value 值。
若:<input type="checkbox"/>
1、没有配置 input 的 value 属性,那么收集的就是 checked(勾选 or 未勾选,是布尔值) 2、配置了 input 的 value 属性: (1)v-model 的初始值是非数组,那么收集的就是 checked(勾选 or 未勾选,是布尔值) (2)v-model 的初始值是数组,那么收集的的就是 value 组成的数组
v-model 的三个修饰符: lazy:失去焦点再收集数据 number:输入字符串转为有效的数字 trim:输入首尾空格过滤
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 <!DOCTYPE html > <html > <head > <meta charset ="UTF-8" /> <title > 收集表单数据</title > <script type ="text/javascript" src ="../vue.js" > </script > </head > <body > <div id ="root" > <form @submit.prevent ="demo" > 账号:<input type ="text" v-model.trim ="userInfo.account" > <br /> <br /> 密码:<input type ="password" v-model ="userInfo.password" > <br /> <br /> 年龄:<input type ="number" v-model.number ="userInfo.age" > <br /> <br /> 性别: 男<input type ="radio" name ="sex" v-model ="userInfo.sex" value ="male" > 女<input type ="radio" name ="sex" v-model ="userInfo.sex" value ="female" > <br /> <br /> 爱好: 学习<input type ="checkbox" v-model ="userInfo.hobby" value ="study" > 打游戏<input type ="checkbox" v-model ="userInfo.hobby" value ="game" > 吃饭<input type ="checkbox" v-model ="userInfo.hobby" value ="eat" > <br /> <br /> 所属地区 <select v-model ="userInfo.city" > <option value ="" > 请选择地区</option > <option value ="beijing" > 北京</option > <option value ="shanghai" > 上海</option > <option value ="shenzhen" > 深圳</option > <option value ="guangzhou" > 广州</option > </select > <br /> <br /> 其他信息: <textarea v-model.lazy ="userInfo.other" > </textarea > <br /> <br /> <input type ="checkbox" v-model ="userInfo.agree" > 阅读并接受<a href ="#" > 《用户协议》</a > <button > 提交</button > </form > </div > </body > <script type ="text/javascript" > Vue .config .productionTip = false new Vue ({ el :'#root' , data :{ userInfo :{ account :'' , password :'' , age :18 , sex :'female' , hobby :[], city :'beijing' , other :'' , agree :'' } }, methods : { demo ( ){ console .log (JSON .stringify (this .userInfo )) } } }) </script > </html >
内置指令与自定义指令 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 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <meta http-equiv ="X-UA-Compatible" content ="IE=edge" > <meta name ="viewport" content ="width=device-width, initial-scale=1.0" > <style > [v-cloak] { display : none } </style > <title > Document</title > <script src ="../vue.js" > </script > </head > <body > <div id ="root" > <h1 v-cloak > {{str}}</h1 > <span v-html ="str" > </span > <span v-text ="str" > </span > <div > <h1 v-pre > v-once测试</h1 > <h1 v-once > n的初始值为:{{n}}</h1 > <h1 > n的当前值为:{{n}}</h1 > <h1 > 放大10倍的n为:<span v-big ="n" > </span > </h1 > <h1 > 放大10倍的n为:<span v-big ="n" > </span > </h1 > <button @click ="n++" > 点击n+1</button > </div > </div > </body > <script > const vm = new Vue ({ el : "#root" , data : { str : "<h1>hello</h1>" , n : 1 }, directives : { big (elment, binding ) { elment.innerText = binding.value * 10 ; }, fbind : { } } }) </script > </html >
生命周期
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 87 88 89 90 91 92 93 94 95 96 97 98 99 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <meta http-equiv ="X-UA-Compatible" content ="IE=edge" > <meta name ="viewport" content ="width=device-width, initial-scale=1.0" > <title > Document</title > <script src ="../../vue.js" > </script > </head > <body > <div id ="root" :x ="n" > <h2 v-text ="n" > </h2 > <h2 > 当前的n值是:{{ n }}</h2 > <button @click ="add" > 点我n+1</button > <button @click ="bye" > 点我销毁vm</button > </div > </body > <script type ="text/javascript" > Vue .config .productionTip = false new Vue ({ el : '#root' , data : { n : 1 }, methods : { add ( ) { console .log ('add' ) this .n ++ }, bye ( ) { console .log ('bye' ) this .$destroy() } }, watch : { n ( ) { console .log ('n变了' ) } }, beforeCreate ( ) { console .log ('beforeCreate' ); console .log (this ); debugger ; }, created ( ) { console .log ('created' ); console .log (this ); debugger ; }, beforeMount ( ) { console .log ('beforeMount' ); console .log (this ); debugger ; }, mounted ( ) { console .log ('mounted' ); console .log (this ); debugger ; }, beforeUpdate ( ) { console .log ('beforeUpdate' ); console .log (this ); debugger ; }, updated ( ) { console .log ('updated' ); console .log (this ); debugger ; }, beforeDestroy ( ) { console .log ('beforeDestroy' ); console .log (this ); debugger ; }, destroyed ( ) { console .log ('destroyed' ); console .log (this ); debugger ; }, }) </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 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <meta http-equiv ="X-UA-Compatible" content ="IE=edge" > <meta name ="viewport" content ="width=device-width, initial-scale=1.0" > <title > Document</title > <script src ="../../vue.js" > </script > </head > <body > <div id ="root" > <my-student > </my-student > <hello > </hello > </div > </body > <script type ="text/javascript" > Vue .config .productionTip = false const student = Vue .extend ({ template :` <div> <h2>学生姓名:{{studentName}}</h2> <h2>学生年龄:{{age}}</h2> </div> ` , data ( ){ return { studentName :'张三' , age :18 } } }) const hello = Vue .extend ({ template :` <div> <h2>你好啊!{{name}}</h2> </div> ` , data ( ){ return { name :'Tom' } } }) Vue .component ('hello' ,hello) new Vue ({ el :'#root' , components :{ "my-student" : student } }) console .log (student) </script >