一、vue3简介
1.性能的提升
打包大小减少41%
初次渲染快55%, 更新渲染快133%
内存减少54%
2.源码的升级
使用Proxy代替defineProperty实现响应式
重写虚拟DOM的实现和Tree-Shaking
3.拥抱TypeScript
Vue3可以更好的支持TypeScript
4.新的特性
Composition API(组合API)
setup配置
ref与reactive
watch与watchEffect
provide与inject
新的内置组件
Fragment
Teleport
Suspense
其他改变
新的生命周期钩子
data 选项应始终被声明为一个函数
移除keyCode支持作为 v-on 的修饰符
5 组合式API和配置项API
-使用组合式API
-配置项API
-{
name:'xx',
data:function(){},
methods:{}
}
二、创建vue3的两种方式
# 打开终端输入命令
# vue-cli:创建vue2和vue3
-跟之前一样
# vite:创建vue3,创建最新
npm init vue@latest
# 根据自己的需要选择是否要下载依赖
# Pinai 这个就相当于是vuex
# vite创建另一种方式:创建vue3.0.4版本
npm init vite-app <project-name>
## 进入工程目录
cd <project-name>
## 安装依赖
npm install
## 运行
npm run dev
# 以后在页面中的this,已经不是vue2中的vc对象了,是一个代理对象
三、setup函数
# 向之前vue2编写变量和函数的时候是在data和methods中编写
eg:
export default {
data(){
name:'jason'
},
methods:{
handleClick(){
alert('弹出')
}}} # 这是vue2的写法 像这种写法 叫做配置项api
# 在vue3中也是能够支持这样写的 但是vue3推荐写在setup函数中 就是把定义变量和写函数都下载setup中
eg:
export default {setup(){
let name = 'jason'
let age = 19
function handleClick(){
alert('弹出')
return {name, age, handleClick} # 这些变量都必须返回出去 这样页面才可以使用
}}}
3.1 代码演示
<template>
<h2>{{ name }}</h2>
<h3>{{ age }}</h3>
</template>
<script>
export default {
name: 'App',
setup() { // setup中没有this了
let age = 19
let name = 'lqz'
// 函数必须有返回值
return {
age, name // 只要返回了 页面上直接使用插值语法即可
}
}
}
</script>
四、ref和reactive
'''
使用了setup函数的话 那么setup就没有了响应式布局了
之前vue2只要定义了变量 那么就可以使用响应式布局
修改变量 页面上的数据也会跟着改变
现在vue3是没有了响应式布局了 如果想把变量变成响应式布局
那么需要关键字帮助才可以 就是自己可以决定了哪些变量可以响应式'''
4.1 ref
<!--基本数据类型 数字,字符串,布尔值 如果想让这些数据类型加响应式, 那么需要ref包裹
然后js通过对象.value取值修改-->
<script>
import {ref, reactive} from 'vue' // 先导入
export default {
let age = ref(19) // age 已经不是数字了,是RefImpl的对象 RefImpl中有value
let name = ref('lqz')
}
let handleAdd = () => {
console.log('我要开始加了,age是', age) // 通过点击事件 把age加1
age.value = age.value + 1 // 但是需要通过 age.value才能够取到值
}
return {
age, name, handleAdd // 这样通过ref就可以使用响应式布局 这样变量修改 页面就会实时变化
}
</script>
4.2 reactive
<!--# 对象,数组引用使用reactive, js直接点值就可以取到值
ref也可以包对象类型,但是用的时候必须.value-->
<script>
import {ref, reactive} from 'vue'
export default {
let person = reactive({
'name':'lqz',
'age':19
})
let handleAdd = () => {
console.log('我要开始加了,age是', age)
person.age = person.age + 1 // 通过reactive可以直接点出值来修改
}
return {
person, handleAdd
}
}
五、计算和监听属性
5.1 计算属性
<template>
<input type="text" v-model="firstName "></input>
<input type="text" v-model="lastName "></input>
{{fullName }}
<!--就是通过两个输入框的输入的变化 然后触发computed的执行 然后该computed返回了 两个输入框的和 所以一个输入框发生变化 那么fullName也就跟着发生了变化-->
</template>
<script>
import {computed,} from 'vue' // 导入
// computed:{ vue2的写法
// fullName:function (){}
// },
setup() {
// 1 计算属性案例1
let firstName = ref('刘')
let lastName = ref('清政')
// 定义计算属性
let fullName = computed(() => { // 使用computed写计算属性
return firstName.value + lastName.value
})
return {firstName ,lastName ,fullName } // 这样页面上拿到的就是一个数据
// 2 计算属性案例2
let person = reactive({ // 使用了reactive包裹了 响应式 页面上就可以直接使用person.firstName显示了
firstName: '刘',
lastName: '清政',
})
// 定义计算属性
person.fullName = computed({ // 现在把fullName 添加到了person对象中
get() { // 可以写get对象
return person.firstName + '-' + person.lastName // 也可以直接点出数据了
},
set(value) { // 也可以写set对象
console.log(value)
const nameArr = value.split('-') // 使用split将get返回出来的值分割
person.firstName = nameArr[0]
person.lastName = nameArr[1] // 然后在赋值给firstName和lastName 这样我们修改fullName的时候 firstName也会跟着修改
}
})
return {
person
}
}
</script>
5.2 监听属性
import {watch, ref, watchEffect} from 'vue'
export default {
name: 'App',
setup() {
let name = ref('lqz')
// 定义监听属性
watch(name, (newValue, old) => { // 就当name变化的时候 就会触发watch函数
console.log('name变了')
console.log(old) // old就是修改之前的值
console.log(newValue) // newValue就是修改后的值
})
// vue3 又多了个watchEffect,只要函数中使用的变量发生变化,它就会触发
watchEffect(() => {
// 只要该函数中使用的变量发生变化,它就会触发
let a = name.value + '?' // 将name赋值给了a然后name加? 那么name就是发生了变化 然后就会触发watchEffect函数
console.log('watchEffect配置的回调执行了')
})
return {
name
}
}
}
六、生命周期
# Vue3.0中可以继续使用Vue2.x中的生命周期钩子,但有有两个被更名:
beforeDestroy 改名为 beforeUnmount # 删除组件之前
destroyed 改名为 unmounted # 删除组件之后
# Vue3.0也提供了 Composition API 形式的生命周期钩子,与Vue2.x中钩子对应关系如下:
# vue.2 vue.3
beforeCreate===>setup()
created=======>setup()
beforeMount ===>onBeforeMount
mounted=======>onMounted
beforeUpdate===>onBeforeUpdate
updated =======>onUpdated
beforeUnmount ==>onBeforeUnmount
unmounted =====>onUnmounted
<script>
export default {
import {onMounted, onBeforeUpdate} from 'vue' // 需要导入
name: 'test',
// 其实在setup外面也是可以写vue2的钩子函数的写法的 但是推荐在setup中编写 如果都写了的话 那么会优先执行setup中的在执行setup外面的钩子函数
setup(){
// beforeCreate和created可以直接在setup中编写函数 可以之间往后端发送axios请求
// 其他的钩子函数其实写法都一样就是名字变了
onMounted(() => { // 页面挂载之后 就会触发
console.log('onMounted')
})
onBeforeUpdate(() => { // 页面修改之后 重新挂载之前触发 其他的写法也是一样的
console.log('onMounted')
})
}
}
</script>
七、hooks
# 什么是hook?——
本质是一个函数,把setup函数中使用的Composition API进行了封装。
类似于vue2.x中的mixin。 就是把重复的代码可以提取出来 然后哪里需要用 那么在导入即可
自定义hook的优势: 复用代码, 让setup中的逻辑更清楚易懂
7.1 hooks/index.js
import {onMounted, onUnmounted, reactive} from "vue";
// 我们编写一个 只要在页面上点击 那么立刻打印这个点的xy轴
export default function () {
let p = reactive({ // 顶一个p对象,该对象中有x和y轴
x: 0,
y: 0
})
function getPoint(event) { // 定义一个getPoint函数
console.log(event)
p.x = event.pageX
p.y = event.pageY
}
// 声明周期钩子的onMounted,当页面挂载就会执行
onMounted(() => {
// 给数鼠标点击增加监听,就是当点击鼠标的时候,就会执行这个函数
window.addEventListener('click', getPoint) // 该函数就是帮我们知道点击的这个地方的x和y轴是多少
})
// 组件被销毁时,把功能去掉 组件销毁之后就需要把该功能去掉 不去掉会浪费资源
onUnmounted(() => {
window.removeEventListener('click', getPoint) // 该函数就是去掉该功能
})
return p // 然后把p对象返回
} // 然后把上述代码写到hooks文件中的index.js文件中
7.2 其他组件
<template>
<h2>x坐标是:{{ p.x }},y坐标是:{{ p.y }}</h2>
</template>
<script>
import hooks from './hooks/index'
export default {
setup() {
let p = hooks() // 需要加括号调用
return {p} // 接收的函数有几个返回值 就返回一个变量
}
}
</script>
八、toRefs
<template>
<!-- <h1>{{data.name}}</h1> -->
<!-- 本来我们在页面上显示对象的值 需要使用句点符的形式显示 但是如果我们使用了toRefs的话那么我们可以直接使用对象中的值 -->
<h1>{{name}}</h1>
<h1>{{age}}</h1>
<button @click="handleShow">点击</button>
dhiwhoidhwo
</template>
<script>
import {toRefs} from 'vue'
export default {
name: 'App',
setup() {
let data = reactive({
name: 'lqz',
age: 19,
isShow: true
})
function handleShow() {
console.log('ssdaf')
data.isShow = !data.isShow
data.age++
}
return {
...data,
// 就相当于解压了 然后 就等于name:'lqz',age:19返回了出去 但是如果就这样解压出去的话 页面修改的值不会修改data中的值 这样就不会关联起来了
...toRefs(data),
// 需要加上toRefs这样 页面上的变量才能继续跟data中的值绑定 页面变化 数据也跟着变化
handleShow
}
}
}
</script>