1.初识vue3:
vue3支持大多数vue2特性
性能提升
打包减少40%、初次渲染快55%、更新渲染快133%、内存减少54%、使用Proxy代替defineProperty实现数据响应式、重写虚拟dom的实现和Tree-shaking
新增特性:
Composition(组和)api
setup:(ref和reactive/computed和watch/新的生命周期/provide和inject)
新组件:Fragment-文档碎片、Teleport-瞬移组件位置、Suspenes-异步加载组件的loading界面
其他api: 全局api的修改、将原来的全局api转移到应用对象、模板语法变化
2.创建vue3项目:
一、使用vue-cli创建项目
1.如果是第一次创建vue项目,那么应该先安装vue脚手架,全局安装一次即可,其命令:
yarn add @vue/cli -g
2.查看是否安装成功,可以通过查看版本号得知是否安装成功,其命令:
vue --version 或 vue -V
3.通过vue-cli脚手架创建vue项目,其命令:
vue create my-test
4.进入项目输入命令启动项目:npm run serve ,可以在浏览器看到项目正常启动了。
二、使用vite创建项目:
vite是一个由原生ESM驱动的web开发构建工具,在开发环境下基于浏览器原生ES imports开发,它做到了本地快速开发启动,在生产下基于rollup打包。快速的冷启动,无需打包操作,及时的热模块更新,替换性能和模块数量的解耦让更新更快,真正的按需编译,不再等待整个应用编译完成。
1.通过vite创建项目的命令:
npm init vite-app vitedemo
2.进入项目先下载依赖包:vite创建的项目,默认是没有下载依赖包的:
cd vitedemo
npm install
3.启动项目,其命令:
npm run dev
3.vue3项目源码分析:
main.ts文件分析:
// 1.createApp方法在vue3中用来创建一个应用
import { createApp } from 'vue'
// 2.App组件为所有组建的父级组件:
import App from './App.vue'
import router from './router'
import store from './store'
// 3.createApp传入App组件创建一个vue实例,并使用链式调用挂载vuex和router并通过mount挂载到#app上面:
createApp(App).use(store).use(router).mount('#app')
App.vue文件分析:
HomeView.vue组件分析:
4.setup和ref:
setup是一个新的配置,所有的组合API函数都在此使用,它只在初始化时执行一次,函数如果返回对象,对象中的属性或方法,在模板中可以直接使用,setup可以理解为vue2中data中数据,但是并不是响应式的,如果需要响应式,那么还需要借助ref, setup方法组件每次进入都会执行一次。
ref是用来定义一个基本类型(测试引用型也会响应式被改)的响应式数据的方法,如果想要操作这个响应式数据,可以通过此属性返回对象的value方法对数据值进行操作,而模板中是不需要value的,如:
{{ sayHello }}
{{ satHi }}
引用型被改:
{{ satHi.names }}
5.reactive:
reactive用来定义一个引用型的响应式数据,它返回一个Proxy的代理对象,被代理者就是reactive中的传入对象。
{{ user.names }}
{{ user.age }}
{{ user.height }}
{{ user.sex }}
6.vue3响应数据的原理:
vue2中数据响应是: 使用 Object.defineProperty 方法添加对象,重写了原有的 get 和 set 方法实现。
vue3中数据响应是通过Proxy代理实现的,它是深度更新的,具体如下:
// 目标对象:给对象设置any类型,表示可以接收任意类型的对象属性值
const obj:any = {
names: '小明',
age: 18
}
// 代理对象:Proxy第一个参数传入目标对象,第二个参数用于操作目标对象
const proxyObj = new Proxy(obj, {
// 1.get方法用于获取某个对象的属性:参数一为目标对象,参数二为对象属性,此方法需要通过返回 Reflect.get才可以在代理对象中拿到属性值
get (target, props) {
console.log('get方法调用了')
return Reflect.get(target, props)
},
// 2.set方法用于设置某个对象的属性值,同时可以给某个对象添加新的属性,同样需要通过返回Reflect.set才可以实现
set (target, props, newValue) {
console.log('set方法调用了')
return Reflect.set(target, props, newValue)
},
// 3.deleteProperty方法用于删除某个对象的属性值,同样需要通过返回Reflect.deleteProperty才可以实现
deleteProperty (target, props) {
console.log('属性被删除了')
return Reflect.deleteProperty(target, props)
}
})
// 通过代理对象获取目标对象中的某个属性值:
console.log(proxyObj.names) // 未返回Reflect.get时打印内容为:undefined;返回Reflect.get时打印内容为:小明
// 通过代理对象设置目标对象中的某个属性值:
proxyObj.age = 22
// 通过代理对象新增某个属性:
proxyObj.height = 150
// 查看目标对象:
console.log(obj) // {names: '小明', age: 22, height: 150}
// 通过代理对象删除某个对象的属性:
delete proxyObj.names
// 查看目标对象:
console.log(obj) // {age: 22, height: 150}
7.setup详细介绍:
父组件:
父组件:{{ satHi }}
父组件:{{ num }}
子组件:
子组件中:{{ msg }}
8.reactive与ref细节:
obj1: {{ obj1 }}
obj2: {{ obj2 }}
9.计算属性和监视:
姓氏:
firstName:{{ firstName }}
名字:
lastName:{{ lastName }}
fullName:
fullName:{{ fullName }}
fullName2:
compChange:{{ compChange }}
-----------通过计算属性实现姓名显示:----------
fullName:{{ fullName }}
fullName2:{{ fullName2 }}
----------------watch监听非响应式数据-------------
user.names
user.names:{{ user.names }}
10.生命周期:
vue3中生命周期和vue2中生命周期基本一样,只有最后销毁前和销毁的不一样,在vue3中分别是beforeUnmount和unmounted;vue2中生命周期函数都是组件的配置对象,而vue3中都是组合式api,当然vue2中的配置对象生命周期在vue3中同样支持,vue2中的生命周期函数在vue3中对应的组合式api分别如下:
beforeCreated -> setup
created -> setup
beforeMount -> onBeforeMount
mounted -> onMounted
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
beforeDestroy(且vue3中vue2改名为:beforeUnmount) -> onBeforeUnmount
destroyed(且vue3中vue2改名为:unmounted) -> onUnmounted
errorCaptured -> onErrorCaptured
vue3还新增了2个生命周期函数:
onRenderTracked:
onRenderTriggered:
hello组件输出:{{ msg }}
11.hook函数:
vue3中的hook函数类似于vue2中mixin技术,hook函数的优势:很清楚复用功能代码的来源,vue2中mixin是将一段在多个组件中都用到的代码惊醒抽离,然后通过mixin引入到当前组件即可,而vue3中和vue2中类似。
封装hook函数:
// 引入需要用的到组合式api:
import { ref, onMounted, onBeforeUnmount } from 'vue'
// 1.导出一个公共的方法用来获取点击屏幕的坐标:
export const usePointerClick = () => {
const x = ref(0)
const y = ref(0)
const clickHandle = (e: any) => {
x.value = e.pageX
y.value = e.pageY
}
// 页面挂载时给window注册获取坐标事件
onMounted(() => {
window.addEventListener('click', clickHandle)
})
// 页面卸载时注销window获取坐标事件
onBeforeUnmount(() => {
window.removeEventListener('click', clickHandle)
})
// 将值返回出去
return {
x,
y
}
}
组件中使用:
home页:
点击的坐标是:{{ x + ',' + y }}
12.toRefs的使用:
toRefs可以把一个响应式对象reactive转换成普通对象,改普通对象的每一个属性都是一个ref。
{{ age }}
{{ obj.age }}
13.ref获取元素:
ref还有另一个作用,用于获取页面中的元素,对元素操作需要在onMounted钩子后面,并且需要先判断其value值是否存在,如:
box盒子
14.shallowReactive和shallowRef:
shallowReactive只处理对象的外层响应式,它是一个浅Reactive;
shallowRef只处理value的响应式,不进行对象的reactive处理。
经测试:它们都会深度监测,测试代码:
ref{{ val1 }}
reactive{{ val2 }}
shallowRef{{ val3 }}
shallowReactive{{ val4 }}
提示:本文图片等素材来源于网络,若有侵权,请发邮件至邮箱:[email protected]联系笔者删除。
笔者:苦海