1. Mustache语法
Mustache语法也叫插值表达式,Mustache语法式通过{{}}渲染到页面,并且数据是响应式的。
数据的响应式:数据的变化导致页面的内容随之变化
效果图:
2. 指令
1.什么是指令?
指令的本质就是自定义属性。
Vue指令的格式: 通常以V开头 比如v-block。
2. v-once 指令
v-once指令只会执行一次性插值。也就是说当data中的数据放生改变时,Mustache语法中的内容不会继续发生改变。不常使用。
3. v-pre 指令
v-pre指令会显示原始的信息,跳过这个元素和它子元素的编译过程。不常使用。
展示效果:data数据为改变时
当data 中的数据改变时
4. v-block 指令
该指令解决了插值表达式存在的"闪动"问题。
为什么会有”闪动“的问题?
代码加载时,先加载HTML把插值语法当作HTML内容加载到页面上。当加载完JS后,才把插值语法替换掉,所以出现了”闪烁“的问题。
v-block解决闪烁问题的原理
先将插值表达式隐藏(display:none),等JS加载完,替换好值之后再显示
5. v-text 指令
js中的innerText,用于将数据填充到标签中,作用与插值表达式相同,但没有闪动问题。但是在日常的开发中 我们还是经常使用插值表达式,不使用这个。
6. v-html 指令
与JS中的innerHtml相同。
展示效果:
注意:
在网站上动态的渲染任意HTML非常危险,容易导致XSS(跨站脚本攻击),所以如果要使用请在可信内容上使用v-html,永远不要在用户提交的内容上使用v-html。
7. v- model指令
v-model是双向的数据绑定。
什么是数据绑定?
将页面填充到标签中成为数据绑定。
什么是双向数据绑定?
当数据发生变化的时候,视图也就发生了变化。
当视图发生变化时,数据也会跟着同步的变化
v-model指令限制在 input 、select 、textarea 等表单属性中使用
<!--当我们在输入框输入数据时,data中的str也随之放生改变 -->
<input type="text" v-model='str'>
<script src="../lib/dep/plugins/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data() {
return {
str: "你好"
}
},
})
</script>
3. 属性绑定 v-bind
1. v-bind 指令
该指令被用来动态的绑定 HTML的属性。
在后期的开发中,我们有很多属性,例如a元素的href属性,img元素的src属性等等 都是通过后台接口返回的,所以这些数据很少写“死”,都是使用v-bind 动态获取。也常常用来绑定class和style。
<body>
<div id="app">
<image v-bind:src="imgSrc" alt="" />
<!-- : 是v-bind 语法糖 也就是缩写 -->
<image :src="imgSrc" alt="" />
</div>
<script src="../lib/dep/plugins/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data() {
return {
imgSrc: "../学习笔记/images/指令2.png"
}
},
})
</script>
</body>
什么是语法糖?
语法糖(Syntactic sugar),也译为糖衣语法,是由英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。
2. v-bind 绑定class
比如当我们需要频繁的切换class 时 ,就要使用v-bind 动态绑定。
v-bind绑定class 通常有两种写法,对象语法和数组语法。
2.1 对象语法
<!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>
<style>
.yellow {
color: yellow;
}
.size {
font-size: 20px;
}
.bold {
font-weight: bold;
}
</style>
<body>
<div id="app">
<!-- 用法一 绑定一个类 键值对为 类名:布尔类型 -->
<div :class="{'size':status}">{{text}}</div>
<!-- 用法二:也可以通过判断,传入多个值 -->
<div :class="{'size':status,'yellow':status}">{{text}}</div>
<!-- 用法三:和普通的类同时存在,并不冲突 -->
<div class="bold" :class="{'size':status,'yellow':status}">{{text}}</div>
<!-- 如果过于复杂,可以放在一个methods或者computed中 后续有将 -->
</div>
<script src="../lib/dep/plugins/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data() {
return {
text: "天神下凡,1V4",
status: true
}
},
})
</script>
</body>
</html>
2.2 数组语法
<!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>
<style>
.yellow {
color: yellow;
}
.size {
font-size: 20px;
}
.bold {
font-weight: bold;
}
</style>
<body>
<div id="app">
<!-- 数组语法用法一 数组中的每个值来自data 用途不大 -->
<div :class='[bold,yellow]'>{{text}}</div>
<!-- 数组语法用法二,数组语法中可以包含对象语法 -->
<div :class='[bold,yellow,{"size":status}]'>{{text}}</div>
<!-- 数组用法三 数组中的calss 可以和普通class共存 -->
<div class="yellow" :class='[bold,{"size":status}]'>{{text}}</div>
</div>
<script src="../lib/dep/plugins/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data() {
return {
text: "天神下凡,1V4",
status: true,
bold: "bold",
yellow: "yellow"
}
},
})
</script>
</body>
</html>
7.1 v-model修饰符
1.lazy修饰符
默认情况下,v-model默认是在input事件中同步输入框的数据的。也就是说,一旦有数据发生改变对应的data中的数据就会自动发生改变。
lazy修饰符可以让数据在失去焦点或者回车时才会更新
<div id="app">
<!-- lazy修饰符 只有回车或失去焦点时才拿到数据 -->
<input type="text" v-model.lazy="message">
<p>你拿到的数据是{{message}}</p>
</div>
2.number修饰符
默认情况下,在输入框中无论我们输入的是字母还是数字,都会被当做字符串类型进行处理。但是如果我们希望处理的是数字类型,那么最好直接将内容当做数字处理。
number修饰符可以让在输入框中输入的内容自动转成数字类型
<div>
<input type="number" v-model.number="nbr">
<!-- 事件修饰符也可以连写 -->
<input type="number" v-model.number.lazy="nbr">
<p>你拿到的数据是{{nbr}}</p>
</div>
3.trim修饰符
如果输入的内容首尾有很多空格,通常我们希望将其去除.trim修饰符可以过滤内容左右两边的空格.
<!-- trim修饰符 -->
<div>
<input type="text" v-model.trim.lazy="trim">
<p>你拿到的数据是{{trim}}</p>
</div>
3. v-bind 绑定style
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=., initial-scale=1.0">
<title>Document</title>
</head>
<style>
</style>
<body>
<div id="app">
<!-- style 对象语法1 {}中 属性名: "属性值"-->
<div :style="{color:'#ccc'}">{{text}}</div>
<!-- style 对象语法2 属性值不加 "" Vue会解释为变量 则会去data中查找 -->
<div :style="{color:color}">{{text}}</div>
<!-- style 数组语法 数组中每个元素的值是data中 变量 该语法基本不适用 -->
<div :style="[bgStyle,color]">{{text}}</div>
</div>
<script src="../lib/dep/plugins/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data() {
return {
text: "憨八龟",
color: "#eee",
bgStyle: {
background: "pink",
fontSize: "28px"
},
color: "#fff"
}
},
})
</script>
</body>
</html>
4. 事件绑定 v-on
Vue中通过v-on绑定事件,例如绑定单击事件 v-on:click 。当然了v-on也有相对应的语法糖 @ 例如@click。每个事件都有自己的事件对象,事件对象存放着一些对事件的描述 比如说参数 以及事件触发的位置等等。
编程界万年不变的点击按钮加减案例:
<body>
<div id="app">
<div>{{number}}</div>
<!-- 通过v-on事件绑定 也可以通过语法糖 @ (常用)进行绑定-->
<!-- 如果只是单纯的运算 也可以直接写在html中 或者写在methods中 -->
<button v-on:click='number++'>你一按我就加</button>
<button @click="reduce">你一按我就减</button>
</div>
<script src="../lib/dep/plugins/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data() {
return {
number: 20
}
},
methods: {
/**减法 */
reduce() {
this.number--
}
},
})
</script>
</body>
4.1 事件函数参数传递
- 如果事件直接绑定函数名称,则默认会传递事件对象作为事件函数的第一个参数。例 @click=“submit”
- 如果格式为@click=“submit()”,则表示不传递任何参数
- 如果事件绑定调用函数 , 那么最后一个参数是事件对象,且事件对象的名字必须为$event
<body>
<div id="app">
<div>{{number}}</div>
<!-- 通过v-on事件绑定或者说事件监听 也可以通过语法糖 @ (常用)进行绑定-->
<!-- 如果只是单纯的运算 也可以直接写在html中 或者写在methods中 -->
<button v-on:click='number++'>你一按我就加</button>
<!-- 标准写法是@click="reduce()"表示调用一个方法 不过可以省略() 如果reduce方法有参数 那么这个参数就是事件对象 -->
<button @click="reduce">你一按我就减</button>
<button @click="multiply(20,$event)">你一按我就乘</button>
</div>
<script src="../lib/dep/plugins/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data() {
return {
number: 20
}
},
methods: {
/**减法
因为每个事件都有自己的事件对象,如果不传参的话 默认第一个参数为事件对象
如果上面绑定格式是@click="reduce"的话,event形参就是事件对象
如果上面绑定的格式是@click="reduce()"的话打印就是undefined
像@click="reduce()" 表示要传的参数为空 函数需要实参,但是调用时没有传值给函数,形参是undefined;
*/
reduce(event) { //event是形参 传递实参 接收为形参
console.log(event)
this.number--
},
/**
* 乘法
*
*/
multiply(value, event) {
this.number *= value
console.log(event)
}
},
})
</script>
</body>
注意 如果传递的参数为字符类型一定要加引号,如果不加引号 ,vue会解释为变量,然后去data中查找,如果找不到会报错。
4.2 事件修饰符
常用事件修饰符
事件修饰符 | 作用 |
---|---|
stop | 阻止事件冒泡 |
prevent | 阻止默认行为(例如a链接的跳转) |
self | 只有是当前元素自身时才能触发的函数 |
once | 只触发一次回调 |
native | 监听组件根元素的原生事件(后续会讲) |
keyup | 常用按键修饰符 |
注意:
使用修饰符时,顺序很重要,相应的代码会以同样的顺序产生.因此使用 @click.prevent.self 会阻止所有点击,
用@click.self.prevent 只会阻止元素自身的点击
常用的按键修饰符:keyup 表单搜索等特定的场景有用到,目的时提升用户的体验,例如在PC端搜索输入回车即可搜索等等
按键修饰符 | 说明 |
---|---|
enter | 回车键 |
tab | tab键 |
esc | 取消键 |
soace | 空格键 |
按键修饰符也可以使用相对应的键盘吗 例如 v-on: keyup.13="submit"
代码部分:
5. 分支结构
5.1 条件指令 v-if
Vue中条件指令有 v -if 、v-else-if 、v-else 。与JavaScript的条件语句if、else、else if类似。
**Vue的条件指令 可以根据表达式的值在DOM中渲染或销毁元素或组件 **。
案例如下:
5.1.1 v-if key的问题
下面的案例 是 登录切换的功能,在开发中比较常见,但如果不注意很有可能掉入BUG中。
造成这一问题的原因:
- 这是因为Vue在进行DOM渲染时,出于性能考虑,会尽可能的复用已经存在的元素,而不是重新创建新的元素。
- 上面的案例Vue内部会发现原来的input元素不再使用,直接作为else中的input来使用了。
解决办法:
方法一:通过v-model 对input 进行双向数据绑定,当点击切换按钮的时候,清除input的输入。
方法二:给input标签加上一个key标识符,key的作用主要是为了高效的更新虚拟DOM,key标识符必须是作用域中独一无二的。
5.2 条件指令 v-show
v-show 指令通过改变元素的 css 属性(display)来决定元素是显示还是隐藏。
v-if 和v- show 的区别:
- v-if 控制元素是否渲染到页面
- v-show控制元素是否显示 (已经渲染到页面 )
v-if 和v-show的使用场景:
v-if 指令开销较大,所以更适合条件不经常改变的场景。而 v-show 指令适合条件频繁切换的场景。
5.3 循环指令 v-for
5.3.1 遍历数组
5.3.2 遍历对象
5.3.3 key标识符的作用
为什么需要这个key属性呢?
这个其实和Vue内部也使用了虚拟DOM有关系(和小程序、React很相似)。
当某一层有很多相同的节点时,也就是列表节点时,我们希望插入一个新的节点
我们希望可以在B和C之间加一个F,Diff算法默认执行起来是这样的。即把C更新成F,D更新成C,E更新成D,最后再插入E。
所以我们需要使用key来给每个节点做一个唯一标识,这样做的好处:
- Diff算法就可以正确的识别此节点
- 找到正确的位置区插入新的节点。
图右是加了key标识符
所以一句话,key的作用主要是为了高效的更新虚拟DOM。
5.3.4 双重for循环
5.4 数组相关API
在Vue中直接修改对象属性的值无法触发响应式.当你直接修改了对象的属性值,只是数据修改了,但页面没有更新.
当使用this.arr[1]=5方法时,结果没有渲染到页面上
当使用$set 时,数据成功渲染到页面上
变异方法(修改原有数据)
变异数组方法即保存数组方法原功能不变的情况下,对其功能进行拓展,使其响应式.
方法 | 说明 | 例子 |
---|---|---|
push() | 往数组的最后面添加元素,返回当前数组长度 | this.arr.push(“张三”,“李四”) |
pop() | 删除数组最后一个元素,返回删除元素的值 | this.arr.pop() |
shift() | 删除数组第一个元素,返回删除的元素值 | this.arr.shift() |
unshit() | 往数组的最前面添加元素,返回当前数组长度 | this.arr.unshit(“张三”,“李四”) |
splice() | 删除,替换,添加数组元素,有三个参数(在下面说明) | this.arr.splice(2,0,“张三”,“李四”) |
sort() | 使数组按照字符编码默认从小到大排序,成功返回排序后的数组 | this.arr.sort() |
reverse() | 将数组倒序,成功后返回倒序后的数组 | this.arr.reverse() |
splice方法 有三个参数
- 参数一: 开始的元素下标或者说"起点"(必写)
- 参数二: 想要删除的个数,如果不想删除就写0 (必写)
- 参数三: 想要在原位置替换或插入的值,可以多个 (可选)
替换数组(生成新的数组)
方法 | 说明 |
---|---|
filter | 通过检查指定数组中符和条件的所有元素,返回新的数组 |
concat | 用于连接(拼接或说合并)数组 |
clice | 可从已有的数组 中返回选定的元素 |
三个方法没有改动 详情请参照javaScript官网
5.6 分支结构的代码部分
5.6.1 条件指令案例1 分数
<!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">
<h3 v-if="grade>90">优</h3>
<h3 v-else-if="grade>80&& grade<90">良</h3>
<h3 v-else>回去挨揍把,耶稣祝你平安</h3>
<h3>{{result}}</h3>
</div>
<script src="../lib/dep/plugins/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data() {
return {
grade: 70,
}
},
// Vue定义的计算属性,适合存放多个变量或对象进行处理后的返回值,与data等级相同。
// 一般需要计算的 推荐放入computed 上述的案例就适合放在computed
computed: {
// 个人不喜欢使用switch 所以使用if
result() {
let grade = this.grade
switch (grade) {
case grade > 90:
return "优秀的娃"
break;
case grade > 80 && grade < 90:
return "还行把"
break;
default:
return "回去挨揍把,耶稣祝你平安"
break;
}
}
}
})
</script>
</body>
</html>
5.6.2 条件指令案例2 登录表单
<!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>登录案例</title>
</head>
<body>
<div id="app">
<div v-if="type">
<label for="account">请输入您的账号:</label>
<!-- key标识符的用法 key:"标识符名称" -->
<input type="text" id="account" :key="account-ipt">
<!-- <input type="text" id="account" v-model="username"> -->
</div>
<div v-else>
<label for="phone">请输入您的手机:</label>
<input type="text" id="phone" :key="phone-ipt">
<!-- <input type="text" id="phone" v-model="username"> -->
</div>
<button @click="status">
切换到{{content}}登录
</button>
</div>
<script src="../lib/dep/plugins/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
// 存放变量
data() {
return {
type: true, //登录的类型 true账号登录 否则 手机登录 默认账号登录
content: "手机",
username: ''
}
},
// 存放方法
methods: {
status() {
if (this.type) {
this.type = false
this.content = "账号"
// this.username = ""
} else {
this.type = true
this.content = "手机"
// this.username = ""
}
}
},
})
</script>
</body>
</html>
5.6.3 循环指令案例1 遍历数组
<!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">
<ul>
<!-- v-for 代码格式 v-for ="(参数一,参数二) in 要循环的数组名" -->
<!-- 参数一:每个元素(自命名) 参数二:元素的索引值(自命名,可省略) -->
<li v-for="item in arr"> {{item}}</li>
<li v-for="(item,value) in arr"> 我的名字:{{item}} 我的索引:{{value}}</li>
</ul>
</div>
<script src="../lib/dep/plugins/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data() {
return {
arr: ["路飞", "艾斯", "女帝", "娜美", "山治"],
}
},
})
</script>
</body>
</html>
5.6.4 循环指令案例2 遍历对象
<!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">
<!-- for 遍历对象有3个参数 -->
<div v-for="(value,key,index) in personal" :key="value.id">
<!-- 参数一:对象的值(必写) -->
<span>{{value}}</span>
<!-- 参数二: 对象的key(可选) -->
<span>{{key}}</span>
<!-- 参数三:当前对象值的索引 (可选,遍历对象中用途不大)-->
<span>{{index}}</span>
</div>
</div>
<script src="../lib/dep/plugins/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data() {
return {
personal: {
name: "伍六一",
profession: "士兵突击副班长||玄武国杀手",
age: 3333
}
}
},
})
</script>
</body>
</html>
5.6.5 循环指令案例3 双重for循环
<!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">
<div v-for="list in data" :key='list.id'>
<!-- {{list}} -->
<div v-for="item in list" :key='item.id'>
{{item}}
</div>
</div>
</div>
<script src="../lib/dep/plugins/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data() {
return {
// 后端返回的数据
// data: {
// "success": "true",
// "code": "0",
// "msg": "访问成功",
"data": [{
"noticeId": 3,
"noticeTitle": "第三条测试公告",
"noticeContent": "<p>第三条测试公告内容</p>",
"noticeFlag": "A",
"createBy": "admin",
"createTime": "2021-01-19 15:58:39"
}, {
"noticeId": 4,
"noticeTitle": "第四条测试公告",
"noticeContent": "<p>第四条测试公告内容</p>",
"noticeFlag": "B",
"createBy": "admin",
"createTime": "2021-01-19 15:58:39"
}, ]
// }
}
},
methods: {
},
})
</script>
</body>
</html>