vue 的官方文档(使用说明书):https://cn.vuejs.org/v2/guide/
官方给出的概念:vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。
vue 不强求程序员一次性接受并使用它的全部功能特性。
在使用了 vue 的页面中,data 数据的变化,会导致页面结构的重新渲染。示意图如下:
Chrome 浏览器在线安装 vue-devtools
FireFox 浏览器在线安装 vue-devtools
更多工具 -> 扩展程序 -> Vue.js devtools
详细信息,并勾选如下的两个选项: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>Documenttitle>
head>
<body>
<div id="app">
<p>------------ v-text ---------------p>
<p v-text="username">名字是:p>
<p v-text="gender">性别:p>
<p>------------ { { } } ---------------p>
<p>名字是:{{ username }}p>
<p>性别是:{{ gender }}p>
<p>{{ username + '~~~' }}p>
<p>{{ username + gender }}p>
<p>{{ 123 }}p>
<p>{{ true }}p>
<p>{{ 1>3 ? '成立' : '不成立' }}p>
<p>{{ username.length }}p>
<p>{{ username.split('').reverse().join('') }}p>
<p>--------------- v-html ---------------p>
<div v-text="info">div>
<div>{{info}}div>
<div v-html="info">div>
div>
<script src="./lib/vue-2.6.12.js">script>
<script>
const vm = new Vue({
el: '#app',
// 声明数据
data: {
username: '汤哥1234',
gender: '男',
info: '这是一个h3标签
'
}
})
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>Documenttitle>
head>
<body>
<div id="app">
<input type="text" :placeholder="info">
<img :src="url" alt="">
<h3 :title="txt + '~~~~'">xxxxxxxxxxxh3>
<input :type="password" placeholder="v-bind: 是属性绑定指令">
div>
<script src="./lib/vue-2.6.12.js">script>
<script>
const vm = new Vue({
el: '#app',
data: {
info: 'abcdefg',
// 图片的 url 地址
url: 'https://img0.baidu.com/it/u=3280618160,1318135601&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500',
txt: '这是h3的标题',
password: 'password'
}
})
script>
body>
html>
语法:
v-on:事件名="methods中的函数(实参)"
v-on:事件名="methods中的函数"
简写: @事件名="methods中的函数"
作用:给DOM元素绑定事件
事件对象
$event
:$event
是 vue 提供的特殊变量,用来表示原生的事件参数对象 event。$event
可以解决事件参数对象event被覆盖的问题。
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>Documenttitle>
head>
<body>
<div id="app">
<h3>count是:{{ count }}h3>
<button @click="add(2, $event)">+Nbutton>
div>
<script src="./lib/vue-2.6.12.js">script>
<script>
const vm = new Vue({
el: '#app',
data: {
count: 0
},
methods: {
// 绑定事件,必然会有事件对象 event
add (n, e) {
console.log(n, e.target);
// e.target 是事件的触发源
// 记住:e.target 是原生的 DOM 对象
e.target.style.backgroundColor = 'red'
this.count += n
// 在 add 函数中,调用 show 函数
this.show()
},
show () {
console.log('触发了 methods 中的 show 函数')
}
},
})
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>Documenttitle>
<style>
.outer {
padding: 100px 50px;
background-color: orange;
}
.inner {
padding: 50px;
background-color: cyan;
}
style>
head>
<body>
<div id="app">
<a href="https://juejin.cn/editor/drafts/7075957234605244447" @click.prevent="show">去掘金网站a>
<div class="outer" @click="handler2">
<div class="inner" @click.stop="handler1">内部的 divdiv>
div>
div>
<script src="./lib/vue-2.6.12.js">script>
<script>
const vm = new Vue({
el: '#app',
methods: {
show () {
console.log('点击了 a 链接')
},
handler1 () {
console.log('点击了内部的盒子')
},
handler2 () {
console.log('点击了外部的盒子')
}
},
})
script>
body>
html>
按键修饰符
@keyup.enter
@keyup.esc
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>Documenttitle>
head>
<body>
<div id="app">
<input type="text" @keyup.enter="submit" @keyup.esc="clear">
div>
<script src="./lib/vue-2.6.12.js">script>
<script>
const vm = new Vue({
el: '#app',
methods: {
submit (e) {
console.log('触发了 submit 函数')
console.log(e.target.value)
},
clear (e) {
console.log('触发了 esc 函数')
e.target.value = ''
}
},
})
script>
body>
html>
vue 提供了 v-model
双向数据绑定指令,用来辅助开发者在不操作 DOM 的前提下,快速获取表单的数据。
语法: v-model="vue数据变量"
作用:把标签的 value 属性 与 vue变量 双向绑定
v-model 指令的修饰符
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>Documenttitle>
head>
<body>
<div id="app">
<h3>count是:{{count}}h3>
<button @click="count += 1">+1button>
<hr>
<input type="text" :value="count" @input="getValue">
<hr>
<input type="text" v-model.number="count">
<hr>
<input type="text" v-model.lazy.trim="msg">
<hr>
div>
<script src="./lib/vue-2.6.12.js">script>
<script>
// 3. vm 实例就是 ViewModel
const vm = new Vue({
// 2. el 所指定的区域,就是 View 视图
el: '#app',
// 1. Model 数据源
data: {
count: 0,
msg: 'abc'
},
methods: {
getValue(e) {
// console.log(typeof e.target.value)
this.count = parseInt(e.target.value)
}
},
})
script>
body>
html>
条件渲染指令用来辅助开发者按需控制 DOM 的显示与隐藏。条件渲染指令有如下两个,分别是:
语法:
v-show="vue变量"
v-if="vue变量"
原理:
v-if 和 v-show 的区别
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>Documenttitle>
head>
<body>
<div id="app">
<button @click="flag = !flag">Togglebutton>
<p v-if="!flag">这是被 v-if 控制的元素p>
<p v-show="flag">这是被 v-show 控制的元素p>
div>
<script src="./lib/vue-2.6.12.js">script>
<script>
const vm = new Vue({
el: '#app',
data: {
// 如果 falg 为 true,则展示被控制的元素
// 如果 falg 为 false,则隐藏被控制的元素
flag: false
}
})
script>
body>
html>
v-else
v-else-if
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>Documenttitle>
head>
<body>
<div id="app">
<p v-if="flag">条件成立p>
<p v-else>条件不成立p>
<hr>
<h3 v-if="age>=18">成年人,可以抽烟喝酒烫头h3>
<h1 v-else>未成年,漫画 + 娃哈哈h1>
<hr>
<p v-if="score === 'A'">优秀p>
<p v-else-if="score === 'B'">良好p>
<p v-else-if="score === 'C'">一般p>
<p v-else>差p>
div>
<script src="./lib/vue-2.6.12.js">script>
<script>
const vm = new Vue({
el: '#app',
data: {
flag: true,
age: 18,
// A -> 优秀
// B -> 良好
// C -> 一般
// D -> 差
score: 'A'
}
})
script>
body>
html>
vue 提供了 v-for 列表渲染指令,用来辅助开发者基于一个数组来循环渲染一个列表结构。v-for 指令需要使
用 item in list 形式的特殊语法,其中:
v-for 中的索引
v-for 指令还支持一个可选的第二个参数,即当前项的索引。
(item, index) in list
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>Documenttitle>
<style>
table {
width: 600px;
border-collapse: collapse;
}
td,
th {
border: 1px solid #efefef;
line-height: 35px;
font-size: 12px;
text-align: center;
}
style>
head>
<body>
<div id="app">
<table>
<thead>
<tr>
<th>idth>
<th>nameth>
<th>ageth>
<th>indexth>
tr>
thead>
<tbody>
<tr v-for="(item, index) in list" :key="item.id">
<td>{{ item.id }}td>
<td>{{ item.name }}td>
<td>{{ item.age }}td>
<td>索引是:{{ index }}td>
tr>
tbody>
table>
div>
<script src="./lib/vue-2.6.12.js">script>
<script>
const vm = new Vue({
el: '#app',
data: {
// 用户的数组
list: [
{ id: 1, name: '老汤', age: 35 },
{ id: 2, name: '狗哥', age: 34 },
{ id: 3, name: '小彬彬', age: 18 },
{ id: 4, name: '杨耀', age: 20 }
]
}
})
script>
body>
html>
使用 key 维护列表的状态
key 的注意事项
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<style>
li {
list-style: none;
}
style>
<body>
<div id="app">
<div>
<input type="text" v-model="name">
<button @click="addNewUser">添加button>
div>
<ul>
<li v-for="(user, index) in userlist" :key="user.id">
<input type="checkbox" />
姓名:{{user.name}}
li>
ul>
div>
<script src="./lib/vue-2.6.12.js">script>
<script>
const vm = new Vue({
el: '#app',
data: {
// 用户列表
userlist: [
{ id: 1, name: '张三疯' },
{ id: 2, name: '桑三炮' },
{ id: 3, name: '倪大野' }
],
// 输入的用户名
name: '',
// 下一个可用的 id 值
nextId: 4
},
methods: {
// 点击了添加按钮
addNewUser () {
if (this.name === '') {
this.userlist.unshift({ id: this.nextId, name: '禽兽' })
this.name = ''
this.nextId++
} else {
this.userlist.unshift({ id: this.nextId, name: this.name })
this.name = ''
this.nextId++
}
}
},
})
script>
body>
html>
directives 节点
下声明私有自定义指令。示例代码如下:directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus()
} }
}
Vue.directive()
”进行声明,示例代码如下: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>Documenttitle>
head>
<body>
<div id="app">
<p>{{ message | capt }}p>
<p>{{ info | capt }}p>
div>
<script src="./lib/vue-2.6.12.js">script>
<script>
// 声明过滤器的语法:
// Vue.filter('过滤器的名字', 过滤器的fucntion函数)
// 过滤器的本质:就是一个 function 函数
// 过滤器的 function 函数,第一个形参,永远都是 | 前面那个值
Vue.filter('capt', function (val) {
// 注意:过滤器函数,必须 return 一个处理的结果,
// 如果没有 return 任何结果,就是一个无效的过滤器
// 1. 把 val 的首字母转为大写
const result = val.charAt(0).toUpperCase() + val.slice(1)
// 2. 把转化的结果,return 出去
return result
})
const vm = new Vue({
el: '#app',
data: {
message: 'hello vue.js',
info: 'my name is xxx'
}
})
script>
body>
html>
私有过滤器
,因为它只能在当前 vm 实例所控制的 el 区域内使用。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>Documenttitle>
head>
<body>
<div id="app">
<p>{{ message | capt }}p>
<p>{{ info | capt }}p>
<p>{{ message | test }}p>
<p>--------------p>
<p>{{ message | capt | test }}p>
div>
<hr>
<div id="app2">
<h3>{{ msg | capt }}h3>
div>
<script src="./lib/vue-2.6.12.js">script>
<script>
// 声明过滤器的语法:
// Vue.filter('过滤器的名字', 过滤器的fucntion函数)
// 过滤器的本质:就是一个 function 函数
// 过滤器的 function 函数,第一个形参,永远都是 | 前面那个值
Vue.filter('capt', function (val) {
// 注意:过滤器函数,必须 return 一个处理的结果,
// 如果没有 return 任何结果,就是一个无效的过滤器
// 1. 把 val 的首字母转为大写
const result = val.charAt(0).toUpperCase() + val.slice(1)
// 2. 把转化的结果,return 出去
return result
})
const vm = new Vue({
el: '#app',
data: {
message: 'hello vue.js',
info: 'my name is xxx'
},
// 私有过滤器节点
filters: {
// 形参中的 val 就是调用过滤器时候, | 前面那个值
test(val) {
return val + '~~'
}
}
})
const vm2 = new Vue({
el: '#app2',
data: {
msg: 'welcome xxx'
}
})
script>
body>
html>
<p>{{ message | capt | test }}p>
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>Documenttitle>
head>
<body>
<div id="app">
<p>{{ msg | maxLength(3) }}p>
<p>{{ maxLength2(msg, 5) }}p>
div>
<script src="./lib/vue-2.6.12.js">script>
<script>
Vue.filter('maxLength', function (val, endIndex = 3) {
if (val.length <= endIndex) {
return val
}
// 字符串的 slice 函数,接收俩参数:
// 开始的下标(包含)
// 结束的下标(不包含)
// slice/substr/substring
return val.slice(0, endIndex) + '...'
})
const vm = new Vue({
el: '#app',
data: {
msg: '1234567890'
},
methods: {
maxLength2(val, endIndex = 3) {
if (val.length <= endIndex) {
return val
}
// 字符串的 slice 函数,接收俩参数:
// 开始的下标(包含)
// 结束的下标(不包含)
// slice/substr/substring
return val.slice(0, endIndex) + '...'
}
},
})
script>
body>
html>
过滤器仅在 vue 2.x 和 1.x 中受支持,在 vue 3.x 的版本中剔除了过滤器相关的功能。
在企业级项目开发中:
// 侦听器
watch: {
async username (newName, oldName) {
console.log('监视到了 username 值的变化。', newName, oldName)
// 如果用户名为空,则 return,防止调用接口报错
if (newName === '') return
// 注意:如果调用某个函数,返回值是 Promise 实例,
// 则可以使用 async/await 简化 Promise 的使用。
const result = await axios.get('https://www.escook.cn/api/finduser/' + newName)
console.log(result.data)
}
}
如果想让 watch 侦听器立即被调用,则需要使用 immediate 选项
。示例代码如下:
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>Documenttitle>
head>
<body>
<div id="app">
请输入值:<input type="text" v-model="username" placeholder="请输入值">
div>
<script src="./lib/vue-2.6.12.js">script>
<script src="./lib/axios.js">script>
<script>
const vm = new Vue({
el: '#app',
data: {
username: ''
},
// 侦听器
watch: {
async username (newName, oldName) {
console.log('监视到了 username 值的变化。', newName, oldName)
// 如果用户名为空,则 return,防止调用接口报错
if (newName === '') return
// 注意:如果调用某个函数,返回值是 Promise 实例,
// 则可以使用 async/await 简化 Promise 的使用。
const result = await axios.get('https://www.escook.cn/api/finduser/' + newName)
console.log(result.data)
},
// 表示页面初次渲染好之后,就立即触发当前的 watch 侦听器
immediate: true
}
})
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>Documenttitle>
head>
<body>
<div id="app">
<input type="text" v-model="goods.title">
<button @click="updateGoods">修改 goodsbutton>
div>
<script src="./lib/vue-2.6.12.js">script>
<script>
const vm = new Vue({
el: '#app',
data: {
// 商品的信息对象
goods: {
title: '娃哈哈酸奶',
price: 3,
count: 200
}
},
watch: {
goods: {
handler: function (newVal) {
console.log(newVal)
},
// 如果监听的对象上的属性发生了变化,可以能够触发侦听器
// 深度监听
deep: true
}
},
methods: {
updateGoods () {
this.goods = {
title: '牛奶',
price: 5,
count: 100
}
}
},
})
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>Documenttitle>
head>
<body>
<div id="app">
<input type="text" v-model="goods.title">
div>
<script src="./lib/vue-2.6.12.js">script>
<script>
const vm = new Vue({
el: '#app',
data: {
// 商品的信息对象
goods: {
title: '娃哈哈酸奶',
price: 3,
count: 200
}
},
watch: {
/* 'goods.title': {
handler: function (newVal, oldVal) {
console.log(newVal, oldVal)
}
} */
// 如果在定义侦听器的时候,必须要添加 immediate 或 deep 选项,需要把侦听器定义为【对象格式】
// 否则,直接把侦听器定义为【函数格式】即可
'goods.title'(newVal, oldVal) {
console.log(newVal, oldVal)
}
}
})
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>Documenttitle>
head>
<body>
<div id="app">
<h3>count 的值是:{{ count }}h3>
<p>count * count 的值是:{{ num }}p>
<p>count * count 的值是:{{ num }}p>
<p>count * count 的值是:{{ num }}p>
div>
<script src="./lib/vue-2.6.12.js">script>
<script>
const vm = new Vue({
el: '#app',
data: {
count: 2
},
// 计算属性
computed: {
// 1. 计算属性在定义的时候,需要被定义成函数
// 4. 注意:计算属性,会缓存上一次计算的结果
// 5. 只有计算属性中依赖的数据项发生变化的时候,才会重新对计算属性求值
num() {
console.log('执行了 num 这个计算属性')
// 2. 计算属性,必须 return 一个计算的结果,否则,就是无效的计算属性
return this.count * this.count
}
}
})
script>
body>
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">
<title>Documenttitle>
<script src="./lib/vue-2.6.12.js">script>
<style>
.box {
width: 200px;
height: 200px;
border: 1px solid #ccc;
}
style>
head>
<body>
<div id="app">
<div>
<span>R:span>
<input type="text" v-model.number="r">
div>
<div>
<span>G:span>
<input type="text" v-model.number="g">
div>
<div>
<span>B:span>
<input type="text" v-model.number="b">
div>
<hr>
<div class="box" :style="{ 'background-color': rgb }">
div>
<p>{{ rgb }}p>
<button @click="show">按钮button>
div>
<script>
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
// 红色
r: 0,
// 绿色
g: 0,
// 蓝色
b: 0
},
// 计算属性
computed: {
// 1. 计算属性,在定义的时候,要定义成函数
// 注意:只要计算属性中,用到的 data 数据发生了变化,就会重新对计算属性求值
rgb() {
// 2. 必须 return 一个结果
return `rgb(${this.r}, ${this.g}, ${this.b})`
}
},
methods: {
// 点击按钮,在终端显示最新的颜色
show() {
// 在 methods 函数中,要访问计算属性的值,要通过 this.计算属性 来访问
console.log(this.rgb)
}
},
});
script>
body>
html>
vue-cli 是 npm 上的一个全局包,使用 npm install 命令,即可方便的把它安装到自己的电脑上:npm install -g @vue/cli
基于 vue-cli 快速生成工程化的 Vue 项目:vue create 项目的名称
存在的问题:
推荐的方式:选择 Manually select features
好处:在项目创建期间,能够选择并安装更多的功能
手动选择要安装的功能(1/10)
手动选择要安装的功能(2/10)
手动选择要安装的功能(3/10)
手动选择要安装的功能(4/10)
手动选择要安装的功能(5/10)
手动选择要安装的功能(6/10)
手动选择要安装的功能(7/10)
手动选择要安装的功能(8/10)
手动选择要安装的功能(9/10)
手动选择要安装的功能(10/10)
目标:能够知道 ESLint 常见的语法规则,并在实际开发中遵守这些规则
节点中。
节点中封装组件的 JavaScript 业务逻辑。