1 - 表单操作
1. 基于Vue的表单操作
- Input 单行文本
- textarea 多行文本
- select 下拉多选
- radio 单选框
- checkbox 多选框

v-model是双向数据绑定一个指令,限制在 <input>、<textarea>、<select>、components
中使用。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<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>
<!-- 双向绑定uname数据源 -->
<input type="text" v-model='uname'>
</span>
</div>
<div>
<span>性别:</span>
<span>
<!--
1、 两个单选框需要同时通过v-model双向绑定一个值
2、 每一个单选框必须要有value属性,且value值不能一样,
3、 当某一个单选框选中的时候v-model会将当前的value值改变为data中的数据
4、 gender的值就是选中的值,我们只需要实时监控他的值就可以了
-->
<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>
<!--
1、 复选框需要同时通过v-model双向绑定一个值
2、 每一个复选框必须要有value属性,且value值不能一样
3、 当某一个单选框选中的时候v-model会将当前的value值改变为data中的数据
4、 复选框是`checkbox`这种的类型时,data中的hobby我们要定义成数组,否则无法实现多选
5、 hobby的值就是选中的值,我们只需要实时监控他的值就可以了
-->
<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下拉选择框支持多选,设置multiple就可以了,按住shift键就可以多选了 -->
<!--
1、 需要给select通过v-model双向绑定一个值
2、 每一个option必须要有value属性,且value值不能一样
3、 当某一个option选中的时候,v-model会将当前的value值改变为data中的数据
4、 occupation的值就是选中的值,我们只需要实时监控他的值就可以了
-->
<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>
<!-- 双向绑定desc数据源 -->
<textarea v-model='desc'></textarea>
</div>
<div>
<!-- submit默认的提交行为会刷新本界面,使用prevent禁止掉默认提交行为 -->
<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: '1', // 默认会让当前的 value 值为 1 的单选框选中
hobby: ['2','3'], // 默认会让当前的 value 值为 2 和 3 的复选框选中
// occupation: '3', // 默认选中 value 为 3 的下拉框
occupation: ['2','3'], // 默认会让当前的 value 值为 2 和 3 的下拉框选中
desc: 'nihao'
},
methods: {
handle: function(){
// console.log(this.uname)
// console.log(this.gender)
// console.log(this.hobby.toString())
// console.log(this.occupation)
console.log(this.desc)
}
}
});
</script>
</body>
</html>
2. 表单域修饰符
① .number:转化为数值
以前我们通过parseInt
将字符串转成数值,现在可以直接使用.number
转化为数值。
注意:刚开始输入的就是非数字的字符串时,因为Vue无法将字符串转换成数值,所以属性值将实时更新成相同的字符串,即使后面再输入数字,也将被视作字符串。
② .trim:去掉开始和结尾的空格
只能去掉首尾的,不能去除中间的空格。
③ .lazy : 将input事件切换为change事件
-
input
事件是每次输入的时候都会触发,change
事件是在当输入框的值和上次不一样并且输入框失去焦点才会触发,blur
是在输入框失去焦点后触发。 - .lazy 修饰符延迟了同步更新属性值的时机,即将原本绑定在 input 事件的同步逻辑转变为绑定在 change 事件上。
- 使用场景:比如使用在,用户输入用户名之后,验证是否合法。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<!-- 将字符串转化为数值 -->
<input type="text" v-model.number='age'>
<!-- 去掉开始和结尾的空格 -->
<input type="text" v-model.trim='info'>
<!-- 将input事件切换为change事件 -->
<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(){
console.log(this.age + 1)
// console.log(this.info.length)
}
}
});
</script>
</body>
</html>
2 - 自定义指令
Vue 的内置指令不能满足我们特殊的需求,Vue允许我们自定义指令。directive n. 指示、指令。
1. Vue.directive 自定义全局指令
① 自定义指令语法规则(自动获取元素焦点)
自定义一个自动聚焦指令 v-focus,如下:
<!--
使用自定义的指令,只需在对用的元素中,加上'v-'的前缀形成类似于内部指令'v-if','v-text'的形式。
-->
<input type="text" v-focus>
<script>
// 注意点:
// 1、 在自定义指令中,如果以驼峰命名的方式定义 如 Vue.directive('focusA',function(){})
// 2、 在HTML中使用的时候 只能通过 v-focus-a 来使用
// 注册一个全局自定义指令 v-focus
Vue.directive('focus', {
// 当被绑定元素插入父节点时调用,其中el为dom元素
inserted: function (el) {
// 聚焦元素
el.focus();
}
});
new Vue({
el:'#app'
});
</script>
② 带参数的自定义指令(改变元素背景色)
自定义一个改变元素背景色指令 v-color,如下:
<input type="text" v-color='msg'>
<script type="text/javascript">
Vue.directive('color', {
// bind生命周期, 只调用一次,指令第一次绑定到元素时调用,在这里可以进行一次性的初始化设置
// el 为当前自定义指令的DOM元素
// binding为自定义的函数形参,是个对象,通过自定义属性传递过来的值,存在 binding.value 里面
bind: function(el, binding){
// 根据指令的参数设置背景色
// console.log(binding.value.color)
// binding.value 就是 msg 对应的值,是个对象
el.style.backgroundColor = binding.value.color;
}
});
var vm = new Vue({
el: '#app',
data: {
msg: {
color: 'blue' // 修改color就可以修改背景色
}
}
});
</script>
2. directives 自定义局部指令
- 局部指令需要定义在组件的directives选项中,只能在当前组件里面使用,用法和全局指令用法一样
- 当全局指令和局部指令同名时以局部指令为准
<input type="text" v-color='msg'>
<input type="text" v-focus>
<script type="text/javascript">
/*
自定义指令-局部指令
*/
var vm = new Vue({
el: '#app',
data: {
msg: {
color: 'red'
}
},
// 局部指令,需要定义在directives的选项
directives: {
color: {
bind: function(el, binding){
el.style.backgroundColor = binding.value.color;
}
},
focus: {
inserted: function(el) {
el.focus();
}
}
}
});
</script>
3 - computed 计算属性
1. 关于计算属性
- 模板中放入太多的逻辑会让模板过重且难以维护,使用计算属性可以让模板更加的简洁
- computed比较适合对多个变量或者对象进行处理后返回一个结果值,也就是数多个变量中的某一个值发生了变化则我们监控的这个值也就会发生变化
- 尽量避免在同一个元素上同时使用 v-if 和 v-for,建议使用计算属性替代
2. 计算属性的用法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
// Nihao
<div>{{msg}}</div>
// 直接使用计算属性就可以 oahiN
<div>{{reverseString}}</div>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
/*
计算属性
*/
var vm = new Vue({
el: '#app',
data: {
msg: 'Nihao'
},
computed: {
// 计算属性(反转字符串) Nihao -> oahiN
reverseString: function(){
return this.msg.split('').reverse().join('');
}
}
});
</script>
</body>
</html>
3. 计算属性与方法的区别
- 计算属性是基于它们的响应式依赖进行缓存的,这个依赖就是data中的数据,如果data中的数据没有改变,就直接从缓存中取数据,以节省性能
- 方法不存在缓存,每次调用都会执行方法
<div id="app">
<!--
当多次调用 reverseString 的时候,只要里面的num值不改变,他会把第一次计算的结果直接返回
直到data中的num值改变,计算属性才会重新发生计算
(因为计算属性计算的时候用到了num,只要num没改变,就没必要再计算一次,所以就取上次的缓存就好了)
-->
<div>{{reverseString}}</div>
<div>{{reverseString}}</div>
<!-- 调用methods中的方法的时候,他每次会重新调用 -->
<div>{{reverseMessage()}}</div>
<div>{{reverseMessage()}}</div>
</div>
<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 属性定义和 data 以及 methods 平级
computed: {
// reverseString 这个是我们自己定义的名字
// 计算属性里面可能有耗时操作,如果num没改变就没必要重新计算,以节省性能
reverseString: function(){
console.log('computed')
var total = 0;
// 当data 中的 num 的值改变的时候 reverseString 会自动发生计算
for(var i = 0; i <= this.num; i++){
total += i;
}
// 这里一定要有return,否则调用 reverseString 的时候无法拿到结果
return total;
}
}
});
</script>
4 - watch 侦听器

