06-Vue3.0

image-20200723170734421

参考资料:

本文全部基于 vue3。

vue3插件:

  • VSCode 插件:Vue(Offical) 语法格式检查和着色

  • Chrome 插件:Vue.js devtools 7.7.7 监控组件、路由等数据流

一、vue3介绍

1.1 官网初识

Vue (发音为/vju:/,类似view)是一款用于构建用户界面的JavaScript框架。它基于标准HTML、CSS和 JavaScript构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。无论是简单还 是复杂的界面,Vue都可以胜任。

1.2 环境搭建

1.2.1 线上尝试

想要快速体验Vue,你可以直接试试演练场.

1.2.2 CDN使用
1
<script src="https://unpkg.com/vue @3/dist/vue.global.js"></script>

也可以将 js 文件下载,在使用的文件中引用。

1.2.3 Vue CLI-组件开发使用

Vue CLI是官方提供的基于Webpack的Vue工具链,它现在处于维护模式。我们建议使用Vite开始新的项目,除非你依赖特定的Webpack的特性。

1.2.4 Vite-组件开发使用

Vite是一个轻量级的、速度极快的构建工具,对Vue SFC提供第一优先级支持。作者尤雨溪(也是Vue作者)!在大多数情况下,Vite将提供更优秀的开发体验

二、vue3基础

2.1 模板语法

2.1.1 我的第一个vue应用

1
2
3
4
5
6
7
8
9
10
11
12
13
<div id="box">
{{10+20}}
{{name}}
</div>
<script>
var app = Vue.createApp({
data() {
return {
name:"jerry"
}
}
}).mount("#box")
</script>
  • 推荐使用的IDE是VSCode,配合Vue语言特性(Volar)插件。该插件提供了语法高亮、TypeScript支持,以 及模板内表达式与组件props的智能提示。

  • Volar取代了我们之前为Vue 2提供的官方VSCode扩展Veturo,如果你之前已经安装了 Vetur,请确保在 Vue 3的项目中禁用它。

2.1.2 应用背后的真相

(1) Object.defineProperty

1
2
3
4
5
6
7
8
9
10
11
12
13
var obj = {};
var obox = document.getElementById('box');

Object.defineProperty(obj,'myname',{
get: function () {
console.log('有人访问了');
return obox.innerHTML;
},
set: function (value) {
console.log('有人改变我了', value);
obox.innerHTML = value;
}
});

缺陷:无法监听数组的改变,无法监听class改变,无法监听M叩Set结构。

⑵ Proxy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var obj = {}
var obox = document.getElementById("box")
var vm = new Proxy(obj, {
get(target, key) {
console.log("get") return target[key]
},
set(target, key, value) {
console.log("set")
target[key] = value obox.innerHTML = value
}
})

/* vue3 基于 Proxy ,ES6 Proxy ,
if(支持 proxy){
proxy 行拦截处理,实现功能
}else{
object.defineProtery
}
*/

2.1.3 模板语法

(1)最基本的数据绑定形式是文本插值,它使用的是“Mustache”语法(即双大括号):

Message:

双大括号标签会被替换为相应组件实例中msg属性的值。同时每次msg属性更改时它也会同步更新。

(2)双大括号不能在HTML attributes中使用。想要响应式地绑定一个attribute,应该使用v-bmd.指令 template

v-bind指令指示Vue将元素的id attribute与组件的dynamicId属性保持一致。如果绑定的值是null或者 undefined ,那么该attribute将会从渲染的元素上移除。

(3)表达式的支持

1
2
3
4
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split(").reverse().join(") }}
<div :id=" 'list-${id}'"></div>

(4)指令

1
<a v-on:click="doSomething”> ... </a>
1
<a @click="doSomething”> ... </a>

2.1.4 案例:Todolist-添加待办

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../lib/vue.global.js"></script>
</head>

<body>
<div id="box">
<input type="text" v-model="mytext" />
<button @click="handleAdd">add</button>
<ul>
<li v-for="data,index in datalist">
{{data}}
<button @click="handleDel(index)">del</button>
</li>
</ul>
</div>
<script>
var obj = {
data() {
return {
mytext: "",
datalist: ["11", "22", "33"],
}
},
methods: {
handleAdd(ev) {
this.datalist.push(this.mytext)
this.mytext = ""
},
handleDel(index) {
this.datalist.splice(index, 1)
}
}
}
var app = Vue.createApp(obj).mount("#box")
</script>
</body>

