模板语法
数据绑定
插值语法绑定
插值表达式
使用双大括号的标签,该标签内可以是JavaScript的任意表达式(字符串拼接、数值计算,函数调用等)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<style>[v-cloak] { display: none }</style> <!-- 隐藏具有v-cloak属性的标签 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- CDN方式引入Vue -->
</head>
<body>
<div id="app">
{{1+1}} <!-- 1 -->
<br>
{{"hello" + " worad"}} <!-- hello worad -->
<br>
{{new Date()}} <!-- Thu Jan 01 1970 08:00:00 GMT+0800 (中国标准时间) -->
</div>
<script>
var app = new Vue({ //创建Vue实例
el: "#app", //挂载元素
});
</script>
</body>
</html>
v-cloak
若客户端出现卡顿,插值表达式会先显示Mustache标签,之后会迅速替换为定义的数据,为了解决这种闪动问题,可使用该指令,隐藏未编译的Mustache标签,编译完成后显示,和CSS[v-cloak] { display: none }
连用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<style>[v-cloak] { display: none }</style> <!-- 隐藏具有v-cloak属性的标签 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- CDN方式引入Vue -->
</head>
<body>
<div id="app" v-cloak>{{message}}</div> <!-- 插值语法填充数据 -->
<script>
var app = new Vue({ //创建Vue实例
el: "#app", //挂载元素
data() { //绑定数据
return { message: "hello world" }
}
});
</script>
</body>
</html>
v-text、v-html和v-pre
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- CDN方式引入Vue -->
</head>
<body>
<div id="app">
<div v-text="message"></div> <!-- 替换标签中的整个内容(会自动转义html标签) -->
<div v-html="message"></div> <!-- 替换标签中的整个内容(会渲染html标签) -->
<div v-pre>{{message}}</div> <!-- 标签中的插值表达式不会经过编译,而是原封不动的返回 -->
<div v-text="message + 123"></div> <!-- 引号中可以是JavaScript的任意表达式(字符串拼接、数值计算,函数调用等) -->
</div>
<script>
var app = new Vue({ //创建Vue实例
el: "#app", //挂载元素
data() { //绑定数据
return { message: "<h1>hello world</h1>" }
}
});
</script>
</body>
</html>
v-model
随表单内容数据进行双向数据绑定,可用于输入框、下拉框、复选框和单选框,还可以使用以下三种修饰符
.lazy
:使用input
事件监听代替change
事件.number
: 输入字符串转为有效的数字.trim
: 输入首尾空格过滤
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <!-- CDN方式引入Vue -->
</head>
<body>
<div id="app">
<fieldset>
<legend>输入框</legend>
输入框双向绑定:<input type="text" v-model="input">
<h4>绑定的input变量值为:{{input}}</h4>
使用lazy修饰符:<input type="text" v-model.lazy="input">
<h4>绑定的input变量值为:{{input}}</h4>
</fieldset>
<fieldset>
<legend>复选框</legend>
<input type="checkbox" v-model="checkboxArray" name="checkbox" value="checkbox1">复选框1
<input type="checkbox" v-model="checkboxArray" name="checkbox" value="checkbox2">复选框2
<h4>绑定的checkboxArray数组为:{{checkboxArray}}</h4>
</fieldset>
<fieldset>
<legend>单选框</legend>
<input type="radio" value="nan" v-model="radio">男
<input type="radio" value="nv" v-model="radio">女
<h4>绑定的radio变量值为:{{radio}}</h4>
</fieldset>
<fieldset>
<legend>下拉框</legend>
<select v-model="select">
<option value="opt1">选项1</option>
<option value="opt2">选项2</option>
<option value="opt3">选项3</option>
</select>
<h4>绑定的select变量值为:{{select}}</h4>
<select v-model="selectArray" multiple>
<option value="opt1">选项1</option>
<option value="opt2">选项2</option>
<option value="opt3">选项3</option>
</select>
<h4>绑定的selectArray数组为:{{selectArray}}</h4>
</fieldset>
</div>
<script>
var app = new Vue({ //创建Vue实例
el: "#app", //挂载元素
data() { //绑定数据
return {
input: "input",
checkboxArray: [],
radio: "",
select: "",
selectArray: []
}
}
});
</script>
</body>
</html>
v-once
只编译一次,不再具有数据响应式功能,用于新能优化
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- CDN方式引入Vue -->
</head>
<body>
<div id="app" v-once>{{message}}</div> <!-- 插值语法填充数据 -->
<script>
var app = new Vue({ //创建Vue实例
el: "#app", //挂载元素
data() { //绑定数据
return { message: "hello world" }
}
});
app.$data.message = "你好,世界"; //该修改不会影响到页面变化
</script>
</body>
</html>
事件绑定
v-on
使用v-on:事件名="内容"
方式绑定事件,也可以使用@事件名="内容"
的简写方式,内容可以是简单的JavaScript代码,也可以是Vue对象中methods
属性中的方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- CDN方式引入Vue -->
</head>
<body>
<div id="app">
<h1>{{number}}</h1>
<input type="button" v-on:click="number++" value="按钮"> <!-- 简单JavaScript代码片段 -->
<input type="button" @click="number++" value="按钮"> <!-- 简写方式 -->
<input type="button" @click="add" value="按钮"> <!-- 绑定方法,会自动传递事件对象参数,等价与add($event) -->
<input type="button" @click="addNum(2,$event)" value="按钮"> <!-- 绑定方法,但并非是该方法的返回值,而是用于传参 -->
<!-- 不会自动传递事件对象参数,必须手动传递事件对象,并且事件对象必须是最后一个参数 -->
</div>
<script>
var app = new Vue({ //创建Vue实例
el: "#app", //挂载元素
data() { //绑定数据
return { number: 0 }
},
methods: {
add(event) {
console.log(event); //默认参数是事件对象
this.number++; //this指向该Vue对象,即app
},
addNum(number, event) { //事件对象必须是最后一个参数
console.log(event);
this.number += number; //this指向该Vue对象,即app
}
}
});
</script>
</body>
</html>
事件修饰符
还可以使用以下修饰符,多个修饰符可链式调用,但是要注意顺序,因为 @click.prevent.self
会阻止所有的点击,而 @click.self.prevent
只会阻止对元素自身的点击
.stop
:调用event.stopPropagation()
取消事件冒泡.prevent
:调用event.preventDefault()
取消事件默认行为.self
:只当事件是从绑定的元素本身触发时才触发回调.once
:只触发一次回调
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- CDN方式引入Vue -->
</head>
<body>
<div id="app" @click="fun(1)">fun(1) <!-- 父元素绑定事件 -->
<h1 @click.stop="fun(2)">fun(2)</h1> <!-- 阻止子元素的事件冒泡 -->
<a href="https://www.baidu.com" @click.stop.prevent>百度</a> <!-- 阻止默认行为和冒泡,链式调用即可 -->
</div>
<script>
var app = new Vue({ //创建Vue实例
el: "#app", //挂载元素
methods: {fun(num){ alert(num) }}
});
</script>
</body>
</html>
按键修饰符
对于键盘事件可以使用以下修饰符来指定按键,若不指定按键,则任意按键都会触发事件,可以向Vue.config.keyCodes
对象中添加自定义按键修饰符
.enter
:回车键.tab
:tab键.delete
:包括删除和退格键.esc
:ESC键.space
:空格键.up
:上方向键.down
:下方向键.left
:左方向键.right
:右方向键
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- CDN方式引入Vue -->
</head>
<body>
<div id="app">
<input type="text" @keyup.enter.delete.a="fun(1)"> <!-- 可链式调用指定多个键 -->
</div>
<script>
Vue.config.keyCodes.a = 65; //自定义按键修饰符(必须用小写),该数字是键盘事件对象中keyCode的值
var app = new Vue({ //创建Vue实例
el: "#app", //挂载元素
methods: { fun(num){ console.log(num) } }
});
</script>
</body>
</html>
控制按键修饰符
控制按键修饰符,需同时于其他按键一起使用,否则组合任意键都会触发事件(包括鼠标事件)
.ctrl
:与ctrl键同时按下.alt
:与alt键同时按下.shift
:与shift键同时按下.meta
:与win键或command键同时按下.exact
:组合按键更加精确,比如在点击事件和控制按键组合时,若多按一个控制键也会触发,但是使用该修饰符后就不再会触发
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- CDN方式引入Vue -->
</head>
<body>
<div id="app">
<input type="text" @keyup.ctrl.a="fun(1)"> <!-- 同时按下CTRL + A键 -->
</div>
<script>
Vue.config.keyCodes.a = 65; //自定义按键修饰符
var app = new Vue({ //创建Vue实例
el: "#app", //挂载元素
methods: { fun(num) { console.log(num) } }
});
</script>
</body>
</html>
鼠标按钮修饰符
对于鼠标事件可以使用以下修饰符来指定按钮,若不指定按键,则默认是鼠标左键
.left
:左键.right
:右键.middle
:中键
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- CDN方式引入Vue -->
</head>
<body>
<div id="app">
<h1 @click.right.prevent="fun(1)">H1</h1> <!-- 按下鼠标右键 -->
</div>
<script>
Vue.config.keyCodes.a = 65; //自定义按键修饰符
var app = new Vue({ //创建Vue实例
el: "#app", //挂载元素
methods: { fun(num) { console.log(num) } }
});
</script>
</body>
</html>
属性绑定
v-bind
使用v-bind:属性名="内容"
方式绑定属性,也可以使用:属性名="内容"
的简写方式,内容可以是Vue对象中data
属性中的数据变量,也可以是Javascript代码
普通属性绑定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- CDN方式引入Vue -->
</head>
<body>
<div id="app">
<a v-bind:href="url">连接</a>
<a :href="url">连接</a> <!-- 简写方式 -->
</div>
<script>
var app = new Vue({ //创建Vue实例
el: "#app", //挂载元素
data() { return { url: "http://www.baidu.com" } }
});
</script>
</body>
</html>
Class属性绑定
对象语法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- CDN方式引入Vue -->
</head>
<body>
<div id="app">
<div :class="{one:isOne,two:isTwo}"></div> <!-- 对象的键是one,值是布尔类型,若为true则添加该类名 -->
<div class="base" :class="{one:isOne,two:isTwo}"></div> <!-- 对于已有的class不会覆盖,而是融合 -->
<div :class="ClassObj"></div> <!-- 也可以是对象类型的变量 -->
</div>
<script>
var app = new Vue({ //创建Vue实例
el: "#app", //挂载元素
data() {
return {
isOne: true,
isTwo: false,
ClassObj: { isOne: true, isTwo: false }
}
}
});
</script>
</body>
</html>
数组语法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- CDN方式引入Vue -->
</head>
<body>
<div id="app">
<div :class="[oneClass,twoClass,threeClass]"></div> <!-- 数组中所有类变量全部添加到该标签上,若该类名为空字符串则不会添加任何内容 -->
<div class="base" :class="[oneClass,twoClass]"></div> <!-- 对于已有的class不会覆盖,而是融合 -->
<div :class="ClassArr"></div> <!-- 也可以是数组类型的变量 -->
<div :class="[oneClass,twoClass,{three:isThree}]"></div> <!-- 也可以与对象方式混合使用连用 -->
</div>
<script>
var app = new Vue({ //创建Vue实例
el: "#app", //挂载元素
data() {
return {
oneClass: "one",
twoClass: "two",
threeClass: "",
ClassArr: ["one", "two"],
isThree: true
}
}
});
</script>
</body>
</html>
Style属性绑定
对象语法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- CDN方式引入Vue -->
</head>
<body>
<div id="app">
<div :style="{border: borderStyle, width: widthStyle, height: heightStyle}"></div> <!-- 对象的键是属性名,值是属性值 -->
<div :style="styleObj"></div> <!-- 也可以是对象类型的变量 -->
<div style="border:1px solid yellow;" :style="styleObj"></div> <!-- 对于已有的样式会覆盖,没有的会融合 -->
</div>
<script>
var app = new Vue({ //创建Vue实例
el: "#app", //挂载元素
data() {
return {
borderStyle: "1px solid red",
widthStyle: "100px",
heightStyle: "100px",
styleObj: {border: "1px solid red", width: "100px", height: "100px"}
}
}
});
</script>
</body>
</html>
数组语法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- CDN方式引入Vue -->
</head>
<body>
<div id="app">
<div :style="[styleObj1,styleObj2]"></div>
<!-- 数组中存放多个对象,前后对象中有重复的属性时,后面会覆盖掉前面的,不重复时会融合 -->
</div>
<script>
var app = new Vue({ //创建Vue实例
el: "#app", //挂载元素
data() {
return {
styleObj1: {border: "1px solid red", width: "100px", height: "100px"},
styleObj2: {backgroundColor: "blue", width: "200px"} //短横线连接的属性在JavaScript中使用驼峰命名法
}
}
});
</script>
</body>
</html>
其他数据操作
计算属性
是Vue对象中computed
属性中的方法就是计算属性,与普通方法不同的是:
- 若有多处用到该计算属性时该函数只会执行一次,而方法却会执行多次(当页面重新渲染时方法也会重新执行)
- 定义计算属性时必须有return语句,调用计算属性时不能加括号
- 当数据发生改变时,计算属性的缓存值也会发生变化,若是对象形式的计算属性则可以定义setter方法,非对象形式计算属性默认只有getter方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <!-- CDN方式引入Vue -->
</head>
<body>
<div id="app">
<h4>计算属性:{{fullNameComputed}} | 方法:{{fullNameMethod()}} | {{age}}</h4>
<h4>计算属性:{{fullNameComputed}} | 方法:{{fullNameMethod()}} | {{age}}</h4>
<!-- 切勿使用函数调用的方式进行调用,因为计算属性本身就是属性,Vue只是将该值当作属性缓存起来了,方便下次调用 -->
<h4>对象形式的计算属性:{{fullName}}</h4>
</div>
<script>
var app = new Vue({ //创建Vue实例
el: "#app", //挂载元素
data() { //绑定数据
return {
firstName: "firstName",
lastName: "lastName",
age : 18
}
},
computed: { //计算属性
fullNameComputed() { //默认情况下只有getter方法
console.log("计算属性执行了一次");
return this.firstName + " " + this.lastName;
},
fullName: { //计算属性的对象形式,可以定义setter方法
get(){
return this.firstName + " " + this.lastName;
},
set(value){ //value是外部传递的值,就可以通过设置计算属性值设置非计算属性的值
this.firstName = value.split(" ")[0];
this.lastName = value.split(" ")[1];
}
}
},
methods: { //方法
fullNameMethod() {
console.log("方法执行了一次");
return this.firstName + " " + this.lastName;
}
}
});
app.age = 100; //修改age属性会导致页面重新渲染,当页面渲染时,方法会重新执行,但是计算属性却不会
setTimeout(() => { app.fullName = "first last"; }, 1000); //1秒后修改对象形式的计算属性的值
</script>
</body>
</html>
监听器
是Vue对象中watch
属性中的方法,并且与data
中绑定的数据名字保持一致,当data
中的属性发生变化时,会触发watch
中对应的方法,方法中第一个参数就是变化后的值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <!-- CDN方式引入Vue -->
</head>
<body>
<div id="app"> {{message}} </div>
<!-- 切勿使用函数调用的方式进行调用,因为计算属性本身就是属性,Vue只是将该值当作属性缓存起来了,方便下次调用 -->
<script>
var app = new Vue({ //创建Vue实例
el: "#app", //挂载元素
data(){ //绑定数据
return{message: "hello world"}
},
watch: { //计算属性
message(value){
console.log("变化后的数据为:",value);
//this.message = "我是前缀" + value; //切勿在监听器中递归修改,否则递归没有出口导致栈溢出
}
}
});
app.message = "hello world!!!"
</script>
</body>
</html>
过滤器
是Vue对象中filters
属性中的方法,方法中第一个参数就是要过滤的值,在使用时类似Linux中的管道运算符,过滤器参数可以使用括号进行传递,在定义过滤器时自定义参数是从第二个开始的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <!-- CDN方式引入Vue -->
</head>
<body>
<div id="app">
{{message | prefix}} <!-- 对message进行过滤 -->
<br>
{{message | prefix | prefix}} <!-- 可过滤多次 -->
<br>
{{message | suffix("参数")}} <!-- 带参数的过滤器 -->
</div>
<script>
var app = new Vue({ //创建Vue实例
el: "#app", //挂载元素
data() { //绑定数据
return { message: "hello world" }
},
filters: { //过滤器
prefix(value) { return "前缀" + value },
suffix(value,arg) { return value + arg } //参数是从第二个开始的
}
});
</script>
</body>
</html>
分支循环结构
v-if、v-else和v-else-if
控制元素是否会被渲染,会有DOM操作,v-if、v-else和v-else-if这三个指令必须紧贴在一起使用,否则会报语法错误
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- CDN方式引入Vue -->
</head>
<body>
<div id="app">
<h1 v-if="score>=90">A</h1> <!-- v-if后是一个布尔表达式,若表达式为真则该元素将会被渲染,否则不会渲染 -->
<h1 v-else-if="score<90&&score>=60">B</h1> <!-- 与v-if类似 -->
<h1 v-else>C</h1> <!-- 无需跟布尔表达式,若上面的v-if或v-else-if都为fasle时才会渲染该元素 -->
</div>
<script>
var app = new Vue({ //创建Vue实例
el: "#app", //挂载元素
data() { return { score: 60 } }
});
</script>
</body>
</html>
v-show
控制元素是否显示,不会有DOM操作,而是已经渲染到页面上,使用的style标签中添加display: none
来控制是否显示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- CDN方式引入Vue -->
</head>
<body>
<div id="app">
<h1 v-show="show">show</h1> <!-- v-show后是一个布尔表达式,若表达式为真则该元素将会被显示,否则不会显示 -->
</div>
<script>
var app = new Vue({ //创建Vue实例
el: "#app", //挂载元素
data() { return { show: false } }
});
</script>
</body>
</html>
v-for
可以用
of
替代in
作为分隔符,因为它更接近JavaScript迭代器的语法
遍历数组
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- CDN方式引入Vue -->
</head>
<body>
<div id="app">
<ul>
<li v-for="item in array">{{item}}</li> <!-- 遍历数组的项 -->
</ul>
<ul>
<li v-for="(item,index) in array">{{index}} : {{item}}</li> <!-- 遍历数组项和索引 -->
</ul>
<ul>
<li v-for="item in objArray">{{item.name}}</li> <!-- 遍历对象数组 -->
</ul>
</div>
<script>
var app = new Vue({ //创建Vue实例
el: "#app", //挂载元素
data() {
return {
array: ["one", "tow", "three"],
objArray: [
{name: "one"},
{name: "tow"},
{name: "three"},
]
}
}
});
</script>
</body>
</html>
遍历对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- CDN方式引入Vue -->
</head>
<body>
<div id="app">
<ul>
<li v-for="value in obj">{{value}}</li> <!-- 遍历对象,不包括键 -->
</ul>
<ul>
<li v-for="(value,key) in obj">{{key}} : {{value}}</li> <!-- 遍历对象,包括键 -->
</ul>
<ul>
<li v-for="(value,key,index) in obj">{{index}}、{{key}} : {{value}}</li> <!-- 遍历对象,包括键和索引 -->
</ul>
</div>
<script>
var app = new Vue({ //创建Vue实例
el: "#app", //挂载元素
data() {
return {
obj: {
oneKey: "one",
towKey: "tow",
threeKey: "three"
}
}
}
});
</script>
</body>
</html>
与v-if联用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- CDN方式引入Vue -->
</head>
<body>
<div id="app">
<ul>
<li v-if="index>0" v-for="(item,index) in array">{{item}}</li> <!-- 可过滤要数组中的遍历项,从第二个开始遍历 -->
</ul>
</div>
<script>
var app = new Vue({ //创建Vue实例
el: "#app", //挂载元素
data() { return { array: ["one", "tow", "three"] } }
});
</script>
</body>
</html>
模板占位符
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- CDN方式引入Vue -->
</head>
<body>
<div id="app">
<template v-for="(item,index) in array"> <!-- 此时的template标签只起到包裹作用,不会被渲染到页面上 -->
<em>{{index}}</em> <strong>{{item}}</strong>
<br>
</template>
</div>
<script>
var app = new Vue({ //创建Vue实例
el: "#app", //挂载元素
data() { return { array: ["one", "tow", "three"] } }
});
</script>
</body>
</html>
Diff算法
Diff算法的目的就是尽可能的复用页面中的DOM元素,减少删除添加DOM元素的操作,从而提高效率,但是这有时候会带来一些BUG,解决这个问题,简单的就为不希望复用的DOM元素绑定一个唯一的key值
列表渲染
使用v-for
列表渲染时,默认就地更新的策略,若顺序被改变,不会移动DOM元素来匹配数据项的顺序,而是就地更新每个元素中的内容,并且确保它们在每个索引位置正确渲染
也就是说当前数组为[1,2,3]
此时更改为[1,2,30]
,Vue会依次对比0号元素是否发生改变,1号元素是否发生改变,若改变则修改DOM中的值,这个默认的模式是高效的;但若元素的顺序发生变化时,此时更改为[0,1,2,3]
,Vue会对比所有元素进行内容替换,效率会很低,为了而重用和重新排序现有元素,所以要为每项绑定一个唯一 key
,Vue会依次对比与变化之前key值相同的元素是否发生变化,对于没有的key值的元素就会插入一个DOM元素,从而提高效率(切勿将key值设置为索引值,因为在与虚拟DOM进行对比时和未绑定key的效果是一样的)
条件渲染
使用v-if
条件渲染时,同样的使用就地更新策略,若两个条件渲染DOM元素相同时,不会移除并添加DOM,而是就地更新每个元素中的内容
比如页面中两个input标签进行切换,当已输入到第一个input中内容,之后在切换input标签,此时Vue为了复用DOM所以相同的DOM并不会切换,而是复用,导致input中的内容不会被清空,所以要为input标签绑定一个唯一key
值即可
更新检测机制
由于JavaScript的限制,Vue不能检测数组和对象的属性增删变化,也就是说通过索引的方式修改数据不能达到数据响应式的功能,若想修改必须使用数组中的方法间接修改(这是因为Vue重写了这些方法)或修改整个数组中的引用,也可以使用Vue.set()
或vue.prototype.$set()
方法进行修改(Vue.delete()
和vue.prototype.$delete()
方法进行删除)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- CDN方式引入Vue -->
</head>
<body>
<div id="app">
<ul>
<li v-for="item in array" :key="item">{{item}}</li>
</ul>
</div>
<script>
var app = new Vue({ //创建Vue实例
el: "#app", //挂载元素
data() { return { array: ["one", "tow", "three"] } }
});
app.array[0] = 1000; //虽然数据发生改变,但是页面并为发生改变
app.array.splice(0,1,100); //这种间接修改方式可以检测到数据发生变化
Vue.set(app.array, 0, 10); //这种方式可以检测到数据发生变化,对象也是一样的,只不过索引变成了key值
app.$set(app.array, 0, 1); //实例方法也是一样
</script>
</body>
</html>
Comments NOTHING