1. 关于侦听器
- 使用watch来响应数据的变化,一般用于异步或者开销较大的操作
- watch中的属性一定是data中已经存在的数据
2. 侦听器的用法
<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">
/* 侦听器 */
var vm = new Vue({
el: '#app',
data: {
firstName: 'Jim',
lastName: 'Green',
fullName: 'Jim Green'
},
//watch 和 data 以及 methods 平级
watch: {
// 注意:这里firstName,对应着data 中的 firstName
// 当 firstName 值改变的时候,会自动触发 watch
// 这里的val就是监听到的值
firstName: function(val) {
this.fullName = val + ' ' + this.lastName;
},
// 注意:这里lastName,对应着data 中的 lastName
lastName: function(val) {
this.fullName = this.firstName + ' ' + val;
}
}
});
</script>
当然,上面也可以不使用侦听器,使用计算属性也可以(如下),而且我们推荐优先使用计算属性,只有遇到异步或者开销较大的操作才考虑侦听器。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<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',
// fullName: 'Jim Green'
},
computed: {
fullName: function(){
return this.firstName + ' ' + this.lastName;
}
},
watch: {
// firstName: function(val) {
// this.fullName = val + ' ' + this.lastName;
// },
// lastName: function(val) {
// this.fullName = this.firstName + ' ' + val;
// }
}
});
</script>
</body>
</html>
3. 侦听器案例:验证用户名是否可用

