vue之vue3
一、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>