文本
在html中通过{{}}(双大括号)中可以把Vue对象中的数据插入到网页中。并且只要Vue对象上对应的值发生改变了,那么html中双大括号中的值也会立马改变。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuedemo</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
<p>{{name}}</p>
<button v-on:click="change">点击修改</button>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
"name": "博客园"
},
methods: {
change: function(){
this.name = 'Github';
}
}
});
</script>
</body>
</html>
当然,如果在html的{{}}中,第一次渲染完成后,不想要跟着后期数据的更改而更改,那么可以使用v-once指令来实现。示例代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuedemo</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
<p>{{name}}</p> <!--点击按钮后此处name值被替换-->
<p v-once>{{name}}</p> <!--点击按钮后此处name值不会被替换-->
<button v-on:click="change">点击修改</button>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
"name": "博客园"
},
methods: {
change: function () {
this.name = 'Github';
}
}
});
</script>
</body>
</html>
显示原声HTML
有时候我们的Vue对象中,或者是后台返回给我们一个段原生的html代码,我们需要渲染出来,那么如果直接通过{{}}渲染,会把这个html代码当做字符串。这时候我们就可以通过v-html指令来实现。示例代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuedemo</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
<div v-html="code"></div>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
"code": "<a href='https://www.baidu.com/'>百度一下,你就知道!</a>"
}
});
</script>
</body>
</html>
属性绑定
如果我们想要在html元素的属性上绑定我们Vue对象中的变量,那么需要通过v-bind来实现:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuedemo</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
<img v-bind:src="imgSrc" alt="博客园">
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
"imgSrc": "https://dss2.bdstatic.com/6Ot1bjeh1BF3odCf/it/u=3533293712,4029543067&fm=74&app=80&f=JPEG?w=200&h=200"
}
});
</script>
</body>
</html>
v-bind写法
<!-- 完整语法 --> <a v-bind:href="url">...</a> <!-- 缩写 --> <a :href="url">...</a> <!-- 动态参数的缩写 (2.6.0+) --> <a :[key]="url"> ... </a>
属性绑定class和style
在绑定class或者style的时候,可以通过以下方式来实现。
绑定class
1.通过数组的方式来实现:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuedemo</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
<p v-bind:class="[classname1,classname2]">hello 博客园</p>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
classname1: "c1",
classname2: "c2"
}
});
</script>
</body>
</html>
2.通过对象的方式来实现:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuedemo</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
<p v-bind:class="{c1:isC1,c2:isC2}">hello,博客园</p>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
isC1: true,
isC2: true
}
});
</script>
</body>
</html>
绑定Style
用对象的方式。示例代码如下:
读取对应样式值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuedemo</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
<p :style="{color:myColor,size:mySize}">hello</p>
</div>
<script>
new Vue({
el: "#app",/**/
data: {
myColor: "red",
mySize: "21px"
}
})
</script>
</body>
</html>
或者直接读取整个字符串
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuedemo</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
<p :style=myStyle>hello</p>
</div>
<script>
new Vue({
el: "#app",
data: {
myStyle: 'color: red;size: 21px;'
}
})
</script>
</body>
</html>
用数组的方式。示例代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuedemo</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
<p :style='[style1,style2]'>hello</p>
</div>
<script>
new Vue({
el: "#app",
data: {
style1:{color:'red',backgroundColor: "blue",},
style2:{size:'21px'},
}
})
</script>
</body>
</html>
用JavaScript表达式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuedemo</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
<!--g-u-b-0-->
<p>{{username.split("").reverse().join("-")}}</p>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
username: "0bug",
}
});
</script>
</body>
</html>
条件判断
在模板中,可以根据条件进行渲染。条件用到的是v-if、v-else-if以及v-else来组合实现的。示例代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuedemo</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
<p v-if="weather == 'sun'">今天去公园玩!</p>
<p v-else-if="weather == 'rain'">今天去看电影!</p>
<p v-else>今天哪儿也不去!</p>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
weather: 'sun'
}
});
</script>
</body>
</html>
有时候我们想要在一个条件中加载多个html元素,那么我们可以通过template元素上实现。示例代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuedemo</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
<template v-if="age<18">
<p>数学多少分?</p>
<p>英语多少分?</p>
</template>
<template v-else-if="age>=18 && age<25">
<p>女朋友找到了吗?</p>
<p>考研究生了吗?</p>
</template>
<template v-else>
<p>二胎生了吗?</p>
<p>工资多少?</p>
</template>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
age: 24
}
});
</script>
</body>
</html>
另外,在模板中,Vue会尽量重用已有的元素,而不是重新渲染,这样可以变得更加高效。如果你允许用户在不同的登录方式之间切换:
<div id="app">
<template v-if="loginType=='username'">
<label for="username">用户名:</label>
<input type="text" id="username" name="username" placeholder="用户名">
</template>
<template v-else-if="loginType=='email'">
<label for="email">邮箱:</label>
<input type="text" id="email" name="email" placeholder="邮箱">
</template>
<div>
<button v-on:click="changeLoginType">切换登录类型</button>
</div>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
loginType: "username"
},
methods: {
changeLoginType: function(event){
this.loginType = this.loginType=="username"?"email":"username";
}
}
});
</script>
这个里面会有一个问题,就是如果我在username的输入框中输入完信息,切换到邮箱中,之前的信息还是保留下来,这样肯定不符合需求的,如果我们想要让html元素每次切换的时候都重新渲染一遍,可以在需要重新渲染的元素上加上唯一的key属性,其中key属性推荐使用整形,字符串类型。示例代码如下:
<div id="app">
<template v-if="loginType=='username'">
<label for="username">用户名:</label>
<input type="text" id="username" name="username" placeholder="用户名" key="username">
</template>
<template v-else-if="loginType=='email'">
<label for="email">邮箱:</label>
<input type="text" id="email" name="email" placeholder="邮箱" key="email">
</template>
<div>
<button v-on:click="changeLoginType">切换登录类型</button>
</div>
</div>
注意,<label>元素仍然会被高效地复用,因为它们没有添加key属性。
v-show和v-if
v-if是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。 v-if也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。 相比之下,v-show就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于CSS进行切换。 一般来说,v-if有更高的切换开销,而v-show有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用v-show较好;如果在运行时条件很少改变,则使用v-if较好。
循环
在模板中可以用v-for指令来循环数组,对象等。
循环数组
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuedemo</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
<table>
<thead>
<tr>
<th>序号</th>
<th>标题</th>
<th>作者</th>
</tr>
</thead>
<tbody>
<tr v-for="(book,index) in books">
<td>{{index}}</td>
<td>{{book.title}}</td>
<td>{{book.author}}</td>
</tr>
</tbody>
</table>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
books: [{
'title': '三国演义',
'author': '罗贯中'
}, {
'title': '水浒传',
'author': '施耐庵'
}, {
'title': '西游记',
'author': '吴承恩'
}, {
'title': '红楼梦',
'author': '曹雪芹'
}]
}
});
</script>
</body>
</html>
循环对象
循环对象跟循环数组是一样的。并且都可以在循环的时候使用接收多个参数。示例代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuedemo</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
<div v-for="(value,key) in person">
{{key}}:{{value}}
</div>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
person: {
"name": "0bug",
"age": 18,
"blog": "https://www.cnblogs.com/0bug"
}
}
});
</script>
</body>
</html>
保持状态
循环出来的元素,如果没有使用key元素来唯一标识,如果后期的数据发生了更改,默认是会重用的,并且元素的顺序不会跟着数据的顺序更改而更改。比如:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuedemo</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
<div v-for="(book,index) in books">
<label for="book">{{book}}</label>
<input type="text" v-bind:placeholder="book">
</div>
<button v-on:click="changeBooks">更换图书</button>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
books: ['三国演义', '水浒传', '红楼梦', '西游记']
},
methods: {
changeBooks: function (event) {
this.books.sort((x, y) => {
return 5 - parseInt(Math.random() * 10)
});
}
}
});
</script>
</body>
</html>
如果你在某个input标签中输入了值,然后点击了“更换图书”的按钮,你会发现及时数据更改了,input并不会跟着数据的更改而更改,这时候我们只需要在v-for的时候加上一个key属性就可以了。示例代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuedemo</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
<div v-for="(book,index) in books" v-bind:key="book">
<label for="book">{{book}}</label>
<input type="text" v-bind:placeholder="book">
</div>
<button v-on:click="changeBooks">更换图书</button>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
books: ['三国演义', '水浒传', '红楼梦', '西游记']
},
methods: {
changeBooks: function (event) {
this.books.sort((x, y) => {
return 5 - parseInt(Math.random() * 10)
});
}
}
});
</script>
</body>
</html>
注意,key只能是整形,或者是字符串类型,不能为数组或者对象。
触发视图更新
Vue对一些方法进行了包装和变异,以后数组通过这些方法进行数组更新,会出发视图的更新。这些方法如下:
push():添加元素的方法。
this.books.push("金xx")
pop():删除数组最后一个元素。
this.books.pop()
shift():删除数组的第一个元素。
this.books.shift()
unshift(item):在数组的开头位置添加一个元素。
this.books.unshift("金xx")
splice(index,howmany,item1,...,itemX):向数组中添加或者删除或者替换元素
// 向books第0个位置添加元素 this.books.splice(0,0,"金xx") // 下标从0开始,删除2个元素 this.books.splice(0,2) // 下标从0开始,替换2个元素 this.books.splice(0,2,'金xx','骆驼祥子')
sort(function):排序
this.books.sort(function(x,y){
// 取两个随机数排序
a = Math.random();
b = Math.random();
return a-b;
});
reverse():将数组元素进行反转。
this.books.reverse();
还有一些Vue没有包装的方法,比如filter、concat、slice,如果使用这些方法修改了数组,那么只能把修改后的结果重新赋值给原来的数组才能生效。比如
this.books = this.books.filter(function(x){
return x.length>3?false:true;
})
视图更新注意事项
直接修改数组中的某个值是不会出发视图更新的。比如:
this.books[0] = '金xx';
这种情况应该改成用splice或者是用Vue.set方法来实现:
Vue.set(this.books,0,'金xx');
如果动态的给对象添加属性,也不会触发视图更新。只能通过Vue.set来添加。比如:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuedemo</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
<ul>
<li v-for="(value,name) in person">{{name}}:{{value}}</li>
<button v-on:click="changePerson">changePerson</button>
</ul>
<script>
let vm = new Vue({
el: "#app",
data: {
person: {"username": '0bug'}
},
methods: {
changePerson: function (event) {
// 直接修改this.person.age是没有效果的
// this.person.age = 18;
Vue.set(this.person, 'username', 'lcg')
}
}
});
</script>
</div>
</body>
</html>
事件绑定
事件绑定就是在HTML元素中,通过v-on绑定事件的。事件代码可以直接放到v-on后面,也可以写成一个函数。示例代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuedemo</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
<p>{{count}}</p>
<button v-on:click="count+=1">加</button>
<button v-on:click="subtract(10)">减10</button>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
count: 0
},
methods: {
subtract: function (value) {
this.count -= value;
}
}
});
</script>
</div>
</body>
</html>
传入event参数
如果在事件处理函数中,想要获取原生的DOM事件,那么在html代码中,调用的时候,可以传递一个$event参数。示例代码如下:
<button v-on:click="subtract(10,$event)">减10</button>
...
<script>
...
methods: {
subtract: function(value,event){
this.count -= value;
console.log(event);
}
}
...
</script>
事件修饰符
有时候事件发生,我们可能需要做一些操作。比如针对这个事件要他的默认行为。那么我们可能通过以下代码来实现:
<div id="app">
<a href="https://www.baidu.com/" v-on:click="gotoWebsite($event)">百度</a>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
count: 0
},
methods: {
gotoWebsite: function(event){
event.preventDefault();
window.location = "https://www.360.cn/"
}
}
});
</script>
那个阻止默认事件执行的代码,我们可以通过click.prevent来实现。示例代码如下:
<a href="https://www.baidu.com/" v-on:click.prevent="gotoWebsite($event)">百度</a>
另外,常见的修饰符还有以下:
.stop:event.stopPropagation,阻止事件冒泡。.capture:事件捕获。.once:这个事件只执行一次。.self:代表当前这个被点击的元素自身。.passive:在页面滚动的时候告诉浏览器不会阻止默认的行为,从而让滚动更加顺畅