需求:输入框中输入姓名,失去焦点时验证是否存在,如果已经存在,提示重新输入,如果不存在,提示可以使用。
① 通过v-model实现数据绑定,并且将将input事件切换为change事件
② 需要侦听器监听输入信息的变化
上面我们说了,侦听器一般用于异步或者开销较大的操作,调用接口就属于异步操作。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<div>
<span>用户名:</span>
<span>
<!-- 将input事件切换为change事件 -->
<input type="text" v-model.lazy='uname'>
</span>
<span>{{tip}}</span>
</div>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
/*
侦听器
1、采用侦听器监听用户名的变化
2、调用后台接口进行验证
3、根据验证的结果调整提示信息
*/
var vm = new Vue({
el: '#app',
data: {
uname: '',
tip: ''
},
methods: {
checkName: function(uname) {
// 调用接口,但是可以使用定时任务的方式模拟接口调用
var that = this; // setTimeout里面的this是window,所以我们在外面保存一下
setTimeout(function(){
// 模拟接口调用
if(uname == 'admin') {
that.tip = '用户名已经存在,请更换一个';
}else{
that.tip = '用户名可以使用';
}
}, 2000);
}
},
watch: {
// 这里的val就是监听到的值
uname: function(val){
// 调用后台接口验证用户名的合法性,是个异步操作
this.checkName(val);
// 修改提示信息
this.tip = '正在验证...';
}
}
});
</script>
</body>
</html>
5 - 过滤器
1. 关于过滤器
- Vue.js允许自定义过滤器,可被用于格式化数据,比如将字符串格式化为首字母大写,将日期格式化为指定的格式等
- 过滤器和自定义指令一样,也分为全局过滤器、局部过滤器
- 过滤器可以用在两个地方:双花括号插值和 v-bind: 表达式
- 过滤器使用 | 调用,支持级联操作
- 过滤器不改变真正的
data
,而只是改变渲染的结果,并返回过滤后的版本 - 全局注册时是filter,没有s的。而局部过滤器是filters,是有s的

