表单基本操作
通过V-model获取单选框、复选框、下拉框、文本框中的值
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
| <style type="text/css"> form div { height: 40px; line-height: 40px; } form div:nth-child(4) { height: auto; } form div span:first-child { display: inline-block; width: 100px; } </style> </head> <body> <div id="app"> <form action="http://itcast.cn"> <div> <span>姓名:</span> <span> <input type="text" v-model='uname'> </span> </div> <div> <span>性别:</span> <span> <input type="radio" id="male" value="1" v-model='gender'> <label for="male">男</label> <input type="radio" id="female" value="2" v-model='gender'> <label for="female">女</label> </span> </div> <div> <span>爱好:</span> <input type="checkbox" id="ball" value="1" v-model='hobby'> <label for="ball">篮球</label> <input type="checkbox" id="sing" value="2" v-model='hobby'> <label for="sing">唱歌</label> <input type="checkbox" id="code" value="3" v-model='hobby'> <label for="code">写代码</label> </div> <div> <span>职业:</span> <select v-model='occupation' multiple> <option value="0">请选择职业...</option> <option value="1">教师</option> <option value="2">软件工程师</option> <option value="3">律师</option> </select> </div> <div> <span>个人简介:</span> <textarea v-model='desc'></textarea> </div> <div> <input type="submit" value="提交" @click.prevent='handle'> </div> </form> </div> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript">
var vm = new Vue({ el: '#app', data: { uname: 'lisi', gender: 2, hobby: ['2','3'], occupation: ['2','3'], desc: 'nihao' }, methods: { handle: function(){ console.log(this.desc)
} } }); </script> </body>
|
表单修饰符
- .number 转换为数值
- 注意点:
- 当开始输入非数字的字符串时,因为Vue无法将字符串转换成数值
- 所以属性值将实时更新成相同的字符串。即使后面输入数字,也将被视作字符串。
- .trim 自动过滤用户输入的首尾空白字符
- .lazy 将input事件切换成change事件
- .lazy 修饰符延迟了同步更新属性值的时机。即将原本绑定在 input 事件的同步逻辑转变为绑定在 change 事件上
- 在失去焦点 或者 按下回车键时才更新
1 2 3 4 5 6 7 8
| <!-- 自动将用户的输入值转为数值类型 --> <input v-model.number="age" type="number">
<!--自动过滤用户输入的首尾空白字符 --> <input v-model.trim="msg">
<!-- 在“change”时而非“input”时更新 --> <input v-model.lazy="msg" >
|
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
| <body> <div id="app"> <input type="text" v-model.number='age'> <input type="text" v-model.trim='info'> <input type="text" v-model.lazy='msg'> <div>{{msg}}</div> <button @click='handle'>点击</button> </div> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript">
var vm = new Vue({ el: '#app', data: { age: '', info: '', msg: '' }, methods: { handle: function(){ } } }); </script> </body>
|
自定义指令
- 内置指令不能满足我们特殊的需求
- Vue允许我们自定义指令
Vue.directive 注册全局指令
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
| <body> <div id="app"> <input type="text" v-focus> <input type="text"> </div> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript">
Vue.directive('focus', { inserted: function(el){ el.focus(); } }); var vm = new Vue({ el: '#app', data: { }, methods: { handle: function(){ } } }); </script> </body>
|
Vue.directive 注册全局指令 带参数
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
| <body> <div id="app"> <input type="text" v-color='msg'> </div> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript">
Vue.directive('color', { bind: function(el, binding){ el.style.backgroundColor = binding.value.color; } }); var vm = new Vue({ el: '#app', data: { msg: { color: 'blue' } }, methods: { handle: function(){ } } }); </script> </body>
|
自定义指令局部指令
- 局部指令,需要定义在 directives 的选项 用法和全局用法一样
- 局部指令只能在当前组件里面使用
- 当全局指令和局部指令同名时以局部指令为准
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
| <body> <div id="app"> <input type="text" v-color='msg'> <input type="text" v-focus> </div> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript">
var vm = new Vue({ el: '#app', data: { msg: { color: 'red' } }, methods: { handle: function(){ } }, directives: { color: { bind: function(el, binding){ el.style.backgroundColor = binding.value.color; } }, focus: { inserted: function(el) { el.focus(); } } } }); </script> </body>
|
计算属性 computed
- 模板中放入太多的逻辑会让模板过重且难以维护 使用计算属性可以让模板更加的简洁
- 计算属性是基于它们的响应式依赖进行缓存的
- 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 26 27 28 29 30 31 32 33 34 35 36 37 38
| <body> <div id="app"> <div>{{reverseString}}</div> <div>{{reverseString}}</div> <div>{{reverseMessage()}}</div> <div>{{reverseMessage()}}</div> </div> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript">
var vm = new Vue({ el: '#app', data: { msg: 'Nihao', num: 100 }, methods: { reverseMessage: function(){ console.log('methods') return this.msg.split('').reverse().join(''); } }, computed: { reverseString: function(){ console.log('computed') var total = 0; for(var i=0;i<=this.num;i++){ total += i; } return total; } } }); </script> </body>
|
侦听器 watch
- 使用watch来响应数据的变化
- 一般用于异步或者开销较大的操作
- **watch 中的属性 一定是data 中 已经存在的数据 **
- 当需要监听一个对象的改变时,普通的watch方法无法监听到对象内部属性的改变,只有data中的数据才能够监听到变化,此时就需要deep属性对对象进行深度监听
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
| <body> <div id="app"> <div> <span>名:</span> <span> <input type="text" v-model='firstName'> </span> </div> <div> <span>姓:</span> <span> <input type="text" v-model='lastName'> </span> </div> <div>{{fullName}}</div> </div> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript">
var vm = new Vue({ el: '#app', data: { firstName: 'Jim', lastName: 'Green', }, computed: { fullName: function(){ return this.firstName + ' ' + this.lastName; } }, watch: { } }); </script> </body>
|
过滤器
- Vue.js允许自定义过滤器,可被用于一些常见的文本格式化。
- 过滤器可以用在两个地方:双花括号插值和v-bind表达式。
- 过滤器应该被添加在JavaScript表达式的尾部,由“管道”符号指示
- 支持级联操作
- 过滤器不改变真正的
data,而只是改变渲染的结果,并返回过滤后的版本
- 全局注册时是filter,没有s的。而局部过滤器是filters,是有s的
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
| <body> <div id="app"> <input type="text" v-model='msg'> <div>{{msg | upper}}</div> <div>{{msg | upper | lower}}</div> <div :abc='msg | upper'>测试数据</div> </div> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript">
Vue.filter('lower', function(val) { return val.charAt(0).toLowerCase() + val.slice(1); }); var vm = new Vue({ el: '#app', data: { msg: '' }, filters: { upper: function(val) { return val.charAt(0).toUpperCase() + val.slice(1); } } }); </script> </body>
|
过滤器中传递参数
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
| <body> <div id="app"> <div>{{date | format('yyyy-MM-dd hh:mm:ss')}}</div> </div> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript">
Vue.filter('format', function(value, arg) { function dateFormat(date, format) { if (typeof date === "string") { var mts = date.match(/(\/Date\((\d+)\)\/)/); if (mts && mts.length >= 3) { date = parseInt(mts[2]); } } date = new Date(date); if (!date || date.toUTCString() == "Invalid Date") { return ""; } var map = { "M": date.getMonth() + 1, "d": date.getDate(), "h": date.getHours(), "m": date.getMinutes(), "s": date.getSeconds(), "q": Math.floor((date.getMonth() + 3) / 3), "S": date.getMilliseconds() };
format = format.replace(/([yMdhmsqS])+/g, function(all, t) { var v = map[t]; if (v !== undefined) { if (all.length > 1) { v = '0' + v; v = v.substr(v.length - 2); } return v; } else if (t === 'y') { return (date.getFullYear() + '').substr(4 - all.length); } return all; }); return format; } return dateFormat(value, arg); }) var vm = new Vue({ el: '#app', data: { date: new Date() } }); </script> </body>
|
生命周期
- 事物从出生到死亡的过程
- Vue实例从创建 到销毁的过程 ,这些过程中会伴随着一些函数的自调用。我们称这些函数为钩子函数
常用的 钩子函数
| beforeCreate |
在实例初始化之后,数据观测和事件配置之前被调用 此时data 和 methods 以及页面的DOM结构都没有初始化 什么都做不了 |
| created |
在实例创建完成后被立即调用此时data 和 methods已经可以使用 但是页面还没有渲染出来 |
| beforeMount |
在挂载开始之前被调用 此时页面上还看不到真实数据 只是一个模板页面而已 |
| mounted |
el被新创建的vm.$el替换,并挂载到实例上去之后调用该钩子。 数据已经真实渲染到页面上 在这个钩子函数里面我们可以使用一些第三方的插件 |
| beforeUpdate |
数据更新时调用,发生在虚拟DOM打补丁之前。 页面上数据还是旧的 |
| updated |
由于数据更改导致的虚拟DOM重新渲染和打补丁,在这之后会调用该钩子。 页面上数据已经替换成最新的 |
| beforeDestroy |
实例销毁之前调用 |
| destroyed |
实例销毁后调用 |
数组变异方法
- 在 Vue 中,直接修改对象属性的值无法触发响应式。当你直接修改了对象属性的值,你会发现,只有数据改了,但是页面内容并没有改变
- 变异数组方法即保持数组方法原有功能不变的前提下对其进行功能拓展
push() |
往数组最后面添加一个元素,成功返回当前数组的长度 |
pop() |
删除数组的最后一个元素,成功返回删除元素的值 |
shift() |
删除数组的第一个元素,成功返回删除元素的值 |
unshift() |
往数组最前面添加一个元素,成功返回当前数组的长度 |
splice() |
有三个参数,第一个是想要删除的元素的下标(必选),第二个是想要删除的个数(必选),第三个是删除 后想要在原位置替换的值 |
sort() |
sort() 使数组按照字符编码默认从小到大排序,成功返回排序后的数组 |
reverse() |
reverse() 将数组倒序,成功返回倒序后的数组 |
替换数组
| filter |
filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。 |
| concat |
concat() 方法用于连接两个或多个数组。该方法不会改变现有的数组 |
| slice |
slice() 方法可从已有的数组中返回选定的元素。该方法并不会修改数组,而是返回一个子数组 |
生命周期代码
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
| <body> <div id="app"> <div>{{msg}}</div> <button @click='update'>更新</button> <button @click='destroy'>销毁</button> </div> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript">
var vm = new Vue({ el: '#app', data: { msg: '生命周期' }, methods: { update: function(){ this.msg = 'hello'; }, destroy: function(){ this.$destroy(); } }, beforeCreate: function(){ console.log('beforeCreate'); }, created: function(){ console.log('created'); }, beforeMount: function(){ console.log('beforeMount'); }, mounted: function(){ console.log('mounted'); }, beforeUpdate: function(){ console.log('beforeUpdate'); }, updated: function(){ console.log('updated'); }, beforeDestroy: function(){ console.log('beforeDestroy'); }, destroyed: function(){ console.log('destroyed'); } }); </script> </body>
|
变异方法和替换数组
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
| <body> <div id="app"> <div> <span> <input type="text" v-model='fname'> <button @click='add'>添加</button> <button @click='del'>删除</button> <button @click='change'>替换</button> </span> </div> <ul> <li :key='index' v-for='(item,index) in list'>{{item}}</li> </ul> </div> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript">
var vm = new Vue({ el: '#app', data: { fname: '', list: ['apple','orange','banana'] }, methods: { add: function(){ this.list.push(this.fname); }, del: function(){ this.list.pop(); }, change: function(){ this.list = this.list.slice(0,2); } } }); </script> </body>
|
动态数组响应式数据
- Vue.set(a,b,c) 让 触发视图重新更新一遍,数据动态起来
- a是要更改的数据 、 b是数据的第几项、 c是更改后的数据
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
| <body> <div id="app"> <ul> <li v-for='item in list'>{{item}}</li> </ul> <div> <div>{{info.name}}</div> <div>{{info.age}}</div> <div>{{info.gender}}</div> </div> </div> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript">
var vm = new Vue({ el: '#app', data: { list: ['apple', 'orange', 'banana'], info: { name: 'lisi', age: 12 } }, }); vm.$set(vm.list, 1, 'lemon');
vm.$set(vm.info, 'gender', 'female');
</script> </body>
|