</html>

2.1.5 案例:点击变色

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<!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>
<script src="../lib/vue.global.js"></script>
<style>
.active {
background-color: red;
}
</style>
</head>

<body>
<div id="box">
<ul>
<li v-for="(data, index) in datalist" @click="handleclick(index)" :class="current === index? 'active' : ''">
{{data}}
</li>
</ul>
</div>
<script>
var obj = {
data() {
return {
datalist: ["11", "22", "33"],
current: null
};
},
methods: {
handleclick(index) {
this.current = index;
}
}
};
var app = Vue.createApp(obj).mount("#box");
</script>
</body>

</html>

2.1.6 v-html 模板陷阱

双大括号会将数据解释为纯文本,而不是HTML。若想插入HTML,你需要使用v-html指令

1
2
<p>Using text interpolation: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>

[!WARNING]

安全警告:
在网站上动态渲染任意HTML是非常危险的,因为这非常容易造成XSS漏洞。
请仅在内容安全可信时再使用v-html, 并且永远不要使用用户提供的HTML内容。

2.2 class | style

2.2.1 class的绑定

对象写法

1
2
3
4
5
6
7
8
9
data() {
return {
classObject: {
active: true,
'text-danger': false
}
}
}
<div :class="classObject"></div>

数组写法

1
2
3
4
5
6
7
data() {
return {
activeClass: 'active',
errorClass: 'text-danger'
}
}
<div :class="[activeClass, errorClass]"></div>

2.2.2 style的绑定

对象写法

1
2
3
4
5
6
7
8
9
data() { 
return {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
}
<div :style="styleObject"></div>

数组写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
data() {
return {
arr: [
{
width: "200px",
height: "200px",
backgroundSize: "cover"
}
]
};
}
// 如果要在某个方法中执行push操作,以下是一个示例方法
methods: {
someMethod() {
this.arr.push({
backgroundImage: "url(https://pic.maizuo.com/usr/movie/862ab6736237acd11599e5eecbbc83d7.jpg)"
});
}
}

2.3 v-if 条件渲染

条件渲染-生或死的选择

v-if是“真实的”按条件渲染,因为它确保了在切换时,条件区块内的事件监听器和子组件都会被销毁与重建。
v-if也是惰性的:如果在初次渲染时条件值为false,则不会做任何事。条件区块只有当条件首次变为true时才被 渲染。

相比之下,v-show简单许多,元素无论初始条件如何,始终会被渲染,只有CSS display属性会被切换。

总的来说,v-if有更高的切换开销,而v-show有更高的初始渲染开销。因此,如果需要频繁切换,则使用v- show较好;如果在运行时绑定条件很少改变,则v-if会更合适。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<ul>
<li v-for="(item, index) in datalist">
{{item.title}}
<div v-if="item.state === 0">未付款</div>
<div v-else-if="item.state === 1">未发货</div>
<div v-else-if="item.state === 2">已发货</div>
<div v-else>已完成</div>
</li>
</ul>
<script>
var app = new Vue({
el: 'body',
data: {
datalist: [
{
state: 0,
title: "111"
},
{
state: 1,
title: "222"
},
{
state: 2,
title: "333"
}
]
}
});
</script>

2.4 列表渲染

2.4.1 v-for列表渲染

v-for与对象

1
2
3
4
5
6
7
8
9
data() {
return {
myObject: {
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt: '2016 - 04 - 10'
}
};
}
1
2
3
4
5
<ul>
<li v-for="value in myObject">
{{ value }}
</li>
</ul>

v-for与v-if

v-for与v-if一般不可以用于同一个li标签上,可以用加个template 标签错开,template 标签也不会改变原有的dom结构。

1
2
3
4
5
6
7
8
<ul>
<!-- {title,state} 结构赋值 -->
<template v-for="({title,state},index) in datalist">
<li v-if="state===1">
{{title}}-{{state}}
</li>
</template>
</ul>

2.4.2 key设置 - 性能的保障

Vue默认按照“就地更新”的策略来更新通过v-for渲染的元素列表。当数据项的顺序改变时,Vue不会随之移动 DOM元素的顺序,而是就地更新每个元素,确保它们在原本指定的索引位置上渲染。

为了给Vue 一个提示,以便它可以跟踪每个节点的标识,从而重用和重新排序现有的元素,你需要为每个元素对应的块提供一个唯一的 key

1
2
3
<div v-for="item in items" :key="item.id">
<!--内容-->
</div>

虚拟dom

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
type: 'div',
props: {
id: 'container'
},
children: [
{
type: 'span',
props: {
class: 'textl'
},
children: 'hello '
},
{
type: 'span',
props: {
class: 'text2'
},
children: 'jerry'
}
]
}

