文章目录
- 4.1 语法
引言
Vue 是一款渐进式 JavaScript 框架,用来动态构建用户界面。
○ 遵循 MVVM 模式
○ 编码简洁、体积小、运行效率高,适合移动/PC 端开发。
○ 本身只关注UI,可以轻松引入 vue 插件或其它第三库开发项目。
○ 国内大规范使用、生态系统完善。
● 官网地址:
○ https://cn.vuejs.org/
● 作者: 尤雨溪。
● 框架下载:
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
1.快速入门
1.1.创建项目
新建 HTML 页面,引入 Vue.js文件
<script src="js/vue.js"></script>
1.2.模型和视图
Model
<script>
<!-- 模型 -->
new Vue({
el: '#app',
// data: {
// name: '尤雨溪',
// message: 'Hello Vue'
// }
// ES6 语法
data() {
return {
name: '尤雨溪',
message: 'Hello Vue'
}
}
})
</script>
View
<!-- 视图 -->
<div id="app">
<p>{{name}}</p>
<p>{{message}}</p>
<input type="text" v-model="message">
</div>
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello Vue</title>
</head>
<body>
<!-- 视图 -->
<div id="app">
<p>{{name}}</p>
<p>{{message}}</p>
<input type="text" v-model="message">
</div>
<script src="js/vue.js"></script>
<script><!-- 模型 -->
new Vue({
el: '#app',
// data: {
// name: '尤雨溪',
// message: 'Hello Vue'
// }
// ES6 语法
data() {
return {
name: '尤雨溪',
message: 'Hello Vue'
}
}
})</script>
</body>
</html>
运行效果:
1.3.双向数据绑定
MVVM (Model-View-ViewModel)思想,实现数据的双向绑定,将编程的关注点放在数据上。
jQuery 是将关注点放在了 DOM 操作上;先回顾下MVC:
MVC 只能实现模型到视图的单向展示。
双向绑定是指当数据模型数据发生变化时,页面展示的内容会随之发生变化,而如果表单数据发生变化,绑定的模型数据也随之发生变化。MVVM 如下图:
Model 和 View 是通过 ViewModel 对象进行双向绑定的。模型数据发生变化,会更新到视图,视图内容变化,也会更新模型数据。
2.{{ }} - 插值
2.1.语法
● {{ }} 中可以插入文本,上面的案例就是;
● {{ }} 中可以插入JavaScript 表达式;
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
● {{ }} 中只支持表达式,不支持其它语句;
<!-- 这是语句,不是表达式 -->
{{ var a = 1 }}
<!-- 流控制也不会生效,请使用三元表达式 -->
{{ if (ok) { return message } }}
2.2.案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>插值</title>
</head>
<body>
<div id="app">
{{message}}</br>
{{ number + 1 }}</br>
{{ ok ? 'YES' : 'NO' }}</br>
<!-- {{ var a = 1 }}</br>-->
<!-- 流控制也不会生效,请使用三元表达式 -->
<!-- {{ if (ok) { return message } }}</br>-->
</div>
<script src="js/vue.js"></script>
<script>new Vue({
el: '#app',
data() {
return {
message: 'Hello Vue!!!',
number: 100,
ok: false
}
}
})</script>
</body>
</html>
3.v-text、v-html(内容绑定)
● 可以用在 div、p、span、a、h1-h6 等有内容的标签上,为标签插入内容;
● v-text 插入普通文本
● v-html 插入 HTML 代码片段
3.1 语法
<标签 v-text="标签内容"></标签>
<标签 v-html="标签内容"></标签>
3.2 案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>插值和属性绑定</title>
</head>
<body>
<div id="app">
书名:<span v-text="book.name"></span> <br>
作者:<span v-text="book.author"></span> <br>
内容:<span v-text="book.content"></span> <br>
----------------------------------------------
<span v-html="book.content"></span> <br>
</div>
</body>
</html>
<script src="js/vue.js"></script>
<script>new Vue({
el: '#app',
data() {
return {
book: {
name: '三体',
author: '刘慈欣',
content: '<p>此处省略一万字....</p>'
}
};
}
})</script>
4.v-bind (属性绑定)
4.1 语法
● {{ }}、v-text、v-html 语法不能作用在 HTML 标签的属性上;
● v-bind 指令可以用于响应式地更新 HTML 标签的属性。
<标签 v-bind:属性名称="属性值"></标签>
<!--使用缩写-->
<标签 :属性名称="属性值"></标签>
4.2 案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>属性绑定</title>
</head>
<body>
<div id="app">
<a v-bind:href="url">百度</a> | <a :href="url">百度</a>
<span :title="tit">大家好</span>
</div>
<script src="js/vue.js"></script>
<script>new Vue({
el: '#app',
data() {
return {
url: 'https://www.baidu.com',
tit : 'Hello Vue'
}
}
})</script>
</body>
</html>
5.v-on(事件监听 )
● 可以用 v-on 指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码。
5.1 语法
<!-- 完整语法 -->
<标签 v-on:click="doSomething">...</标签>
<!-- 缩写 -->
<标签 @click="doSomething">...</标签>
5.2.案例
案例一
基本用法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件监听</title>
</head>
<body>
<div id="app">
点击次数:{{count}}
<button v-on:click="count++">点击</button>
</div>
<script src="js/vue.js"></script>
<script>new Vue({
el:"#app",
data() {
return {
count: 0
}
}
});</script>
</body>
</html>
案例二
许多事件处理逻辑会更为复杂,所以直接把 JavaScript 代码写在 v-on 指令中是不可行的。
因此 v-on 还可以接收一个需要调用的函数名称。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件绑定</title>
</head>
<body>
<div id="app">
点击次数:{{count}}
<button v-on:click="count++">点击</button>
<button @click="add" :disabled="disabled">点击我</button>
</div>
<script src="js/vue.js"></script>
<script>new Vue({
el: '#app',
data() {
return {
count: 0,
disabled: false
}
},
methods: {
// add: function () {
// if (this.count >= 5) {
// this.disabled = true;
// } else {
// this.count++
// }
// }
add() {
if (this.count >= 5) {
this.disabled = true;
} else {
this.count++
}
}
}
})</script>
</body>
</html>
案例三
除了直接绑定到一个方法,也可以在内联 JavaScript 语句中调用方法:
<div id="app">
hello {{name}} ! <br>
<button @click="say('jack')">点击</button>
</div>
<script src="js/vue.js"></script>
<script>new Vue({
el: '#app',
data: {
name: ''
},
methods: {
say(name) {
this.name = name;
}
}
});</script>
案例四
阻止默认事件,以表单提交为例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>阻止默认事件</title>
</head>
<body>
<div id="app">
<form v-on:submit.prevent action="https://www.baidu.com" method="post">
<button type="submit">提交</button>
</form>
<form action="https://www.baidu.com" method="post">
<button type="submit" v-on:click.prevent>提交</button>
</form>
</div>
<script src="js/vue.js"></script>
<script>new Vue({
el: "#app"
});</script>
</body>
</html>
6.v-if(条件渲染)
6.1.语法
● v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。
● v-else-if 元素必须紧跟在带 v-if 或者 v-else-if 的元素之后,否则它将不会被识别。
<标签 v-if="布尔表达式"></标签>
<标签 v-if="布尔表达式"></标签>
<标签 v-else></标签>
<标签 v-if="布尔表达式1"></标签>
<标签 v-else-if="布尔表达式2"></标签>
<标签 v-else-if="布尔表达式3"></标签>
...
<标签 v-else></标签>
6.2 案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<div v-if="age>18">成年人</div>
<hr>
<div v-if="age<18">未成年</div>
<div v-else>成年人</div>
<hr>
<div v-if="age<18">未成年</div>
<div v-else-if="age<40">有位青年</div>
<div v-else-if="age<60">步入中年</div>
<div v-else>进入老年</div>
</div>
<script src="js/vue.js"></script>
<script>new Vue({
el: '#app',
data: {
age: 65
}
})</script>
</body>
</html>
6.3 v-show
带有 v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简单地切换元素的 CSS display属性。
<div v-show="false">大家好</div>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<div v-show="false">大家好</div>
</div>
<script src="js/vue.js"></script>
<script>new Vue({
el: '#app'
})</script>
</body>
</html>
<div v-show="true">大家好</div>
6.4 v-if vs v-show
● v-if 是真正的条件渲染,它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
● v-if 是惰性的:如果在初始渲染时条件为假,则什么也不做直到条件第一次变为真时才会渲染条件块。
● v-show 不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
● v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。
● 如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。
7. v-for(列表渲染)
7.1 语法
基于源数据多次渲染元素或模板块。此指令之值,必须使用特定语法 alias in expression
,为当前遍历的元素提供别名:
expression
支持的类型: number
、 string
、array 等。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<span v-for="num in 10">{{num}}</span> <br>
<span v-for="num in 10" v-text="num"></span>
<hr>
<span v-for="str in 'abcdef' ">{{str}} - </span>
<hr>
<ul>
<li v-for="name in arr" v-text="name"></li>
</ul>
<hr>
<table>
<tr>
<th>用户名</th>
<th>邮箱</th>
</tr>
<tr v-for="user in userList">
<td>{{user.username}}</td>
<td>{{user.email}}</td>
</tr>
</table>
</div>
<script src="js/vue.js"></script>
<script>new Vue({
el: '#app',
data() {
return {
arr: ['Java', 'C++', 'PHP'],
userList: [{
username: 'jack',
email: '[email protected]'
}, {
username: "rose",
email: "[email protected]"
}]
}
}
})</script>
</body>
</html>
7.3 更多细节
你也可以用 of 替代 in 作为分隔符
<div v-for="item of items"></div>
v-for 还支持一个可选的第二个参数,即当前项的索引。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<ul id="app">
<li v-for="(item, index) in items">
{{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
</ul>
<script src="js/vue.js"></script>
<script>new Vue({
el: '#app',
data: {
parentMessage: 'Parent',
items: [
{ message: 'Foo' },
{ message: 'Bar' },
{ message: 'Three' }
]
}
})</script>
</body>
</html>
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,建议为每项提供一个唯一 key:
<div v-for="item in items" v-bind:key="item.id">
<!-- 内容 -->
</div>
不要使用对象或数组之类的非基本类型值作为 v-for 的 key。请用字符串或数值类型的值。
8.v-model(表单输入绑定)
v-model 指令在表单<input>
、<textarea>
及 <select>
元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
v-model 会忽略所有表单元素的 value、checked、selected 属性的初始值而总是将 Vue 实例的数据作为数据来源。需要通过 data 选项声明初始值。
v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:
● text 和 textarea 使用 value 属性 和 input 事件;
● checkbox 和 radio 使用 checked 属性 和 change 事件;
● select 使用 value 属性和 change 作为事件。
8.1 单行文本和多行文本
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<div>
<div>
<label>用户名:</label>
<input type="text" v-model="user.username"/>
</div>
<div>
<label>简介:</label>
<textarea v-model="user.intro"></textarea>
</div>
<hr>
用户名:{{user.username}}<br>
简介:{{user.intro}}<br>
</div>
</div>
<script src="js/vue.js"></script>
<script>new Vue({
el:"#app",
data:{
user:{
username:"jack",
intro:"我是jack"
}
}
})</script>
</body>
</html>
8.2 单选按钮
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<div>
<div>
<label>性别:</label>
<input type="radio" v-model="user.sex" value="1"> <label>男</label>
<input type="radio" v-model="user.sex" value="2"> <label>女</label>
</div>
</div>
<hr>
性别:{{user.sex}}<br>
</div>
<script src="js/vue.js"></script>
<script>new Vue({
el: '#app',
data: {
user: {
sex: '2'
}
}
})</script>
</body>
</html>
8.3 复选框
单个复选框
单个复选框,默认绑定到布尔值:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<div>
<input type="checkbox" v-model="agree">
<label>阅读并接受</label>
<a target="_blank" href="">《XX用户协议》</a>
</div>
<hr>
同意:{{agree}}<br>
</div>
<script src="js/vue.js"></script>
<script>new Vue({
el: '#app',
data: {
agree: true
}
})</script>
</body>
</html>
使用自定义值:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<div>
<input type="checkbox" v-model="agree" true-value="Y" false-value="N">
<label>阅读并接受</label>
<a target="_blank" href="">《XX用户协议》</a>
</div>
<hr>
同意:{{agree}}<br>
</div>
<script src="js/vue.js"></script>
<script>new Vue({
el: '#app',
data: {
agree: 'Y'
}
})</script>
</body>
</html>
多个复选框
多个复选框,绑定到同一个数组:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<div>
<div>
<label>爱好:</label>
<input type="checkbox" v-model="user.love" value="1">
<label>羽毛球</label>
<input type="checkbox" v-model="user.love" value="2">
<label>篮球</label>
<input type="checkbox" v-model="user.love" value="3">
<label>足球</label>
</div>
</div>
<hr>
爱好:{{user.love}}<br>
</div>
<script src="js/vue.js"></script>
<script>new Vue({
el: '#app',
data: {
user: {
love: [2,3]
}
}
})</script>
</body>
</html>
8.4 下拉列表
单选
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<div>
<div>
<label>城市:</label>
<select v-model="city">
<option value="" disabled>请选择城市</option>
<option value="1">上海</option>
<option value="2">北京</option>
<option value="3">深圳</option>
</select>
</div>
</div>
<hr>
城市:{{city}}<br>
</div>
<script src="js/vue.js"></script>
<script>new Vue({
el: '#app',
data: {
city: '2'
}
})</script>
</body>
</html>
多选
绑定到数组
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<div>
<div>
<label>城市:</label>
<select v-model="city" multiple>
<option value="" disabled>请选择城市</option>
<option value="1">上海</option>
<option value="2">北京</option>
<option value="3">深圳</option>
</select>
</div>
</div>
<hr>
城市:{{city}}<br>
</div>
<script src="js/vue.js"></script>
<script>new Vue({
el: '#app',
data: {
city: []
}
})</script>
</body>
</html>
8.5 动态选项
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<div>
<div>
<label>国家:</label>
<select v-model="country">
<option value="" disabled>请选择国家</option>
<option v-for="country in countryList"
v-bind:value="country.value">{{country.text}}</option>
</select>
</div>
</div>
<hr>
国家:{{country}}<br>
</div>
<script src="js/vue.js"></script>
<script>new Vue({
el: '#app',
data: {
country: '',
countryList: [{
text: '中国',
value: '1'
}, {
text: '日本',
value: '2'
}, {
text: '韩国',
value: '3'
}]
}
})</script>
</body>
</html>
9. <template>
指令必须在 HTML 标签上才能使用。但是如果想切换多个元素呢?此时可以把一个 <template>
标签当做不可见的包裹元素,并在上面使用指令。最终的渲染结果将不包含 <template>
标签。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<template v-if="v">
<span>大家好</span>
</template>
</div>
<script src="js/vue.js"></script>
<script>new Vue({
el: '#app',
data: {
v: false
}
})</script>
</body>
</html>
10.计算属性和侦听属性
10.1.计算属性
模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。例如:
<div id="example">
{{ message.split('').reverse().join('') }}
</div>
模板中也不支持 JavaScript 的复杂语句,比如 循环,分支。所以,对于任何复杂逻辑,你都应当使用计算属性
。
基础例子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- 计算属性 -->
<div id="app">
{{ msg }}
<br>
{{computeMsg}} | {{computeMsg}}
<hr>
<input v-model="msg">
</div>
<script src="js/vue.js"></script>
<script>new Vue({
el: '#app',
data: {
msg: 'Hello Vue'
},
// 计算属性要有返回值
// 原始数据发生改变,计算属性会重新计算
computed: {
computeMsg: function () {
// 可以进行复杂的逻辑处理和计算
console.log('computeMsg...');
return this.msg.toUpperCase();
}
}
})</script>
</body>
</html>
● 计算属性要有返回值;
● 原始数据发生改变,计算属性会重新计算;
● 原始数据没有改变,多次访问计算属性,不会重新计算。
计算属性缓存 vs 方法
你可能已经注意到我们可以通过在表达式中调用方法来达到同样的效果:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- 计算属性 -->
<div id="app">
{{ msg }}
<br>
{{computeMsg}} | {{computeMsg}}
<br>
{{ methodMsg() }} | {{ methodMsg() }}
<hr>
<input v-model="msg">
</div>
<script src="js/vue.js"></script>
<script>new Vue({
el: '#app',
data: {
msg: 'Hello Vue'
},
// 计算属性要有返回值
// 原始数据发生改变,计算属性会重新计算
computed: {
computeMsg: function () {
// 可以进行复杂的逻辑处理和计算
console.log('computeMsg1...')
return this.msg.toUpperCase();
}
},
methods: {
methodMsg: function () {
console.log('methodMsg2...')
return this.msg.toUpperCase();
}
}
})</script>
</body>
</html>
多次调用方法,方法会执行多次,计算属性只再原始值发生改变的时候才重新计算。
10.2.侦听属性
Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:侦听属性。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- 侦听属性 -->
<div id="app">
<input type="text" v-model="firstName" placeholder="input firstName"> <br>
<input type="text" v-model="lastName" placeholder="input lastName"> <br>
fullname: {{computedFullName}}
</div>
<script src="js/vue.js"></script>
<script>new Vue({
el: '#app',
data: {
firstName: '',
lastName: '',
fullName: ''
},
// 侦听属性
watch: {
firstName: function (firstName) {
this.fullName = firstName + ' ' + this.lastName;
},
lastName: function (lastName) {
this.fullName = this.firstName + ' ' + lastName;
}
},
// 计算属性
computed: {
computedFullName: function () {
return this.firstName + ' ' + this.lastName;
}
}
})</script>
</body>
</html>
虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。
当需要在数据变化时执行异步或开销较大的操作时,建议使用侦听属性。
11.生命周期
11.1.生命周期图
● beforecreate : 一般使用场景是在加载 loading事件的时候
● created :处于loading结束后,还做一些初始化,实现函数自执行(data数据已经初始化,但是DOM结构渲染完成,组件没有加载)
● beforemount:处于组件创建完成,但未开始执行操作
● mounted :处于发起后端请求,获取数据,配合路由钩子执行操作(DOM渲染完成,组件挂载完成 )
● beforeupdate、updated:处于数据更新的前后
● beforeDestroy:当前组件还在的时候,想删除组件
● destroyed :当前组件已被销毁,清空相关内容
生命周期 | 是否获取dom节点 | 是否可以获取data | 是否获取methods |
beforeCreate | 否 | 否 | 否 |
created | 否 | 是 | 是 |
beforeMount | 否 | 是 | 是 |
mounted | 是 | 是 | 是 |
看到上面的图,大家无需过多的关注这张图。这些钩子方法我们只关注 mounted 就行了。
mounted:挂载完成,Vue初始化成功,HTML页面渲染成功。而以后我们会在该方法中发送异步请求,加载数据。
11.2.created 与 mounted 的区别
● created:在模板渲染成 html 前调用,即通常初始化某些属性值,然后再渲染成视图。
● mounted:在模板渲染成 html 后调用,通常是初始化页面完成后,再对 html 的 dom 节点进行一些需要的操作。