文章目录
- 一、创建Vue3工程
-
- [1. vue-cli方式](#1. vue-cli方式)
- [2. vite方式](#2. vite方式)
- [3. 项目小说明](#3. 项目小说明)
- [4. 安装插件:](#4. 安装插件:)
-
- [(1) Prettier--整理格式](#(1) Prettier--整理格式)
- [(2) Vue-official](#(2) Vue-official)
- [二、 OptionsAPI 与 CompositionAPI](#二、 OptionsAPI 与 CompositionAPI)
-
- [1 选项式API的弊端](#1 选项式API的弊端)
- [2 组合式API的优势](#2 组合式API的优势)
- 三、setup
-
- [1. 基本使用](#1. 基本使用)
- [2 setup与组合式API](#2 setup与组合式API)
- [3 setup语法糖](#3 setup语法糖)
- 四、Vue中的响应式
-
- [1. ref创建基本类型的响应式数据](#1. ref创建基本类型的响应式数据)
- [2. reactive创建对象类型的响应式数据](#2. reactive创建对象类型的响应式数据)
- [3. ref创建对象类型的响应式数据](#3. ref创建对象类型的响应式数据)
- [4. toRef和toRefs](#4. toRef和toRefs)
- [5. ref与reactive对比](#5. ref与reactive对比)
一、创建Vue3工程
1. vue-cli方式
备注:目前
vue-cli
已处于维护模式,官方推荐基于Vite
创建项目。
powershell
## 查看@vue/cli版本,确保@vue/cli版本在4.5.0以上
vue --version
## 安装或者升级你的@vue/cli
npm install -g @vue/cli
## 执行创建命令
vue create vue_test
## 随后选择3.x
## Choose a version of Vue.js that you want to start the project with (Use arrow keys)
## > 3.x
## 2.x
## 启动
cd vue_test
npm run serve
2. vite方式
vite官网中文:Vite;Vite 是新一代前端构建工具,优势如下:
- 轻量快速的热重载(
HMR
),能实现极速的服务启动。 - 对
TypeScript
、JSX
、CSS
等支持开箱即用。 - 真正的按需编译,不再等待整个应用编译完成。
Vue3
向下兼容Vue2
语法,且Vue3
中的模板中可以没有根标签
3. 项目小说明
项目的入口文件是index.html
加载index.html
后,Vite 解析 <script type="module" src="/src/main.ts">
指向的文件。
4. 安装插件:
(1) Prettier--整理格式
setting.json
文件里,改成红色那一行(我是改这一行就好了)
(2) Vue-official
官方推荐安装,先安装吧,后续写代码会有帮助。到时候会记录
二、 OptionsAPI 与 CompositionAPI
- vue2中的API设计是
Options
风格的(选项式或配置式) - vue3中的API设计是
Composition
风格的(组合式)
1 选项式API的弊端
选项式的API:数据、方法、计算属性等,是分散在:data
、methods
、computed
中的,若想新增或者修改一个需求,就需要分别修改:data
、methods
、computed
,不便于维护和复用。(学习vue2其实主要就是在学一个一个的配置项data
,methods
)
2 组合式API的优势
可以用函数的方式,更加优雅的组织代码,让相关功能的代码更加有序的组织在一起。
说明:以上两张动图原创作者:大帅老猿
三、setup
1. 基本使用
现有这样一个页面:
在vue2中,使用的是配置项的方式:
javascript
// 数据
data() {
return {
nickName: "tom",
};
},
// 方法
methods: {
changeName() {
this.nickName = "Tom";
},
}
vue3中使用setup函数
javascript
setup() {
// 数据,对应到vue2中是应该写在data配置项中;
// 此时的hobby,age都不是响应式的数据
let hobby = "sing";
let age = 18;
// 方法,对应到vue2中是应该写在methods配置项中,
function changeHobby() {
hobby = "dance"; // 注意:这样修改name页面没有变化
console.log(hobby); // hobby的值确实改了,但不是响应式的
}
function changeAge() {
age = age + 1;
}
// console.log(this); // undefined,vue3中已经弱化了this
return { h: hobby, age, changeHobby, changeAge };
},
setup特点:
- setup函数里的
this
值是undefined
- setup函数中的数据不是响应式的。数据值改了,但是页面不会更新
- setup执行的时机比vue2中的beforeCreate钩子函数还要早
- 页面结构中若要用到setup里的数据,需要setup函数
return
返回。-
若返回一个对象 :则对象中的:属性、方法等,在模板中均可以直接使用。
-
若返回一个函数 :则可以自定义渲染内容
javascriptsetup(){ return ()=>'哈哈' // 页面上直接渲染 '哈哈'两个字 }
-
2 setup与组合式API
- Vue2的配置(
data
、methos
...)中可以访问到setup
中的属性、方法。 - 但在
setup
中不能访问到 Vue2的配置(data
、methos
...)。 - 如果与
Vue2
冲突,则setup
优先。
3 setup语法糖
在script
标签里标注setup
后,就不用再写setup
函数,return
;
html
<!-- 数据、方法 -->
<script setup lang='ts'>
let age = 18;
let h = "sing";
function changeHobby() {
h = "dance";
}
function changeAge() {
age = age + 1;
}
</script>
此时无法指定组件名称,组件名称(Person
)默认为文件名Person.vue
;语法糖模式下指定组件名有两种方式:
方式一 :需要再编写一个不写setup
的script
标签,去指定组件名字
html
<!-- 这个主要用来定义组件名称 -->
<script lang='ts'>
export default {
name: "Person",
};
</script>
<!-- 数据、方法 -->
<script setup lang='ts'>
...
</script>
方式二 :安装插件
(1)安装:npm i vite-plugin-vue-setup-extend -D
(2)配置: vite.config.ts
(3) 使用:<script setup lang='ts' name="Person">
拓展:使用第二种方式,App引入Person组件时报错
这是插件的问题,卸载vetur
插件即可,vue2.x使用vetur
插件,vue3.x更换成Vue-Official
插件可更好的支持TS
四、Vue中的响应式
1. ref创建基本类型的响应式数据
- 语法:
let xxx = ref(初始值)
。 - 返回值:一个
RefImpl
的实例对象,简称ref对象
或ref
,ref
对象的value
属性是响应式的。 - 注意点:
JS
中操作数据需要:xxx.value
,但模板中不需要.value
,直接使用即可。- 对于
let age = ref(18);
来说,age
不是响应式的,age.value
是响应式的。
html
<div>
<h1>爱好:{{ hobby }}</h1>
<!--无需.value-->
<h1>年龄:{{ age }}</h1>
<button @click="changeAge">点击改变年龄</button>
</div>
<script setup lang='ts' name="Person">
// 1. 引入ref
import {ref} from 'vue'
// 2. 谁需要变成响应式数据,ref就包裹谁
let age = ref(18);
let hobby = "sing";
function changeAge() {
age.value = age.value + 1;
};
console.log(age);
console.log(hobby);
</script>
可以看出hobby
还是那个hobby
,而age
已经变成一个RefImpl
的实例对象了。
2. reactive创建对象类型的响应式数据
- 作用:定义一个响应式对象 (基本类型不要用它,要用
ref
,否则报错) - 语法:
let 响应式对象= reactive(源对象)
。 - 返回值:一个
Proxy
的实例对象(响应式对象)。
html
<template>
<div>
<h1>一辆{{ car.brand }}车,价值{{ car.price }}w元</h1>
<button @click="changePrice">修改汽车价格</button>
</div>
</template>
<script setup lang='ts' name="Person">
// 1. 引入reactive
import {reactive} from 'vue'
// 2. 使用
let car = reactive({brand:'奔驰',price:20})
let games = reactive([{id:1,name:'超级玛丽'},{id:2,name:'狼人杀'}])
function changePrice() {
car.price ++;
};
console.log(car);
console.log(games);
</script>
操作对象的响应式数据时,不用.vlaue了
-
注意点:
reactive
定义的响应式数据是深层次的。html<template> <div> <h1>{{ obj.a.b.c }}</h1> <button @click="changeC">修改C</button> </div> </template> <script setup lang='ts' name="Person"> import {reactive} from 'vue' let obj = reactive({ a: { b:{ c:10 } } }) function changeC(){ obj.a.b.c = 80 } </script>
3. ref创建对象类型的响应式数据
ref
接收的数据可以是:基本类型、对象类型。- 若
ref
接收的是对象类型,内部其实也是调用了reactive
函数。
javascript
import {reactive,ref} from 'vue'
let car = ref({brand:'奔驰',price:20})
let obj = reactive({a:100})
console.log(car);
console.log(obj);
4. toRef和toRefs
将响应式对象解构之后获得的变量,就不是响应式的了
javascript
let person = reactive({
name: "tom",
age: 18,
})
// name,age不再是响应式数据,其值变化时,页面不更新
let { name, age } = person
// 上述解构赋值等价于
let name = person.name
let age = person.age
toRef
和toRefs
将一个响应式对象中的每一个属性,转换为ref
对象。
toRefs
与toRef
功能一致,但toRefs
可以批量转换。
javascript
import { reactive, toRefs, toRef } from "vue"
let { name, age } = toRefs(person)
console.log(toRefs(person))
console.log("name:", name)
console.log("age:", age)
let n1 = toRef(person.age)
console.log("n1:", n1)
5. ref与reactive对比
-
ref
用来定义:基本类型数据 、对象类型数据 ;
reactive
用来定义:对象类型数据。 -
注意点:
(1)
ref
创建的变量必须使用.value
。安装插件(vue-official)可提示程序员该不该写
value
,安装好之后打开Settings
设置后不起作用就重启vscode。在点
.
的时候,会提示写value
(2)
reactive
重新分配一个新对象,会失去 响应式(可以使用Object.assign
去整体替换)。javascriptimport { reactive } from "vue" let car = reactive({ brand: "奔驰", price: 20 }) function chageCar() { // car = { brand: "雅迪", price: 1 } // 这样写页面不更新 // car = reactive({ brand: "雅迪", price: 1 }) 这样写页面也不更新 // 以上两种方式 car都已经是一个新对象了,不是响应式对象 // 采用 Object.assign 可仍保持其为响应式 Object.assign(car, { brand: "雅迪", price: 1 }) }
-
使用原则:
(1) 若需要一个基本类型的响应式数据,必须使用
ref
。(2) 若需要一个响应式对象,层级不深,
ref
、reactive
都可以。(3) 若需要一个响应式对象,且层级较深,推荐使用
reactive
。
总结响应式对象的赋值
ref
:
javascript
let person = ref({
name: "tom",
age: 18,
})
// 对象的地址值发生变化,但是仍旧为响应式
person.value = { name: "李四", age: 50 }
reactive
:
javascript
let car = reactive({ brand: "奔驰", price: 20 })
car = { brand: "雅迪", price: 1 } // car为新对象,这样写页面不更新
car = reactive({ brand: "雅迪", price: 1 }) // car为新对象,这样写页面也不更新
// 响应式方法1:修改car整体,但是car地址不变
Object.assign(car, { brand: "雅迪", price: 1 })