前言
官网地址:
https://staging-cn.vuejs.org/vue最新版分为两个版本: Vue3.0(20年9月18日) Vue 3.2 (21年8月10日)
#Vue 3.2 +Vite+volar
Vue3 框架做了大量的性能优化,包括虚拟 DOM,编译模板、代理的新数据监听,体积更小的打包文件等。
新的组合式 API (composition-api),更适合大型项目的构建,去除繁琐的 this 操作;
由于是基于 TypeScript 编写,对 TypeScript 原生支持更好,更强大的智能类型推导功能;
生命周期的一些改变,vue2 中的 beforeCreate 和 created 被一个新增的 setup 生命周期函数代替;
一些常见 API 如 v-model 的变化,支持对一个组件同时进行多个 v-model 的数据绑定。
vscode 的插件 vetur 对vue3 的composition API语法支持度非常弱,所以开发vue3项目需要将vetur禁用 更换另一个插件
开发vue3安装并使用: volar 插件
#1.项目创建
Vite 官网:https://cn.vitejs.dev/
yarn create vite my-vue-App --template vue
#2.SFC 单文件组件
html 部分变化不大
vue2的 template 中只能有一个子节点,vue3的 template 中可以写多个子节点
js 部分内置ts,但是vite创建的项目没有开启 , <script lang="ts" setup> 这样写即可支持ts
新增setup 语法糖,js代码大量简化
代码中不再出现 this
css 代码中 可以使用v-bind 指令
<template> <div> </div></template><script setup> let color = '#f60';</script><style scoped>.box{ width: 100px; height: 100px; background: v-bind(color);}</style>
#2. setup语法糖
起初 Vue3.0 暴露变量必须 return 出来,template中才能使用; 这样会导致在页面上变量会出现很多次。
vue3.2只需在script标签中添加setup,可以帮助我们解决这个问题。
1.组件只需引入不用注册,属性和方法也不用返回, 也不用写setup函数,也不用写export default , 甚至是自定义指令也可以在我们的template中自动获得。
#3.data 定义
#3.1 直接定义 无响应式
<template> <div> <h1>{{name}}</h1> <!-- 这里双向绑定失效,直接定义变量没有响应式特性 --> <input type="text" v-model="name"> </div></template><script setup> let name = '张麻子';</script>
#3.2 ref 定义基本数据类型 有响应式
<template> <div> <h1>{{name}}</h1> <!-- 修改数据 有响应式 --> <input type="text" v-model="name"> <button @click="setData">修改数据</button> </div></template><script setup> import {ref} from 'vue'; let name = ref('张麻子'); //js中修改数据有响应式 const setData = ()=>{ name.value = '黄四郎' } </script>
#3.3 reactvie 定义引用数据类型 有响应式
<template> <div> <h2>{{user.name}}</h2> <!-- 修改数据 有响应式 --> <input type="text" v-model="user.name"> <!-- 新增属性 --> <button @click="addItem">新增属性</button> </div></template><script setup>import {ref,reactive} from 'vue'let user = reactive({ name:'张麻子', age:40})// js中新增对象属性-可以直接赋值和修改(有响应式),在ts环境下,vscode会提示错误,但在页面中可以正常渲染const addItem = ()=>{ user.like='打豆豆'}</script>
#4.methods 方法定义
<template> <div> <!-- 年龄 + --> <h1>{{user.age}}</h1> <!-- 调用方法 --> <button @click="addAge">年龄+</button> </div></template><script setup>import { ref, reactive } from "vue";let user = reactive({ name: "张麻子", age: 40,});//方法const addAge=()=>{ user.age++;}//方法调用方法const getUserInfo=()=>{ addAge() console.log(user.age)}</script>
#5.computed 计算属性
<script setup>import { ref, reactive, computed } from "vue";let user = reactive({ name: "张麻子", age: 40,});//计算属性const getAge = computed(()=>{ return '我的年龄'+user.age})</script>
#6.watch 使用
watch(监听数据源,执行函数,[配置参数]) //配置参数: 立即执行 深度监听{immediate: true, deep: true }
#6.1 监听基本数据类型单一数据源
<script setup>import {ref, watch} from 'vue' let name = ref('张麻子') //监听器watch(name,(newVal,oldVal)=>{ console.log('变量发生了改变...',newVal);})</script>
#6.2 监听引用数据类型单一数据源
<script setup>import {reactive, ref, watch} from 'vue'let user = reactive({name:'张三',age:14}) //监听器watch(()=>user.name,(newVal,oldVal)=>{ console.log('对象user中的name属性发生了变化..',newVal);})</script>
#6.3 监听引用数据类型 多数据源[深度监听]
<template> <div> <button @click="addNum()"> 添加随机数</button> <div v-for="item in nums" :key="item">{{ item }}</div> </div></template><script setup>import { reactive, ref, watch } from 'vue'let nums = reactive([]);//添加随机数const addNum = () => { let num = Math.ceil(Math.random() * 100); nums.push(num);}//监听数组变化-深度监听watch(()=>nums,(newVal,oldVal)=>{ console.log('nums数组发生了变化..',newVal);},{deep:true})</script>
#7.生命周期
vue2 |
vue3.0 |
vue3.2 |
备注 |
beforeCreate |
|
setup |
组件创建之前 可以获取顶级实例对象 |
created |
|
setup |
组件创建完成,可以获取变量 |
beforeMount |
|
onBeforeMount |
挂载前,VNdom创建完成,真实dom未渲染 |
mounted |
|
onMounted |
挂载完成,真实dom创建完成,可以获取dom |
beforeUpdate |
|
onBeforeUpdate |
dom更新前触发 |
updated |
|
onUpdated |
dom更新完成触发 |
beforedestroy,destroyed |
beforeUnmount |
onBeforeUnmount |
组件卸载后触发 所有的挂载的数据 子组件全部卸载后触发 |
|
errorCaptured |
onErrorCaptured |
在捕获一个来自后代组件的错误时被调用 |
|
renderTracked |
onRenderTracked |
跟踪虚拟 DOM 重新渲染时调用 |
|
renderTriggered |
onRenderTriggered |
当虚拟 DOM 重新渲染被触发时调用 |
activated |
activated |
onActivated |
缓存组件激活时调用 |
deactivated |
deactivated |
onDeactivated |
缓存组件失活时调用 |
<template> <div> <div class="box"></div> </div></template><script setup>import { onMounted } from 'vue'; //生命周期钩子监听 onMounted(()=>{ console.log(document.querySelector('.box')); //可以获取dom })</script>
#8.组件使用
- 创建 src/components/Son.vue
- App.vue中导入并使用该组件
- vue3.2 中当我们导入子组件时,setup语法糖会自动去注册该组件,所以注册语句不用写了。
<template> <div> <son></son> </div><script setup>import Son from './components/Son.vue'</script>
#9.组件通信
#9.1 父传子 defineProps
- 父组件
<template> <div> <Son class="box" title="我是父组件传递的标题" :likes="likes"></Son> </div></template><script setup> import Son from './components/Son.vue' let likes = ['张三','李四']</script>
- 子组件
<script setup>const props=defineProps({ title:{ type:String, default:'' }, likes:{ type:Array, default:()=>[] }})</script>
#9.2 子传父 defineEmits
- 子组件
<template> <div> <button @click="sendData">传递数据</button> </div></template><script setup>//定义自定义事件const emit = defineEmits(['send'])//自己的事件执行函数const sendData = () => { //执行自定义事件 emit('send', '我是儿子组件传递的数据')}</script>
- 父组件
<template> <div> <Son class="box" @send="getData" ></Son> </div></template><script setup> import Son from './components/Son.vue' //触发自定义事件-接收数据 const getData = (data)=>{ console.log(data); }</script>