Vue复习笔记day2
1.插值操作:mustache语法
<!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>
</head>
<body>
<div id="app">
<!-- mustache语法中,不仅仅可以写变量,还可以写简单表达式,下面是一些简单例子 -->
<h2>{{message}}</h2>
<h2>{{firstname + ' ' + lastname}}</h2>
<h2>{{firstname}} {{lastname}}</h2>
<div>{{counter * 3}}</div>
</div>
<script src="../vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'abc',
firstname: 'Kobe',
lastname: 'Bryant',
counter: 10
}
})
</script>
</body>
</html>
2.插值操作:其他指令应用
本小节重点:
1.v-once指令:可以使得此信息只显示初始化,不会改变;
2.v-html指令:该指令后面往往会跟上一个String类型,会将String的html解析出来。可以理解为提示接收信息格式,使得轻松解析服务器返回的内容(html内容),例如url等等;
3.v-text指令:与mustache语法功能相同,但是有缺陷,无法完成字符串拼接;
4.v-pre指令:用于跳过这个元素和其子元素的编译过程,原封不动展示其内部内容;
5.v-cloak指令:可以看做一个标志,具体使用详见代码(用处不大)。
<!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>
<style>
[v-cloak] {
display: none
}
</style>
</head>
<body>
<!-- 在vue解析之前,有一个v-cloak属性 -->
<!-- 在vue解析之后,没有一个v-cloak属性 -->
<div id="app" v-cloak>
<!-- v-once指令可以使得此信息只显示初始化,不会改变 -->
<h2 v-once>{{message}}</h2>
<h2 v-html='url'></h2>
<!-- 注意v-text指令缺陷:无法拼接是字符串
即:
<h2 v-text="message"></h2>与<h2 v-text="message">多余文本信息</h2>没有区别,被v-text指定内容覆盖
-->
<h2 v-text="message"></h2>
<!-- 如果想要展示的文本信息为{{message}},可以采用v-pre指令 -->
<h2 v-pre>{{message}}</h2>
</div>
<script src="../vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'abc',
url: '<a href = "http://www.baidu.com">百度一下</a>'
}
})
</script>
</body>
</html>
3.v-bind基本使用
前面说了内容的动态绑定,即mustache语法,这小节讨论属性的动态绑定。
- 动态绑定a元素的href属性
- 动态绑定img元素的src属性
这也就是v-bind的作用,动态绑定属性。
v-bind语法糖:v-bind: <=> :
<!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>
</head>
<body>
<div id="app">
<!-- 原来指定src的方法 -->
<!-- <img src="http://masteryhh.oss-cn-beijing.aliyuncs.com/blog_img/a.jpg" alt=""> -->
<!-- 如何改进呢?当然,这里肯定不可以用mustache语法,因为该语法用于内容而不是属性 -->
<img v-bind:src="imgURL" alt="">
<a v-bind:href="aHref">百度一下</a>
<!-- v-bind语法糖:v-bind: <=> : -->
<!-- 即v-bind:src="http://masteryhh.oss-cn-beijing.aliyuncs.com/blog_img/a.jpg"
等价于:src="http://masteryhh.oss-cn-beijing.aliyuncs.com/blog_img/a.jpg"
-->
</div>
<script src="../vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'abc',
imgURL: 'http://masteryhh.oss-cn-beijing.aliyuncs.com/blog_img/a.jpg',
aHref: 'http://www.baidu.com'
}
})
</script>
</body>
</html>
4.v-bind动态绑定class
很多时候,我们希望动态地来切换class,比如
当数据处于某个状态时,字体显示为红色
当数据处于另外一个状态时,字体显示为黑色
v-bind一般要么绑定对象语法,要么绑定数组语法,基本很少纯字符串
此处演示对象语法
<!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>
<style>
.active {
color: greenyellow
}
</style>
</head>
<body>
<div id="app">
<!-- 这里的大括号代表里面是对象,所以可以放键值对,好处是将data中的键值对作为控制器引入 -->
<!-- <h2 :class="{active: true}">{{message}}</h2> -->
<!-- 并且使用v-bind动态绑定类并不影响该标签对象在前面添加必须有的类 实例如下-->
<!-- <h2 class="title" :class="{active: isActive, line: isLine}">{{message}}</h2> -->
<!-- 如果觉得此处键值对太长了可以通过定义methods方法来获取,此处只填写定义的被调用的方法名即可 -->
<h2 :class="{active: isActive, line: isLine}">{{message}}</h2>
<h2 :class="getClasses()">{{message}}</h2>
<button v-on:click="btnClick">颜色反转</button>
</div>
<script src="../vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '这里是测试文本',
isActive: true,
isLine: true
},
methods: {
btnClick: function () {
this.isActive = !this.isActive
},
getClasses: function () {
return {active: this.isActive, line: this.isLine}
}
}
})
</script>
</body>
</html>
此处演示数组语法
<!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>
<style>
.active {
color: greenyellow
}
</style>
</head>
<body>
<div id="app">
<!-- 这里的大括号代表里面是对象,所以可以放键值对,好处是将data中的键值对作为控制器引入 -->
<!-- <h2 :class="{active: true}">{{message}}</h2> -->
<!-- 并且使用v-bind动态绑定类并不影响该标签对象在前面添加必须有的类 实例如下-->
<!-- <h2 class="title" :class="{active: isActive, line: isLine}">{{message}}</h2> -->
<!-- 如果觉得此处键值对太长了可以通过定义methods方法来获取,此处只填写定义的被调用的方法名即可 -->
<h2 :class="{active: isActive, line: isLine}">{{message}}</h2>
<h2 :class="getClasses()">{{message}}</h2>
</div>
<script src="../vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '这里是测试文本',
isActive: true,
isLine: true,
array: 'aaa',
array1: 'bbb'
},
methods: {
getClasses: function () {
return [this.array, this.array1]
}
}
})
</script>
</body>
</html>
5.v-bind动态绑定style
和动态绑定class基本没有区别
对象语法
<!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>
</head>
<body>
<div id="app">
<!-- <h2 :style="{key(属性名): value(属性值)}">{{message}}</h2> -->
<!-- 此处50px必须加上单引号,不然会被当做变量处理,然而对象里面没有这个属性,故会报错 -->
<h2 :style="{fontSize: '50px'}">{{message}}</h2>
<h2 :style="{fontSize: fSize}">{{message}}</h2>
<h2 :style="{fontSize: f2Size + 'px'}">{{message}}</h2>
<h2 :style="{fontSize: fSize, color: fColor}">{{message}}</h2>
<!-- 同v-bind绑定class,如果觉得太长了也可以定义methods方法获取键值对 -->
<h2 :style="getStyles()">{{message}}</h2>
</div>
<script src="../vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '测试文本',
fSize: '100px',
f2Size: 100,
fColor: 'red'
},
methods: {
getStyles: function () {
return {fontSize: this.fSize, color: this.fColor}
}
}
})
</script>
</body>
</html>
数组语法
<!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>
</head>
<body>
<div id="app">
<!-- <h2 :style="{key(属性名): value(属性值)}">{{message}}</h2> -->
<!-- 此处50px必须加上单引号,不然会被当做变量处理,然而对象里面没有这个属性,故会报错 -->
<h2 :style="{fontSize: '50px'}">{{message}}</h2>
<h2 :style="{fontSize: fSize}">{{message}}</h2>
<h2 :style="{fontSize: f2Size + 'px'}">{{message}}</h2>
<h2 :style="{fontSize: fSize, color: fColor}">{{message}}</h2>
<!-- 同v-bind绑定class,如果觉得太长了也可以定义methods方法获取键值对 -->
<h2 :style="getStyles()">{{message}}</h2>
<h2 :style="[baseStyle, baseStyle1]">{{message}}</h2>
</div>
<script src="../vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '测试文本',
fSize: '100px',
f2Size: 100,
fColor: 'red',
baseStyle: {backroundColor: 'red'},
baseStyle1: {color: 'greenyellow'}
},
methods: {
getStyles: function () {
return {fontSize: this.fSize, color: this.fColor}
}
}
})
</script>
</body>
</html>
6.计算属性的基本及复杂使用
基本使用
<!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>
</head>
<body>
<div id="app">
<!--此时想要将firstName和lastName拼接在一起,方法很多 -->
<!-- 方法一 -->
<h2>{{firstName + ' ' + lastName}}</h2>
<!-- 方法二 -->
<h2>{{firstName}} {{lastName}}</h2>
<!-- 方法三,采用methods方法 -->
<h2>{{getFullName()}}</h2>
<!-- 方法四 采用computed计算属性-->
<h2>{{fullName}}</h2>
</div>
<script src="../vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'abc',
firstName: 'Kobe',
lastName: 'Broyan'
},
// 计算属性
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
},
methods: {
getFullName: function () {
return this.firstName + ' ' + this.lastName
}
}
})
</script>
</body>
</html>
复杂情况
<!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>
</head>
<body>
<div id="app">
<h2>{{totalPrice}}</h2>
</div>
<script src="../vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
books: [
{name: 'Unix编程艺术', price: 100},
{name: 'Java编程思想', price: 120},
{name: '深入理解计算机系统', price: 140},
{name: '编译原理', price: 170},
]
},
// 计算属性
computed: {
// filter/map/reduce
totalPrice: function () {
let result = 0;
//方法一
for (let i = 0; i < this.books.length; i++) {
result += this.books[i].price;
}
// 方法二
for (let i in this.books) {
result += this.books[i].price;
}
//方法三
for (let book of this.books) {
result += book.price;
}
return result;
}
}
})
</script>
</body>
</html>
7.计算属性的setter和getter
<!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>
</head>
<body>
<div id="app">
<h2>{{fullName}}</h2>
</div>
<script src="../vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'abc',
firstName: 'Kobe',
lastName: 'Broyan'
},
// 计算属性
computed: {
// fullName: function () {
// return this.firstName + ' ' + this.lastName
// },
// 实际上是通过getter方法实现的,将funName看成一个对象并求其属性值
// 并且计算属性一般没有setter函数,因为大多是只读属性,防止外部篡改数据
//也就是说上面其实就是把get省略之后的简单写法,下面是原始写法
fullName: {
set: function(newValue) {
const names = newValue.split(' ');
this.firstName = names[0];
this.lastName = names[1];
},
get : function () {
return this.firstName + ' ' + this.lastName
}
}
}
})
</script>
</body>
</html>
8.computed与methods对比
<!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>
</head>
<body>
<div id="app">
<!-- 方法一 采用计算属性computed--推荐使用-->
<h2>{{fullName}}</h2>
<!-- 方法二 过于繁琐,不建议使用-->
<h2>{{firstName + ' ' + lastName}}</h2>
<!-- 方法三 采用methods方法 -->
<h2>{{getFullName()}}</h2>
</div>
<script src="../vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'abc',
firstName: 'Kobe',
lastName: 'Broyan'
},
// 计算属性
computed: {
fullName: function () {
console.log('fullName调用');
return this.firstName + ' ' + this.lastName
}
},
//methods方法定义
methods: {
getFullName: function () {
console.log('getFullName调用');
return this.firstName + ' ' + this.lastName
}
}
})
</script>
</body>
</html>
根据代码定义,如果由若干个甚至更大数量级要显示,可以看到computed始终只调用了一次,而methods调用次数与调用变量个数相同。
当然,原因是因为computed内部有缓存,只要值没变。重复打印是不会多次调用的。特别是有循环时,computed大大提高效率
9.块级作用域:let和var
JavaScript中var是有缺陷的,ES5中if,for都没有作用域,这意味着定义的变量全局可用,随时可能被篡改。所以必须借助function作用域限制。所以在ES6中加入let,而let在if 和let是有作用域的,避免此种风险。
简单来说,ES5中var是没有块级作用域的;ES6中let是有块级作用域的。
10.const的使用和注意事项
建议:在ES6开发中,优先使用const,只有需要改变某一标识符时才使用let
注意:const只能修饰常量;并且必须初始化赋值。常量的含义是指指向的对象不能修改,但是内部属性是可以进行修改的。
<!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>
</head>
<body>
<script src="../vue.min.js"></script>
<script>
cont obj = {
name: 'Kobe',
age: 40
}
obj.age = 45;
</script>
</body>
</html>
11.对象字面量的增强写法
<!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>
</head>
<body>
<script>
// ES5的写法
const obj = {
name: 'Hawking',
age: 40
}
// ES6的写法
const obj = {
name,
age
}
// 函数的增强写法
// ES5的写法
const obj = {
run: function () {
console.log("奔跑")
}
}
// ES6写法
const obj = {
run() {
console.log("奔跑")
}
}
</script>
</body>
</html>
12.事件监听/v-on
v-on的语法糖
<!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>
</head>
<body>
<div id="app">
<h2>{{counter}}</h2>
<button v-on:click="increment">+</button>
<button v-on:click="decrement">-</button>
<!-- 语法糖如下 -->
<button @click="increment">+</button>
<button @click="decrement">-</button>
</div>
<script src="../vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'abc',
counter: 0
},
methods: {
increment() {
this.counter++
},
decrement() {
this.counter--
}
}
})
</script>
</body>
</html>
v-on的参数传递问题
<!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>
</head>
<body>
<div id="app">
<h2>{{counter}}</h2>
<!-- 事件调用的方法没有参数 可省略函数括号-->
<button @click="btnclick1()">按钮一</button>
<button @click="btnclick1">按钮二</button>
<!-- 在事件定义时,写方法时省略了括号,但是方法本身需要传入参数,
这个时候vue会默认将浏览器产生的事件event传入方法 -->
<button @click="btnclick2">按钮三</button>
<!-- 方法既需要event又需要额外参数,可采用$event -->
<button @click="btnclick3(abc, $event)">按钮四</button>
</div>
<script src="../vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'abc',
counter: 0,
abc: 12324423423423542
},
methods: {
btnclick1() {
console.log("执行...")
},
btnclick2(event) {
console.log(event)
},
btnclick3(abc,event) {
console.log(abc, event)
}
}
})
</script>
</body>
</html>
v-on修饰符的使用
- .stop 调用event.stopPropagation()
- .prevent 调用event.preventDefault()
- .{keyCode | keyAlias} 只当事件是从特定键触发时才触发回调
- .once 只触发一次回调
<!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>
</head>
<body>
<div id="app">
<!-- 1. .stop修饰符的使用 -->
<div @click="divClick">
aaaaa
<button @click.stop="btnClick">按钮</button>
</div>
<!-- 2. .prevent修饰符的使用 -->
<br>
<form action="baidu">
<input type="submit" value="提交" @click.prevent="submitClick">
</form>
<!-- 3. 监听某个键盘的键帽 -->
<input type="text" @keyUp.enter="keyUp">
</div>
<script src="../vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'abc',
counter: 0,
},
methods: {
btnClick() {
console.log("btnClick")
},
divClick() {
console.log("divClick")
},
submitClick() {
console.log("submitClick")
},
keyUp() {
console.log("kyeUp")
}
}
})
</script>
</body>
</html>
13.v-if,v-else-if和v-else的使用
<!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>
</head>
<body>
<div id="app">
<h2 v-if="isShow">
<div>ABC</div>
<div>ABC</div>
<div>ABC</div>
<div>ABC</div>
<div>ABC</div>
{{message}}
</h2>
<h2 v-else>当isShow为false时显示</h2>
<h3 v-if="score >= 90">优秀</h3>
<h3 v-else-if="score >= 80">良好</h3>
<h3 v-else-if="score >= 60">及格</h3>
<h3 v-else>不及格</h3>
<h2>
{{result}}
</h2>
</div>
<script src="../vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '测试字体',
isShow: true,
score: 99
},
// 较为复杂的逻辑判断在计算属性里边实现比较好
computed: {
result() {
let showMessage = ' ';
if (this.score >= 90) {
return showMessage = '优秀'
}
else if (this.score >= 80) {
return showMessage = '良好'
}
else if (this.score >= 60) {
return showMessage = '及格'
}
else {
return showMessage = '不及格'
}
}
}
})
</script>
</body>
</html>
14.登录切换案例
<!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>
</head>
<body>
<div id="app">
<span v-if="isUser">
<label for="username">用户账户</label>
<input type="text" placeholder="用户账户" id="username">
</span>
<span v-else>
<label for="email">用户邮箱</label>
<input type="text" placeholder="用户邮箱" id="email">
</span>
<button @click="isUser = !isUser">切换类型</button>
</div>
<script src="../vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '测试字体',
isUser: true
}
})
</script>
</body>
</html>
问题
如果在有输入的情况下,input未删除的内容在切换类型之后仍然还在。
答:这是因为vue底层原理出于性能考虑,为了复用未删除的输入和原先的布局。
解决方案 :给对应的input添加key,并且保证key各不相同。具体代码实现如下
<input type="text" placeholder="用户账户" id="username" key="username">
<input type="text" placeholder="用户邮箱" id="email" key="email">