真实dom

1
2
3
4
<div id="container">
<span class="text1">hello</span>
<span class="text2">jerry</span>
</div>

2.4.3 数组变动侦测

Vue能够侦听响应式数组的变更方法,并在它们被调用时触发相关的更新。这些变更方法包括:

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

对于一些不可变(immutable)方法,例如 filter()concat()slice() 这些都不会更改原数组,而总是返回一个新数组。当遇到的是非变更方法时,我们需要将旧的数组替换为新的:

1
this.items = this.items.filter((item) => item.message.match(/Foo/))

match是字符串的一个方法,用于在字符串中查找匹配指定正则表达式的部分。

2.4.4 模糊搜索案例

为了解决数据回删后,原列表数据正常展示,有如下几种方案:

方案1 - 函数表达式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<div id="box">
<input type="text" v-model="mytext" />
<ul>
<li v-for="data in filterList()" :key="data">
{{data}}
</li>
</ul>
</div>
<script>
var obj = {
data() {
return {
mytext: "",
datalist: ["aaa", "abb", "aab", "bcc", "abc", "bcd", "add", "acd"]
};
},
methods: {
filterList(evt) {
return this.datalist.filter(item => item.includes(this.mytext));
}
}
};
Vue.createApp(obj).mount("#box");
</script>
方案2 - 复制方案
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<div id="box">
<input type="text" v-model="mytext" @input="handleInput" />
<ul>
<li v-for="data in datalist" :key="data">
{{data}}
</li>
</ul>
</div>
<script>
var obj = {
data() {
return {
mytext: "",
datalist: ["aaa", "abb", "aab", "bcc", "abc", "bcd", "add", "acd"],
oldlist: ["aaa", "abb", "aab", "bcc", "abc", "bcd", "add", "acd"]
};
},
methods: {
handleInput() {
this.datalist = this.oldlist.filter(item => item.includes(this.mytext));
}
}
};
Vue.createApp(obj).mount("#box");
</script>
方案3 - watch监听
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<div id="box">
<input type="text" v-model="mytext" placeholder="请输入关键词搜索" />
<ul>
<!-- 直接循环过滤后的响应式数据,不再调用方法 -->
<li v-for="data in filteredList" :key="data">
{{data}}
</li>
</ul>
</div>

<script>
var obj = {
data() {
return {
mytext: "",
datalist: ["aaa", "abb", "aab", "bcc", "abc", "bcd", "add", "acd"],
// 新增:存储过滤后的结果(响应式数据)
filteredList: []
};
},
// 初始化:页面加载时先执行一次过滤,显示全部数据
created() {
this.filterData();
},
watch: {
// 监听mytext的变化,触发过滤逻辑
mytext: {
// 监听的处理函数
handler(newVal) {
this.filterData(newVal);
},
// 可选:immediate为true时,watch初始化时会执行一次handler(替代created中的调用也可以)
immediate: true
}
},
methods: {
// 抽离过滤逻辑为独立方法
filterData(keyword = this.mytext) {
this.filteredList = this.datalist.filter(item => item.includes(keyword));
}
}
};
Vue.createApp(obj).mount("#box");
</script>
方案4 - 计算属性【推荐】
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<div id="box">
<input type="text" v-model="mytext" placeholder="请输入关键词搜索" />
<ul>
<li v-for="data in filteredList" :key="data">
{{data}}
</li>
</ul>
</div>

<script>
var obj = {
data() {
return {
mytext: "",
datalist: ["aaa", "abb", "aab", "bcc", "abc", "bcd", "add", "acd"]
};
},
computed: {
filteredList() {
return this.datalist.filter(item => item.includes(this.mytext));
}
}
};
Vue.createApp(obj).mount("#box");
</script>

2.5 事件处理器

2.5.1 事件处理器

内联事件处理器

