一、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 # vite创建另一种方式:创建vue3.0.4版本 npm init vite-app <project-name> ## 进入工程目录 cd <project-name> ## 安装依赖 npm install ## 运行 npm run dev # 启动的两种方式 # 以后再页面中的this,已经不是vue2中的vc对象了,是一个代理对象 ## app.vue <template> <img alt="Vue logo" src="./assets/logo.png" /> <HelloWorld msg="Hello Vue 3.0 + Vite" /> </template> <script> import HelloWorld from './components/HelloWorld.vue' export default { name: 'App', components: { HelloWorld }, created() { console.log('######',this) } } </script> ## main.js import {createApp} from 'vue' import App from './App.vue' import './index.css' // import Vue from 'vue' // Vue.use() // new Vue().$mount('#app') var app=createApp(App) app.mount('#app') console.log('------',app)
三、setup函数
Vue新增的setup配置项函数
-
在里面可以定义变量
-
定义函数
-
必须return变量和函数,在模板中才能使用
<template> <h2>{{ name }}</h2> <h2>{{ age }}</h2> <button @click="handleClick">点我看消息</button> <br> <br> <button @click="handleAdd">点我,age+1</button> </template> <script> import HelloWorld from './components/HelloWorld.vue' export default { name: 'App', // 组合式API // 以后所有的变量定义函数编写,都写在这个函数中 setup() { // setup中没有this了 let age = 19 let name = 'xj' console.log('###',this) // 定义函数 function handleClick() { alert('加油~') } // 定义变量,如果这么写,渲染没问题,但是没有响应,页面变了,变量不会变 let handleAdd = () => { console.log('年龄加一') console.log(this) age = age + 1 console.log(age) } // 函数必须有返回值 return { age, name, handleClick, handleAdd } } } </script>
setup函数的参数
<!--APP.vue--> <template> <h2>setup函数的参数</h2> <hr> <HelloWorld msg="xj is cute"></HelloWorld> </template> <script> import HelloWorld from "./components/HelloWorld.vue"; export default { name: 'App', components: {HelloWorld}, setup() { return {} } } </script> <!--HelloWord.vue--> <template> <h1>我是HelloWorld组件</h1> </template> <script> export default { name: 'HelloWorld', // 可以接收采参数:context,内部函数props接受的自定义属性 props:['msg'], setup(context) { console.log('###',context) return {} } } </script>
四、ref和reactive
# 导入使用:import {ref, reactive} from 'vue' # 基本数据类型(数字,字符串,布尔)如果要加响应式:使用ref包裹,在模板中之间使用,js中通过对象.value取值 # 对象,数组引用使用reactive,ref可以包对象类型,但是用的时候必须.value 接收的数据类型可以是:基本类型也可以是对象类型 基本数据类型的数据:响应依然是靠Object.defineProperty()的get与set完成的 对象的数据类型:reactive函数
4.1ref的使用
作用:定义一个响应式的数据 语法:let 变量=reactive(值) JS中操作数据:变量.value 模板中读取数据:不需要 变量.value,直接:{{变量}}
<template> <h2>{{ name }}</h2> <h2>{{ age }}</h2> <br> <button @click="handleAdd">点我,age+1</button> <br> <button @click="handleChangeName">点我name变化</button> </template> <script> import {ref, reactive} from 'vue' export default { name: 'App', setup() { let age = ref(19) let name = ref('xj') let handleAdd = () => { console.log('现在age是', age) age.value = age.value + 1 console.log('现在age是', age.value) } function handleChangeName() { name.value = name.value + '?' console.log(name) } return { age, name, handleAdd, handleChangeName } } } </script>
4.2reactive的使用
语法:const 变量=ref({ K:value值, K:value值, }) JS中操作数据:info.变量名 模板中读取数据:{{info.变量}} # 对象在渲染时直接对象点key就可以获取到value,也可以直接给对象添加方法。
<template> <h2>{{ info.name }}</h2> <h2>{{ info.age }}</h2> <br> <button @click="info.handleAdd">点我,age+1</button> </template> <script> import {reactive} from 'vue' export default { name: 'App', setup() { let info = reactive({ name: 'xj', age: 22 }) info.handleAdd = () => { info.age += 1 console.log('现在age是', info.age) } console.log('###', info) return { info } } } </script>
五、计算和监听属性
5.1计算属性
<template> <h2>计算属性</h2> <p>姓:<input type="text" v-model="info.firstName"></p> <p>名:<input type="text" v-model="info.lastName"></p> <p>全名:<input type="text" v-model="info.fullName"></p> </template> <script> import {computed, reactive} from "vue"; // 计算属性,监听属性 export default { name: 'App', setup() { const info = reactive({ firstName: '', lastName: '' }) info.fullName = computed({ get() { return info.firstName + '_' + info.lastName }, // 修改属性会执行set函数,并将修改后的值传入 set(val) { console.log(val) let strArray = val.split('_') info.firstName = strArray[0] info.lastName = strArray[1] } }) return { info } } } </script>
5.2监听属性
<template> <h2>监听属性</h2> <p><input type="text" v-model="name">{{ name }}</p> </template> <script> import {watch, ref, watchEffect} from "vue"; // 计算属性,监听属性 export default { name: 'App', setup() { const name = ref('jimin') watch(name, (newvalue, oldvalue) => { console.log(newvalue) console.log(oldvalue) }) watchEffect(() => { // 只有当watchEffect里使用的变量值才会执行该函数 let a = name.value console.log('执行了') }) return { name } } } </script>
六、生命周期
-
beforeCreate:在组件实例初始化完成之后立即调用。组合式 API 中的 setup() 钩子会在所有选项式 API 钩子之前调用,beforeCreate() 也不例外。
-
created:在组件实例处理完所有与状态相关的选项后调用。当这个钩子被调用时,以下内容已经设置完成:响应式数据、计算属性、方法和侦听器。然而,此时挂载阶段还未开始,因此 $el 属性仍不可用。
-
beforeMount:在组件被挂载之前调用。当这个钩子被调用时,组件已经完成了其响应式状态的设置,但还没有创建 DOM 节点。它即将首次执行 DOM 渲染过程。这个钩子在服务端渲染时不会被调用。
-
mounted:在组件被挂载之后调用。这个钩子在服务端渲染时不会被调用。
-
beforeUpdate:在组件即将因为一个响应式状态变更而更新其 DOM 树之前调用。
-
updated:在组件因为一个响应式状态变更而更新其 DOM 树之后调用。
-
beforeUnmount:在一个组件实例被卸载之前调用。当这个钩子被调用时,组件实例依然还保有全部的功能。
-
在一个组件实例被卸载之后调用。可以在这个钩子中手动清理一些副作用,例如计时器、DOM 事件监听器或者与服务器的连接。
# Vue3.0中可以继续使用Vue2.x中的生命周期钩子,但有有两个被更名: beforeDestroy改名为 beforeUnmount destroyed改名为 unmounted # Vue3.0也提供了 Composition API 形式的生命周期钩子,与Vue2.x中钩子对应关系如下: beforeCreate===>setup() created=======>setup() beforeMount ===>onBeforeMount mounted=======>onMounted beforeUpdate===>onBeforeUpdate updated =======>onUpdated beforeUnmount ==>onBeforeUnmount unmounted =====>onUnmounted
<!--App.vue--> <template> <h2>生命周期</h2> <button @click="handleClick">点我消失</button> <HelloWorld v-if="show"></HelloWorld> </template> <script> import HelloWorld from "./components/HelloWorld.vue"; import {ref} from 'vue' // 计算属性,监听属性 export default { name: 'App', components: {HelloWorld}, setup() { let show = ref(true) const handleClick = () => { show.value = !show.value } return { show, handleClick } } } </script> <!--HelloWord.vue--> <template> <h1>我是HelloWorld组件</h1> </template> <script> import {onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted} from "vue"; export default { name: 'HelloWorld', setup() { console.log('组合式api的beforeCreate') console.log('组合式api的created') onBeforeMount(() => { console.log('组合式api的onBeforeMount') }) onMounted(() => { console.log('组合式api的onMounted') }) onBeforeUpdate(() => { console.log('组合式api的onMounted') }) onBeforeUnmount(() => { console.log('组合式api的onBeforeUnmount') }) onUnmounted(() => { console.log('组合式api的onUnmounted') }) return {} } } </script>
七、hooks
在Vue应用概念中,‘组合式函数(Composables) ’是一个利用Vue的组合式API来封装和复用有状态逻辑的函数。
本质
:是一个函数,把setup函数中使用的Composition API进行了封装。类似于vue2.x中的mixin。自定义hook的优势:复用代码,让setup中的逻辑更清晰易懂。
7.1hook/usePoint.js
<!--App.vue--> <template> <h2>打点功能</h2> <button @click="handleShow">点我消失组件</button> <hr> <Point v-if="show"></Point> </template> <script> import Point from "./components/Point.vue"; import {ref} from "vue"; export default { name: 'App', components: {Point}, setup() { let show = ref(true) function handleShow(){ show.value = !show.value } return {show, handleShow} } } </script> <!--components/Point.vue--> <template> <h2>x坐标是:{{ p.x }},y坐标是:{{ p.y }}</h2> </template> <script> import {reactive, onMounted, onUnmounted} from 'vue' export default { name: "Point", setup() { let p = reactive({ x: 0, y: 0, }) function getPoint(event) { console.log(event) console.log('我被点了') p.x = event.pageX p.y = event.pageY } // 声明周期钩子的onMounted,当页面挂载就会执行 onMounted(() => { // 给鼠标点击增加监听事件 window.addEventListener("click", getPoint) }) // 组件被销毁时,把功能去掉 onUnmounted(() => { window.removeEventListener('click', getPoint) }) return { p } } } </script>
7.2在想使用的组件中引入使用即可
<!--App.vue--> <template> <h2>打点功能</h2> <button @click="handleShow">点我消失组件</button> <hr> <Point v-if="show"></Point> </template> <script> import Point from "./components/Point.vue"; import {ref} from "vue"; export default { name: 'App', components: {Point}, setup() { let show = ref(true) function handleShow(){ show.value = !show.value } return {show, handleShow} } } </script> <!--components/Point.vue--> <template> <h2>x坐标是:{{ p.x }},y坐标是:{{ p.y }}</h2> </template> <script> import {reactive, onMounted, onUnmounted} from 'vue' import usePoint from "../hook/usePoint.js"; export default { name: "Point", setup() { let p=usePoint() return { p } } } </script> <!--hook/usePoint.js--> import {onMounted, onUnmounted, reactive} from "_vue@3.2.41@vue"; export default function (){ let p = reactive({ x: 0, y: 0, }) function getPoint(event) { console.log(event) console.log('我被点了') p.x = event.pageX p.y = event.pageY } // 声明周期钩子的onMounted,当页面挂载就会执行 onMounted(() => { // 给鼠标点击增加监听事件 window.addEventListener("click", getPoint) }) // 组件被销毁时,把功能去掉 onUnmounted(() => { window.removeEventListener('click', getPoint) }) return p }
八、toRefs
<img src="" width="800">
九、后台管理模板
<img src="" width="800">