共计 10001 个字符,预计需要花费 26 分钟才能阅读完成。
基础知识
基础环境
- vscode
- 所需的插件:
jshint:JS 代码检查
Beautify:代码美化(选中代码 –>format doc)
Vetur: Vue 插件
JavaScript (ES6) code snippets:ES6 语法
Auto Rename Tag:自动重命名标签
Vue-helper:Vue 提示
vscode-icons:文件夹图标
open in browser
vscode 快捷键
ctrl+k
以及 ctrl+s
打开快捷键窗口,以便查看快捷键
Vue 介绍
是一套构建前后端分离的架构
Vue 的安装和使用
三种方式:
- script 标签引用
<!-- development version, includes helpful console warnings -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- production version, optimized for size and speed -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
- npm 安装
- vue-cli 安装
Vue 体验
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="../lib/vue.js"></script>
<title>01VueStudy</title>
</head>
<body>
<div id="app">
<p>{{greet() }}</p>
<p>{{username}}</p>
<button @click="username=' 隔壁老王 '"> 更改值 </button>
</div>
</body>
<script>
new Vue({
el: '#app',
data: {username: "Hello"},
methods: {greet() {return "你好啊"}
}
})
</script>
</html>
Vue 的模板语法
- v-bind: 属性绑定
- v-once: 在模板中只读取一次变量,后续变量更改了,不会跟着变化
- v-html: 解析 html 标签
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="../lib/vue.js"></script>
<title>vue v-bind</title>
</head>
<body>
<div id="app">
<p v-once>{{username}}</p>
<p v-html='code'>{{code}}</p>
<button @click="username=' 隔壁老王 '"> 改变 </button>
<img v-bind:src="logo" alt="">
</div>
</body>
<script>
new Vue({
el: "#app",
data: {
username: "Alex",
code: "<a href='https://www.baidu.com'>BAT</a>",
logo: "https://vuejs.org/images/logo.png"
}
})
</script>
</html>
Vscode 添加自定义代码片段
ctrl+shift+p
- 搜索
Snippets
关键字,选择 Preferance - 选择 html.json,修改成如下的样子
{
"my vue html code": {
"prefix": "html",
"body": [
"<!DOCTYPE html>",
"<html lang='en'>",
"<head>",
"<meta charset='UTF-8'>",
"<meta name='viewport'content='width=device-width, initial-scale=1.0'>",
"<meta http-equiv='X-UA-Compatible'content='ie=edge'>",
"<script src='../lib/vue.js'></script>",
"<title>$1</title>",
"</head>",
"<body>",
"<div id='app'>",
"</div>",
"</body>",
"<script>",
"new Vue({",
"el:'#app',",
"data: {",
"$2",
"}",
"})",
"</script>",
"</html>",
],
"description": "my vue html code"
}
}
属性绑定
- 绑定 class 的两种形式
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<meta http-equiv='X-UA-Compatible' content='ie=edge'>
<script src='../lib/vue.js'></script>
<title></title>
<style>
.title{
font-size: 20px;
color: red
}
.main-title{font-weight: 1800;}
</style>
</head>
<body>
<div id='app'>
<!-- 数组方式 -->
<p v-bind:class="[pclass1,pclass2]">I like Vue</p>
<!-- 对象方式 -->
<p :class="{'title':true,'main-title':strong}"> 我是隔壁老王 </p>
<button @click="strong=true"> 文字加粗 </button>
<!-- 对象方式 -->
<p :style="{backgroundColor:backgroundColor}"> 属性绑定样例 </p>
<!-- 数组方式 -->
<p :style="[Pstyle1,Pstyle2]"> 属性绑定样例 2 </p>
</div>
</body>
<script>
new Vue({
el: '#app',
data: {
pclass1: "title",
pclass2: "main-title",
strong: false,
backgroundColor: "red",
Pstyle1: {
'background-color':'blue',
'font-size': '30px'
},
Pstyle2: {"border-bottom":"2px solid #000"}
}
})
</script>
</html>
使用 JS 表达式
在属性绑定和变量读取中,可以使用表达式。常见的表达式有:变量读取,变量运算,三目运算符,函数调用,取反等
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<meta http-equiv='X-UA-Compatible' content='ie=edge'>
<script src='../lib/vue.js'></script>
<title></title>
</head>
<body>
<div id='app'>
<div :style="{color: danger?'red':'black'}">{{message.split("").reverse().join(" ") }}</div>
<div>{{greet() }}</div>
<div>{{!is_adult}}</div>
</div>
</body>
<script>
new Vue({
el: '#app',
data: {
// 条件?条件成立的值:条件不成立的值
// danger: true
danger: false,
message: "Hello World Hello China",
is_adult: true
},
methods: {greet() {return "Good Morning!!"}
}
})
</script>
</html>
条件判断
if 系列
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<meta http-equiv='X-UA-Compatible' content='ie=edge'>
<script src='../lib/vue.js'></script>
<title>Vue 判断 </title>
</head>
<body>
<div id='app'>
<p v-if="weather=='sun'">GoPark</p>
<p v-else-if="weather='rain'">WatchMovie</p>
<p v-else>StayHome</p>
</div>
</body>
<script>
new Vue({
el: '#app',
data: {weather: "rain"}
})
</script>
</html>
多重条件使用 template
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<meta http-equiv='X-UA-Compatible' content='ie=edge'>
<script src='../lib/vue.js'></script>
<title>IF</title>
</head>
<body>
<div id='app'>
<template v-if="age < 18">
<p>AAA</p>
</template>
<template v-else-if="age >=18 && age <= 20">
<p>BBB</p>
</template>
<template v-else>
<p>CCC</p>
</template>
</div>
</body>
<script>
new Vue({
el: '#app',
data: {age: 24}
})
</script>
</html>
method 小例子
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<script src='../lib/vue.js'></script>
<title>V-if</title>
</head>
<body>
<div id='app'>
<template v-if="loginType=='username'">
<label> 用户名 </label>
<input type="text" name="username" placeholder="用户名">
</template>
<template v-else-if="loginType=='email'">
<label> 邮箱 </label>
<input type="text" name="email" placeholder="email">
</template>
<button @click="changeLoginType"> 更换登录类型 </button>
</div>
</body>
<script>
new Vue({
el: '#app',
data: {loginType: "username"},
methods: {changeLoginType() {
// 三目运算符
this.loginType = this.loginType =='username'?"email":"username"
}
}
})
</script>
</html>
小结:
-
v-if
,v-else-if
,v-else
- 如果想要某个调间下渲染多个元素,那么就要使用
template
标签 - Vue 默认会重用相同的标签来提高性能,如果不要重用的话,那就在对应的元素上加一个
key
属性即可
v-show 和 v -if 的区别
v-show: 是通过简单的切换 display 来渲染信息,会一次性加载所有的元素,在频繁切换的状态下推荐使用,不能在 template 标签上使用
v-if: 真正的条件渲染,如果条件更改了,会重新加载
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<meta http-equiv='X-UA-Compatible' content='ie=edge'>
<script src='../lib/vue.js'></script>
<title></title>
</head>
<body>
<div id='app'>
<div v-show="loginType=='username'">
<label> 用户名 </label>
<input type="text" name="username" placeholder="username" key="username">
</div>
<div v-show="loginType=='email'">
<label> 邮箱 </label>
<input type="text" name="email" placeholder="email" key="email">
</div>
<button @click='changeLoginType'> 切换登录方式 </button>
</div>
</body>
<script>
new Vue({
el: '#app',
data: {loginType: "username"},
methods: {changeLoginType() {this.loginType = this.loginType=='username'?'email':'username'}
}
})
</script>
</html>
循环语法
- 循环数组
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<meta http-equiv='X-UA-Compatible' content='ie=edge'>
<script src='../lib/vue.js'></script>
<title>loop</title>
</head>
<body>
<div id='app'>
<table>
<thead>
<tr>
<th>Index</th>
<th>bookName</th>
<th>Author</th>
</tr>
</thead>
<tbody>
<tr v-for="book,index in books">
<td>{{index+1}}</td>
<td>{{book.title}}</td>
<td>{{book.author}}</td>
</tr>
</tbody>
</table>
</div>
</body>
<script>
new Vue({
el: '#app',
data: {
books: [
{
'title':'Book1',
'author':'1'
},
{
'title': 'book2',
'author': '2'
},
{
'title':'book3',
'author':'3'
},
{
'title': 'book4',
'author': '4'
}
]
}
})
</script>
</html>
- 循环对象
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<meta http-equiv='X-UA-Compatible' content='ie=edge'>
<script src='../lib/vue.js'></script>
<title>vue for</title>
</head>
<body>
<div id='app'>
<div v-for="(value,key) in person">
{{key}} : {{value}}
</div>
</div>
</body>
<script>
new Vue({
el: '#app',
data: {
person: {
username: "alex",
age: 18,
homepage: "http://www.baidu.com"
}
}
})
</script>
</html>
- 状态保持
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<meta http-equiv='X-UA-Compatible' content='ie=edge'>
<script src='../lib/vue.js'></script>
<title>vue-for</title>
</head>
<body>
<div id='app'>
<div v-for="book in books" :key="book.title">
<label> 标题:</label>
<input type="text" :placeholder="book.title">
</div>
<button @click="changeBookSort"> 更改图书顺序 </button>
</div>
</body>
<script>
new Vue({
el: '#app',
data: {
books: [
{
'title':'Book1',
'author':'1'
},
{
'title': 'book2',
'author': '2'
},
{
'title':'book3',
'author':'3'
},
{
'title': 'book4',
'author': '4'
}
]
},
methods: {changeBookSort() {this.books.sort(function (a,b) {return Math.random(0,1) - 0.5
})
}
}
})
</script>
</html>
小结:
- 默认情况下,如果数组中的顺序发生变化,或者个数比发生变化导致重新渲染,那么 vue 就会重新利用之前的元素,而不会重新排序,这样需要添加
key
属性,key
只能支持 number 和 string 类型 - 在 vue2.2+,key 是必须的
视图更新
针对数组中使用函数进行更新,有一下的方法直接触发更新push/pop/sort/splice/concat/reverse/shift/unshift
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<meta http-equiv='X-UA-Compatible' content='ie=edge'>
<script src='../lib/vue.js'></script>
<title>View Update</title>
</head>
<body>
<div id='app'>
<ul>
<li v-for="role in roles" :key="role">
{{role}}
</li>
</ul>
<button @click="update"> 更新 </button>
<button @click="update2"> 更新 2 </button>
<button @click="popRole"> 删除最后一个元素 </button>
<button @click='shiftRole'> 删除第一个元素 </button>
<button @click='unshiftRole'> 在第一个位置添加元素 </button>
<button @click='spliceTwo'> 删除前两个元素 </button>
<button @click="spliceChange"> 替换前三个元素中的 aaa 为 XXXX</button>
<button @click="spliceAdd"> 在第一个之前添加元素 </button>
<button @click=concatRole> 合并数组 </button>
</div>
</body>
<script>
new Vue({
el: '#app',
data: {roles: ['aaa','bbb','ccc']
},
methods: {
// 直接赋值更新
// 通过函数更新
update() {this.roles = ['ddd']
},
update2() {this.roles.push("eee")
},
popRole() {this.roles.pop()
},
shiftRole() {this.roles.shift()
},
unshiftRole() {this.roles.unshift("AAA")
},
spliceTwo() {this.roles.splice(0,2)
},
spliceChange() {this.roles.splice(0,4,'aaa','XXXX')
},
spliceAdd() {this.roles.splice(0,0,"dsadsadsa")
},
concatRole() {this.roles = this.roles.concat(['ssss','assfa'])
}
}
})
</script>
</html>
视图更新
如果想要通过下标来更新数组中的某个值,这样是不会触发视图更新的,需要通过 Vue.set
来实现
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<meta http-equiv='X-UA-Compatible' content='ie=edge'>
<script src='../lib/vue.js'></script>
<title>updateArray</title>
</head>
<body>
<div id='app'>
<ul>
<li v-for="role in roles" :key="role">
{{role}}
</li>
</ul>
<div v-for="(value,key) in users">
{{key}}:{{value}}
</div>
<button @click='updateArray'> 更新 Array</button>
<button @click='updateObj'> 更新对象 </button>
</div>
</body>
<script>
new Vue({
el: '#app',
data: {roles:["aa","bb","cc"],
users: {"username":"BBB"}
},
methods: {updateArray() {// this.roles[0] = "dsadsadsd" 不能更新
Vue.set(this.roles,0,'dadsffdafa')
},
updateObj() {
this.users.username = "asdsfasfof",
Vue.set(this.users,'age',19)
}
}
})
</script>
</html>
正文完