2. 过滤器的使用
- 表达式 msg 的值将作为参数传入到函数(过滤器)中
- 支持级联操作
- 绑定属性的时候也可以使用过滤器
<div id="app">
<input type="text" v-model='msg'>
<!-- 1、upper 被定义为接收单个参数的过滤器函数,表达式 msg 的值将作为参数传入到函数中 -->
<div>{{msg | upper}}</div>
<!--
2、支持级联操作:
upper 被定义为接收单个参数的过滤器函数,表达式msg 的值将作为参数传入到函数中。
然后继续调用同样被定义为接收单个参数的过滤器 lower,将 upper 的结果传递到 lower 中
-->
<div>{{msg | upper | lower}}</div>
<!-- 3、绑定属性的时候也可以使用过滤器,比如:输入 :abc='nihao', 绑定的属性就叫 :abc='Nihao' -->
<div :abc='msg | upper'>测试数据</div>
</div>
<script type="text/javascript">
// 定义全局过滤器 lower
Vue.filter('lower', function(val) {
return val.charAt(0).toLowerCase() + val.slice(1);
});
var vm = new Vue({
el: '#app',
data: {
msg: ''
},
// filters 和 data 以及 methods 平级
// 定义局部过滤器 upper
filters: {
// upper 被定义为接收单个参数的过滤器函数,表达式 msg 的值将作为参数传入到函数中
upper: function(val) {
// 过滤器中一定要有返回值 这样外界使用过滤器的时候才能拿到结果
return val.charAt(0).toUpperCase() + val.slice(1); // 首字母大写
}
}
});
</script>
3. 过滤器中传递多个参数
<div id="box">
<!--
filterA 被定义为接收三个参数的过滤器函数。
其中 message 的值作为第一个参数,普通字符串 'arg1' 作为第二个参数,表达式 arg2 的值作为第三个参数。
-->
{{ message | filterA('arg1', 'arg2') }}
</div>
<script>
// 在过滤器中 第一个参数 对应的是管道符前面的数据 n,此时对应 message
// 第2个参数 a 对应实参 arg1 字符串
// 第3个参数 b 对应实参 arg2 字符串
Vue.filter('filterA',function(n, a, b){
if(n < 10){
return n + a;
} else {
return n + b;
}
});
new Vue({
el:"#box",
data:{
message: "哈哈哈"
}
})
</script>
4. 过滤器案例:格式化日期


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<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>
</html>
6 - 生命周期
生命周期就是事物从出生到死亡的过程,Vue实例从创建到销毁的过程 ,这些过程中会伴随着一些函数的自调用,我们称这些函数为钩子函数。
大致分为三个阶段:
- 挂载(初始化相关属性):beforeCreate、created、beforeMount、mounted
- 更新(元素或组件的变更操作):beforeUpdate、updated
- 销毁(销毁相关属性):beforeDestroy、destroyed
mounted adj. 安装好的、装裱好的
方法 | 介绍 |
---|---|
beforeCreate | 在实例初始化之后,数据观测和事件配置之前被调用,此时data 和 methods 以及页面的DOM结构都没有初始化,什么都做不了。 |
created | 在实例创建完成后被立即调用,此时data 和 methods已经可以使用,但是页面还没有渲染出来。此时我们可以进行数据请求。 |
beforeMount | 在挂载开始之前被调用,此时页面上还看不到真实数据,只是一个模板页面而已。 |
mounted | el被新创建的vm.$el替换,并挂载到实例上去之后调用该钩子。数据已经真实渲染到页面上,此时我们可以使用一些第三方插件、进行数据请求。 |
beforeUpdate | 数据更新时调用,发生在虚拟DOM打补丁之前,页面上数据还是旧的。 |
updated | 由于数据更改导致的虚拟DOM重新渲染和打补丁,在这之后会调用该钩子,页面上数据已经替换成最新的。 |
beforeDestroy | 实例销毁之前调用 |
destroyed | 实例销毁后调用 |
总结:如果是数据请求,在created和mounted方法里面都可以,如果是使用一些第三方插件,因为第三方插件有可能操作DOM,所以我们必须放到mounted里面,否则会出现意想不到的bug,为了简单起见,我们都放到mounted方法里。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<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">
/*
Vue实例的生命周期
*/
var vm = new Vue({
el: '#app',
data: {
msg: '生命周期'
},
methods: {
update: function(){
// 更新data的值,页面显示的值也会变化
this.msg = 'hello';
},
destroy: function(){
// this是vue示例,调用$destroy()销毁
this.$destroy();
}
},
// 运行之后打印:beforeCreate、created、beforeMount、mounted
// 点击更新按钮打印:beforeUpdate、updated
// 点击销毁按钮打印:beforeDestroy、destroyed
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>
</html>
7 - 数组更新检测
首先要明白,JS 操作数组有些是改变原数组的,称为变异方法,有些则是生成一个新数组,称为非变异方法。
- 如果是变异方法,Vue 可以检测到变化并更新视图。
- 如果是非变异方法,不能够修改原数组,而是返回一个新数组,Vue 也可以检测到变化并更新视图,前提是使用这些方法时要把返回的新数组替换掉旧的数组。
1. 变更方法
顾名思义,变异的单词是mutation 有改变之意,即会修改原数组,但不会返回新的。
shift v. 移位、转移、漂移
方法 | 介绍 |
---|---|
push() |
往数组最后面添加一个元素,成功返回当前数组的长度 |
pop() |
删除数组的最后一个元素,成功返回删除元素的值 |
unshift() |
往数组最前面添加一个元素,成功返回当前数组的长度 |
shift() |
删除数组的第一个元素,成功返回删除元素的值 |
splice() |
有三个参数,第一个是想要删除的元素的下标(必选),第二个是想要删除的个数(必选),第三个是删除后想要在原位置替换的值。(splice:删除-下标 几个 新值) |
sort() |
sort() 使数组按照字符编码默认从小到大排序,成功返回排序后的数组 |
reverse() |
reverse() 将数组倒序,成功返回倒序后的数组 |
2. 替换数组
既然有 mutation,肯定也会有非mutation,即在原数组的基础上生成一个新的数组返回。当使用非变异方法时,可以用新数组替换旧数组。
方法 | 介绍 |
---|---|
filter | filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。 |
concat | concat() 方法用于连接两个或多个数组。该方法不会改变现有的数组 |
slice | slice() 方法可从已有的数组中返回选定的元素。该方法并不会修改数组,而是返回一个子数组。(slice:下标 几个) |
示例代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<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(){
// 从索引0开始,截取两位
// 由于生成的是新数组,所以要把新数组赋值给原来的数组,这样视图才会刷新
this.list = this.list.slice(0,2);
}
}
});
</script>
</body>
</html>
3. 检测变化的注意事项
由于 JavaScript 的限制,Vue 不能检测到以下变动的数组、对象。换句话说就是如下方式的变动不是响应式的,视图不会刷新:
- 当修改数组的长度时,例如:
vm.items.length = newValue
- 当利用索引直接设置数组的一个项时,例如:
vm.items[indexOfItem] = newValue
- 通过对象的key修改对象
Vue 针对这两个问题给出了相应的解决办法,使其也触发视图更新:
- 对于上面的 1 点,使用 splice、concat 方法
- 对于上面的 2、3 点,使用 Vue 全局方法 Vue.set()或者使用 vm.$set() 实例方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<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.list[1] = 'lemon'; //通过索引修改数组的方式不是响应式的,视图不会刷新
Vue.set(vm.list, 2, 'lemon'); //是响应式的
vm.$set(vm.list, 1, 'lemon'); //是响应式的
// 这两行是一模一样的
// vm.info.gender = 'male'; //通过对象的key修改对象的方式不是响应式的,视图不会刷新
Vue.set(vm.info, 'gender', 'female'); //是响应式的
vm.$set(vm.info, 'gender', 'female'); //是响应式的
// 这两行是一模一样的
</script>
</body>
</html>
网友评论