vue3初识
Vue2 vs Vue3
Vue2
- 选项式API(对象形式)
- 只能有一个根元素/使用 this 访问变量
- 打包工具 Webpack
- 状态管理 Vuex
- 语法高亮插件 Vetur
Vue3
- 组合式API(函数形式)
- 可以有多个根元素/使用 .value 访问变量
- 打包工具 Vite
- 状态管理 Pinia
- 语法高亮插件 Volar
创建第一个Vue3项目
切换npm下载源为淘宝
npm set registry https://registry.npmmirror.com/
安装pnpm
npm install -g pnpm
使用pnpm代替npm创建项目
pnpm create vue #或 npm init vue@latest
Vue3组件化增删改查
- 在父组件中完成列表渲染、删除
- 将弹层单独封装为一个子组件,新增/编辑时打开弹层,在子组件中请求更新
- 父组件通过 ref 函数可以得到子组件的实例,调用子组件中的方法打开弹层,同时传入当前行内容供数据回显
- 子组件更新完毕后,要定义 defineEmits 通知父组件更新列表,重新渲染
读取/修改 ref 数据记得 .value
子组件实例中的方法只有 defineExpose 暴露出去才能让父组件访问
组合式API
setup
setup函数 是 Vue3 代码执行的入口。语法:
setup() {
// Vue3代码
// 其中的变量和方法,必须返回后才能在模板中使用
}
在组件初始化时,setup 函数最先被执行
setup 函数中不能使用 this 获取组件实例
在 script 标签上添加 setup 属性语法糖,可以省略 setup 函数,直接写 Vue3 代码
ref&reactive
ref函数/reactive函数 用来定义响应式数据。语法:
import { ref } from 'vue'
const 变量 = ref(值)
import { reactive } from 'vue'
const 变量 = reactive({
属性1: 值1,
属性2: 值2,
... ...
})
reactive 不能封装简单类型的数据
ref 既支持简单类型数据,也支持复杂类型数据,但必须通过 .value 访问数据
ref 封装复杂类型数据时,响应式的实现依赖于函数内部的 reactive 函数
reactive响应失效问题
只有 reactive 函数处理过的对象是响应式的,这点一定要注意:
let person = reactive({
name: '张三',
age: 18
})
// 这里将 person 变量赋值了一个新对象
person = {
name: '李四',
age: 23
}
// => person 失去了响应式特性
computed
computed函数 用来定义计算属性。语法:
import { computed } from 'vue'
const 变量 = computed(()=>{
return 计算后的值
})
watch
watch函数 用来定义监听器。语法:
watch([变量1,变量2...],(newVal,oldVal) => {
// 数据变化后的操作
},{
immediate: true, //初始化时立即执行一次
deep: true //深度监听
})
当监听多个数据时,任何一个数据改变都会触发这个回调,此时 newVal、oldVal 将得到一个数组
监听对象类型时,由于存在引用关系,newVal 与 oldVal 得到的都是变化后的对象
组合式API进阶
编译宏函数
Vue3 提供了一些全局的编译宏函数,不需要导入就可以直接使用:
defineProps():用于组件通信(父传子)defineEmits():用于组件通信(子传父)defineExpose():暴露子组件中的方法,供父组件使用
生命周期函数
onMounted(()=>{
// DOM挂载完毕后的操作
})
Vue3 中,没有 onBeforeCreate/onCreated 钩子函数,所有的初始化操作通常在 onMounted 函数中进行
同一钩子函数可以多次调用,它们从上往下依次执行
父子组件通信
eg.父子组件通信案例
<template>
<div class="dad">
<h3>父组件</h3>
<Son :money="money" @change-money="changeMoney"></Son>
</div>
</template>
<script setup>
import Son from './Son.vue'
import { ref } from 'vue'
const money = ref(100)
const changeMoney = (newMoney) => {
money.value += newMoney
}
</script>
<template>
<div class="son">
<h3>子组件</h3>
<p>老子给的钱:{{ money }}</p>
<button @click="getMoney">再多给点吧</button>
</div>
</template>
<script setup>
// 接收父组件传递的数据
defineProps({
money: {
type: Number,
required: true
}
})
// 通知父组件修改
const emit = defineEmits(['change-money'])
const getMoney = () => {
emit('change-money', 100)
}
</script>
Vue3 中,不需要显式地注册一个组件,导入就可以使用
子传父的本质是:子组件通过触发父组件中的某个方法,通知父组件进行数据更新(有时可以利用子传父的特点来访问子组件内部的数据)
跨层级组件通信
跨层级组件通信的过程:
-
顶层组件通过 provide 函数提供数据
-
底层组件通过 inject 函数接收数据
eg.跨层级组件通信案例
// 父组件
import Son from './Son.vue';
import { provide, ref } from 'vue';
const money = ref(100)
const changeMoney = (newMoney) => {
money.value += newMoney
}
provide('money', money)
provide('changeMoney', changeMoney)
// 子组件
import { inject } from 'vue';
// 接收数据用来渲染
const money = inject('money')
// 接收函数用来通知父组件进行数据更新
const changeMoney = inject('changeMoney')
<template>
<div>
<h3>我是子组件</h3>
<p>老子给的钱:{{ money }}</p>
<button @click="changeMoney(100)">再多给点吧</button>
</div>
</template>
模版引用
在 Vue3 中,使用 ref 函数可获取DOM元素或组件实例:
- 定义一个空的 ref 变量
- 在模版中绑定这个变量
ref="变量名" - 在组件加载完毕后,通过
变量名.value获取DOM元素/组件实例
eg.操作DOM元素
<h3 ref="h3">模版引用</h3>
const h3 = ref(null)
// 只有加载完毕后,才能获取到DOM元素
onMounted(()=>{
h3.value.style.color = 'red'
})
eg.操作组件实例
<el-form ref="form"></el-form>
const form = ref(null)
onMounted(()=>{
form.value.validate()
})
在组件内部,需要显式暴露其中的属性或方法:
const validate = ()=> {
console.log('正在进行表单校验...')
}
// 显式暴露组件内部的属性和方法
defineExpose({
validate
})