1
2
3
<button @click="count++">Add</button>
<button @click="count--">Delete</button>
<button @click="test('hello')">test hello</button>

方法事件处理器:$event 参数拿到点击的dom对象,或 匿名函数传参evt

1
2
3
<button @click="test">test</button>
<button @click="handleClick1(1, 2, 3, $event)">click1</button>
<button @click="(evt) => handleClick2(1, 2, 3, evt)">click2</button>

2.5.2 事件修饰符

Vue为v-on提供了事件修饰符。修饰符是用 . 表示的指令后缀,包含以下这些:

  • .stop (阻止事件冒泡到父标签,如点击li触发了ul的click事件)
  • .prevent (阻止默认事件,如submit按钮的提交事件可以阻止,用于提交前的校验)
  • .self (只触发自身的事件,如ul中的li会冒泡到ul时,ul添加.self就不会被触发冒泡)
  • .capture (在事件的捕获阶段触发父级元素的事件。)
  • .once (只触发一次就不再触发,除非刷新页面)
  • .passive (一般用于触摸事件的监听器,可以用来改善移动端设备的滚屏性能)

[!WARNING]

请勿同时使用.passive和.prevent ,因为.passive已经向浏览器表明了你不想阻止事件的默认行为。
如果你这么做了,则.prevent会被忽略,并且浏览器会抛出警告。

使用示例:<li @click.stop="handleClick">click<li>

组合使用示例:<li @click.stop.prevent="handleClick">click<li>

2.5.3 按键修饰符

Vue 为一些常用的按键提供了别名:(eg: @keyup.enter="func")

  • .enter
  • .tab
  • .delete (捕获“Delete”和“Backspace”两个按键)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

使用示例:<input type="text" v-model="inputText" @keyup.enter="handleKeyupEnter">

2.6 表单控件绑定

2.6.1 v-model 双向绑定

v-model 双向绑定原理:

1
<input type="text" v-model="mytext">

等价于动态绑定input标签的value值,然后监听input事件实时赋值给动态绑定的变量

1
2
3
4
5
6
7
8
<input type="text" :value="mytext" @input="mytext=$event.target.value">
<script>
export default {
data() {
return { mytext:'' }
}
}
</script>

普通文本 text

1
<input type="text" v-model="message" placeholder="请输入" />

复选框 checkbox

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//checked为数组[],存储每一项选择的value值
<div id="box">
你最喜欢的运动:{{checked}}
<div>
<input type="checkbox" v-model="checked" value="足球" />足球
<input type="checkbox" v-model="checked" value="篮球" />篮球
<input type="checkbox" v-model="checked" value="乒乓球" />乒乓球
</div>
</div>
<script>
var obj={
data(){
return{
checked:[]
}
}
}
Vue.createApp(obj).mount("#box");
</script>

单选框 radio

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//picked为字符串"",存储选择的某一个value值
<div id="box">
你最喜欢的运动:{{picked }}
<div>
<input type="radio" v-model="picked " value="足球" />足球
<input type="radio" v-model="picked " value="篮球" />篮球
<input type="radio" v-model="picked " value="乒乓球" />乒乓球
</div>

</div>
<script>
var obj={
data(){
return{
picked :""
}
}
}
Vue.createApp(obj).mount("#box");
</script>

选择器 select

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//<div>Selected: {{ selected }}</div>  //选择会显示对应的“全部订单”、“已取消”、“未付款”、“已付款”
//<select v-model="selected">
// <option>全部订单</option>
// <option>已取消</option>
// <option>未付款</option>
// <option>已付款</option>
//</select>

//selected为字符串"",选择会显示对应的单个选择"all"、"0"、"1"、"2" (如果是数字,value使用动态绑定 :value="0")
<div>Selected: {{ selected }}</div>
<select v-model="selected">
<option value="all">全部订单</option>
<option value="0">已取消</option>
<option value="1">未付款</option>
<option value="2">已付款</option>
</select>

<script>
var obj={
data(){
return{
selected:"" //默认值设置为空,或设置"all"就会默认选项“全部订单”
}
}
}
Vue.createApp(obj).mount("#box");
</script>

2.6.2 案例:购物车

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
<!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>
<script src="../lib/vue.global.js"></script>
<style>
li {
display: flex;
justify-content: space-between;
padding: 10px;
border: 1px solid lightgray;
align-items: center;
}

li img {
width: 100px;
}
</style>
</head>

<body>
<div id="box">
<ul>
<li>
<div>
<input type="checkbox" v-model="isAllChecked" @change="handleChange" />
<span>全选/全不选</span>
</div>
</li>
<template v-if="datalist.length">
<li v-for="(data, index) in datalist" :key="data.id">
<div>
<input type="checkbox" v-model="checkList" :value="data" @change="handleItemChange" />
</div>
<div>
<img :src="data.poster" alt="">
</div>
<div>
<div>{{data.title}}</div>
<div style="color: red;">{{data.price}}</div>
</div>
<div>
<button @click="data.number--" :disabled="data.number === 1">-</button>
{{data.number}}
<button @click="data.number++" :disabled="data.number === data.limit">+</button>
</div>
<div>
<button @click="handleDel(index, data.id)">delete</button>
</div>
</li>
</template>
<li v-else>购物车空空如也</li>
<li>
<div>金额:{{sum()}}</div>
</li>
</ul>
</div>
<script>
var obj = {
data() {
return {
isAllChecked: false,
checkList: [],
datalist: [
{
id: 1,
title: "商品1",
price: 10,
number: 1,
poster: "https://p0.meituan.net/movie/dc2fed6001e809e4553f90cc6fad9a59245170.jpg",
limit: 5
},
{
id: 2,
title: "商品2",
price: 20,
number: 2,
poster: "https://p0.meituan.net/moviemachine/3084e88f63eef2c6a0df576153a3fad0327782.jpg",
limit: 5
},
{
id: 3,
title: "商品3",
price: 30,
number: 3,
poster: "https://p0.meituan.net/movie/897b8364755949226995144bfc2261ee4493381.jpg",
limit: 5
}
]
};
},
methods: {
sum() {
return this.checkList.reduce((total, item) => total + item.price * item.number, 0);
},
handleDel(index, id) {
this.datalist.splice(index, 1);
this.checkList = this.checkList.filter(item => item.id !== id);
this.handleItemChange();
},
handleChange() {
this.checkList = this.isAllChecked ? this.datalist : [];
},
handleItemChange() {
if (this.datalist.length === 0) {
this.isAllChecked = false;
return;
}
this.isAllChecked = this.datalist.length === this.checkList.length;
}
}
};
var app = Vue.createApp(obj).mount("#box");
</script>
</body>

</html>

2.6.3 表单修饰符

.lazy

1
2
<!--在"change"事件后同步更新而不是"input",失去焦点才更新数据-->
<input v-model.lazy="msg" />

.number

用户输入自动转换为数字,你可以在v-model后忝加 .number修饰符来管理输入:

1
<input v-model.number="age" />

number修饰符会在输入框有type=”number”时自动启用。

.trim

默认自动去除用户输入内容中两端的空格,你可以在v-model后添加.trim修饰符:

1
<input v-model.trim="msg" />

2.7 计算属性

2.7.1 计算属性 - 会缓存

模板中的表达式虽然方便,但也只能用来做简单的操作。如果在模板中写太多逻辑,会让模板变得臃肿,难以维 护。因此我们推荐使用计算属性来描述依赖响应式状态的复杂逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{{ publishedBooksMessage }}
<script>
var obj = {
data() {
return {
author: {
name: 'John Doe',
books: [
'Vue 2 - Advanced Guide',
'Vue 3 - Basic Guide',
'Vue 4 - The Mystery'
]
}
}
},
computed: {
// 一个计算属性的getter
publishedBooksMessage() {
// 'this'指向当前组件实例
return this.author.books.length > 0 ? 'Yes' : 'No'
}
}
}
</script>

若我们将同样的函数定义为一个方法而不是计算属性,两种方式在结果上确实是完全相同的,然而,不同之处在于 计算属性值会基于其响应式依赖被缓存 。一个计算属性仅会在其响应式依赖更新时才重新计算。

2.7.2 案例小改造

1
2
3
4
5
6
7
8
9
10
computed:{
isAllChecked:{
get(){
return this.datalist.length===this.checkList.length
},
set(checked){
this.checkList = checked?this.datalist:[]
}
}
}

注意:

(1)Getter 不应有副作用

计算属性的 getter 应只做计算而没有任何其他的副作用,这一点非常重要,请务必牢记。举例来说,不要在 getter 中做异步请求或者更改 DOM!

(2)避免直接修改计算属性值

从计算属性返回的值是派生状态。可以把它看作是一个“临时快照”,每当源状态发生变化时,就会创建一个新的快 照。更改快照是没有意义的,因此计算属性的返回值应该被视为只读的,并且永远不应该被更改——应该更新它所 依赖的源状态以触发新的计算。

2.7.3 侦听器watch的对比

watch选项期望接受一个对象,其中键是需要侦听的响应式组件实例属性(例如,通过data或computed声明的 属性)一一值是相应的回调函数。该回调函数接受被侦听源的新值和旧值。支持异步

  • deep:true 复杂对象的深度监听
  • immediate: true 立即的,第一次就立即触发一次,比如展示默认数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
watch: {
// 侦听根级属性
a(val, oldVal) {
console.log(`new: ${val}, old: ${oldVal}`);
},
// 字符串方法名称
b:'someMethod',
// 该回调将会在被侦听的对象的属性改变时调动,无论其被嵌套多深
c: {
handler(val, oldVal) {
console.log('c changed');
},
deep: true //复杂对象进行深度监听
},
// 侦听单个嵌套属性:
'c.d': function (val, oldVal) {
// do something
},
// 该回调将会在侦听开始之后立即调用
e: {
handler(val, oldVal) {
console.log('e changed');
},
immediate: true
}
}

2.8 数据请求

2.8.1 fetch

XMLHttpRequest API,酒和调用闻E髓乱,而且基于事件的异步模型写起来不友好。

兼容性不好 polyfill: https://github.com/camsong/fetch-ie8

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// 发送GET请求获取用户数据
fetch("http://localhost:3000/users")
.then(res => res.json())
.then(res => {
console.log(res);
});

// 发送POST请求创建新用户
fetch("http://localhost:3000/users", {
method: "POST",
headers: {
"content-type": "application/json"
},
body: JSON.stringify({ username: "jerry", password: "123" })
})
.then(res => res.json())
.then(res => {
console.log(res);
});

// 发送PUT请求更新用户数据
fetch("http://localhost:3000/users/5", {
method: "PUT",
headers: {
"content-type": "application/json"
},
body: JSON.stringify({ username: "jerry", password: "456" })
})
.then(res => res.json())
.then(res => {
console.log(res);
});

// 发送DELETE请求删除用户数据
fetch("http://localhost:3000/users/5", {
method: "DELETE"
})
.then(res => res.json())
.then(res => {
console.log(res);
});

2.8.2 axios

Axios是一个基于promise的HTTP库,可以用在浏览器和node.js中。 https://www.npmjs.com/package/axios

1
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>

1.get请求

1
2
3
4
5
6
7
axios.get("http://localhost:3000/users",{
params:{
name:"jerry"
}
}).then(res=>{
console.log(res.data)
})

2.post请求

1
2
3
4
5
6
axios.post("http://localhost:3000/users",{ 
name:"jerry",
age:100
}).then(res=>{
console.log(res.data)
})

3.put请求

1
2
3
4
5
6
axios.put("http://localhost:3000/users/12",{ 
name:"jerry111",
age:200
}).then(res=>{
console.log(res.data)
})

4.delete请求

1
2
axios.delete("http://localhost:3000/users/11")
.then(res=>{ console.log(res.data)})

5.axios(config)配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
axios({
method: 'post',
url: 'http://localhost:3000/users',
data: {
name: 'jerry',
age: 100
}
})
.then(res => {
console.log(res.data);
})
.catch(err => {
console.log(err);
});

9.过滤器 - 废弃(×)

在 2.x 中,开发者可以使用过滤器来处理通用文本格式。

1
2
3
4
5
6
<p>{{ accountBalance | currencyUSD }}</p>
filters: {
currencyUSD(value) {
return '$' + value
}
}

虽然这看起来很方便,但它需要一个自定义语法,打破了大括号内的表达式“只是JavaScript”的假设,这不仅有学习成本,而且有实现成本。

在 3.x 中,过滤器已移除,且不再支持。取而代之的是,我们建议用方法调用计算属性来替换它们。


06-Vue3.0
https://janycode.github.io/2022/05/22/04_大前端/04_Vue/06-Vue3.0/
作者
Jerry(姜源)
发布于
2022年5月22日
许可协议