120.《vue3.0 最全详细总结+案例》
文章目录一、创建Vue3.0工程1.使用 vue-cli 创建2.使用 vite 创建二.常用 Composition API1.ref函数2.reactive函数3.vue2.0响应式原理4.vue3的响应式原理5.reactive 和 ref 区别6. setup的注意点7.计算属性与监听器1.computed2.watch3.watchEffect函数8.vue3 生命周期9.自定义hook
一、创建Vue3.0工程
1.使用 vue-cli 创建
官方文档:vue-cli
## 查看@vue/cli版本,确保@vue/cli版本在4.5.0以上
vue --version
## 安装或者升级你的@vue/cli
npm install -g @vue/cli
## 创建
vue create vue_test
## 启动
cd vue_test
npm run serve
2.使用 vite 创建
官方文档:https://v3.cn.vuejs.org/guide/installation.html#vite
vite官网:https://vitejs.cn
- 什么是vite?—— 新一代前端构建工具。
- 优势如下:
- 开发环境中,无需打包操作,可快速的冷启动。
- 轻量快速的热重载(HMR)。
- 真正的按需编译,不再等待整个应用编译完成。
- 传统构建 与 vite构建对比图
## 创建工程
npm init vite-app <project-name>
## 进入工程目录
cd <project-name>
## 安装依赖
npm install
## 运行
npm run dev
二.常用 Composition API
1.理解:vue3.0中的一个新的配置项,值为一个函数
2.setup是所有组合API(composition)的基础
3.组件所用到的 数据 方法 ,都配置在setup中
4.setup的返回值为对象,对象的值为setup中的数据,方法注意点
-
尽量不要与vue2.x的混用,vue2.x中可以访问到vue3.0的 数据与方法而3.x不能访问到 vue2.X的数据和方法
-
setup不能被 async 修饰,因为vue3.0.X的返回值注定是个对象,如果被 async 修饰,那返回值就成为一个 promise了,vue3.X并没对 为promise的情况进行处理,因此setup不能被async修饰
案例:
<template>
<div>
<h1>vue2.0</h1>
<h3>{{msg01}}</h3>
<button @click="sendMenth02">点我触发vue的方法</button>
<hr>
<h1>vue3.0</h1>
<h3>这是vue3--{{name}}</h3>
<button @click="sengmenth3">点我触发vue3的方法</button>
</div>
</template>
<script>
export default {
name: 'App',
data(){
return {
msg01:"这是vue2得用法"
}
},
methods:{
sendMenth02(){
alert("这是vue2的方法")
// vue2可以访问到vue3的数据和方法
// this.sengmenth3()
// console.log( this.name );
// console.log( this.age );
}
},
setup(){
let name = '张三'
let age = 18
function sengmenth3(){
alert("这是vue3的方法")
console.log( `我是${name},${age}岁` );
}
return {
name,
age,
sengmenth3
}
}
}
</script>
<style>
#app {
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
1.ref函数
概念:ref函数可以实现 响应式数据
语法:
import {ref} 'vue'
const name = ref('张三')
const obj = ref({
kind:"web前端",
salary:"30k"
})
-
被ref函数包裹 返回一个 ref 引用实例对象
-
修改被ref包裹的数据方式
// 基本数据类型 name.value = '李四' // 对象数据类型 onj.value.kind = 'ui工程师' obj.value.salary = '60k'
-
被ref包裹的基本数据类型返回一个ref引用实例,被包裹的对象通过其 reactive函数返回一个proxy对象,实现对象的响应式
2.reactive函数
-
作用:定义一个对象类型的响应式数据(基本数据类型不用它,用ref)
-
语法:reactive包裹一个对象或数组,返回一个被包裹后的代理对象
const 代理对象 = reactive(源对象)
-
reactive 定义的数据是深层次的,可以被深度监听响应式
-
reactive 的底层是通过es6的proxy代理实现深度响应式
案例(骚写法):
<template>
<div>
<h1>vue3.0</h1>
<h3>这是vue3----name-----{{person.name}}</h3>
<h3>这是vue3-----age-----{{person.age}}</h3>
<h3>这是vue3-----job-----{{person.obj.kind}}</h3>
<h3>这是vue3-----salary-----{{person.obj.salary}}</h3>
<button @click="sengmenth3">点我触发vue3的方法</button>
</div>
</template>
<script>
import { ref,reactive } from "vue";
export default {
name: "App",
setup() {
let person = reactive({
name:"张三",
age:18,
obj:{
kind:"工程师",
salary:'30k'
}
})
function sengmenth3() {
console.log( person );
person.name="李四"
person.age=20
person.obj.kind='ui工程师'
person.obj.salary='60k'
}
return {
person,
sengmenth3
};
}
};
</script>
<style>
#app {
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
3.vue2.0响应式原理
-
实现原理
-
对象类型:通过对 object.defindProperty() 对属性的读取 修改进行拦截(数据劫持)
object.defindProperty()
-
数组类型:通过重写数组的一系列方法来进行拦截(对数组的变更方法进行了拦截)
push() pop() shift() unshift() splice() sort() reverse()
vue2.0响应式存在的问题
- 新增属性,删除属性也不会进行更新
- 通过下标修改数组,页面不会进行更新
原理模拟代码:
-
案例1:
// vue2中的响应式 无法监听 对象 新增 和 删除 属性
let person = {
name: "张三",
age: 18
}
let p = {}
Object.defineProperty(p, "name", {
configurable:true,
get() {
console.log('读取了name属性', person.name);
return person.name
},
set(value) {
console.log('修改了name属性', value);
person.name = value
}
})
案例2:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h1>你好,我是<span></span></h1>
<h1>我来自于:<span></span></h1>
</div>
<script>
let userinfo = {}
Object.defineProperty(userinfo,'name',{
configurable:true,
get(){
return document.getElementsByTagName('span')[0].innerHTML
},
set(val){
return document.getElementsByTagName('span')[0].innerHTML = val
}
})
Object.defineProperty(userinfo,'address',{
get(){
return document.getElementsByTagName('span')[1].innerHTML
},
set(val){
return document.getElementsByTagName('span')[1].innerHTML = val
}
})
</script>
</body>
</html>
4.vue3的响应式原理
- 通过 Proxy代理,拦截对象中任意属性的变化,包括对象的新增属性,删除属性
- 通过 Reflect 反射,对元对象属性进行操作
// vue 3 响应式原理
let per = {
name:"li飞",
age:15
}
// let p = new Proxy(per,{})
// p 输出的结果
// [[Handler]]: Object 增删啊改 的 方法
// [[Target]]: Object 源数据
// [[IsRevoked]]: false
let p = new Proxy(per,{
// 读取时 触发
get(target,propName){
console.log( '当属性被读取时触发' );
return Reflect.get(target,propName)
},
// 修改时 触发
set(target,propName,newVal){
console.log( "属性被修改时触发",target,propName,newVal );
// target[propName] = newVal
Reflect.set(target,propName,newVal)
},
// 删除时 触发
deleteProperty(target,propName){
console.log( "属性被删除时触发" ,target,propName)
// delete target[propName]
Reflect.deleteProperty(target,propName)
}
})
5.reactive 和 ref 区别
- 从定义数据的角度对比:
- ref 用来定义:基本数据类型
- reactive 用来定义:对象或数组类型
- 备注:ref 也可以定义 数组或对象 ,它内部会通过 reactive函数转为代理对象
- 从原理角度:
- ref 底层通过 Object.defineProperty() 的get 和 set 来实现 响应式(数据劫持)
- reactive 通过使用 Proxy 来实现响应式(数据劫持),并通过 Reflect 来操作源对象内部的数据
- 从使用角度对比:
- ref 定义的数据:操作数据需要 .value,读取数据时,模板中直接读取,不需要 .value
- reactive 定义的数据:操作数据与读取数据:均不需要 .value
6. setup的注意点
-
setup 执行时机
- 在 beforeCreate 之前,并且 其内部中的 this 为 undefined
-
setup两个参数
-
props: 值为对象,且为父组件传递过来的数据,且在组件中通过 props 接收的数据
-
context
- attrs: 值为对象 且为父组件传递过来的数据,且没在 props中定义的数据
- emit: 分发自定义事件的函数 相当于 this.$emit
- s l o t : 收 到 的 插 槽 内 容 相 当 于 t h i s . slot: 收到的插槽内容 相当于 this. slot:收到的插槽内容相当于this.slot
-
案例
父组件
<template> <Demo01 @hello='currentEvent' msg="你好呀" school="清华" > <template v-slot:test1> <span>插槽</span> </template> </Demo01> </template> <script> import Demo01 from "./page/demo01.vue"; export default { name: "App", components:{ Demo01 }, setup(){ function currentEvent(val){ alert(`我接受到了子组件传递过来的数据${val}`) } return { currentEvent } } }; </script> <style> #app { text-align: center; color: #2c3e50; margin-top: 60px; } </style>
- 子组件
<template> <div> <h1>{{msg}}</h1> <h1>{{school}}</h1> <button @click="sendData">点击发送数据到父组件</button> </div> </template> <script> export default { props:['msg'], emits:['hello'], beforeCreate(){ console.log( "---- beforeCreate ----" ); }, setup(props,context){ // setup 中的执行时机 正在 beforeCreate() 前 并且 this 为 undfind console.log( "---- setup ----",this ); // 组件传递过来的参数 props 接收过的参数 console.log( props ); // 组件插槽 console.log( context.slots ); // 相当于 this.$attrs 且 没有在 props 中申明的参数 console.log( context.attrs ); // 子向父 传值 function sendData(){ context.emit('hello',6666) } return { sendData } } } </script>
-
7.计算属性与监听器
1.computed
- 与 vue2.x 的功能一致
- 语法
<template>
<div>
<h1>vue3.0</h1>
<input type="text" v-model="p.startName" >
<br>
<input type="text" v-model="p.endName" >
<br>
<input type="text" v-model="p.fullName" >
</div>
</template>
<script>
import { reactive,computed } from "vue";
export default {
name: "App",
setup() {
let p = reactive({
startName:"张",
endName:'三'
})
// get 当属性被读取时 触发
// set 当属性被修改时 触发
p.fullName = computed({
get(){
return p.startName + '-' + p.endName
},
set(val){
let res = val.split('-')
p.startName = res[0]
p.endName = res[1]
}
})
return {
p
};
}
};
</script>
<style>
#app {
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
2.watch
-
与Vue2.x中watch配置功能一致
-
两个小“坑”
- 监视reactive定义的响应式数据时:oldValue无法正确获取、强制开启了深度监视(deep配置失效)。
- 监视reactive定义的响应式数据中某个属性时:deep配置有效。
//情况一:监视ref定义的响应式数据 watch(sum,(newValue,oldValue)=>{ console.log('sum变化了',newValue,oldValue) },{immediate:true}) //情况二:监视多个ref定义的响应式数据 watch([sum,msg],(newValue,oldValue)=>{ console.log('sum或msg变化了',newValue,oldValue) }) /* 情况三:监视reactive定义的响应式数据 若watch监视的是reactive定义的响应式数据,则无法正确获得oldValue!! 若watch监视的是reactive定义的响应式数据,则强制开启了深度监视 */ watch(person,(newValue,oldValue)=>{ console.log('person变化了',newValue,oldValue) },{immediate:true,deep:false}) //此处的deep配置不再奏效 //情况四:监视reactive定义的响应式数据中的某个属性 watch(()=>person.job,(newValue,oldValue)=>{ console.log('person的job变化了',newValue,oldValue) },{immediate:true,deep:true}) //情况五:监视reactive定义的响应式数据中的某些属性 watch([()=>person.job,()=>person.name],(newValue,oldValue)=>{ console.log('person的job变化了',newValue,oldValue) },{immediate:true,deep:true}) //特殊情况 watch(()=>person.job,(newValue,oldValue)=>{ console.log('person的job变化了',newValue,oldValue) },{deep:true}) //此处由于监视的是reactive素定义的对象中的某个属性,所以deep配置有效
3.watchEffect函数
-
watch 监听器:既要指明监听的属性,也要指明监视的回调
-
watchEffect的回调是:不用指明监听哪个属性,监视的回调中用到那个属性,那就监听哪个属性
-
watchEffect有点像computed:
- 但是computed更注重的是计算出来的值(回调函数的返回值),所以必须要写返回值
- 而watch更注重的是过程(回调函数的函数体),所以不用写返回值
//watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调。 watchEffect(()=>{ const x1 = sum.value const x2 = person.age console.log('watchEffect配置的回调执行了') })
8.vue3 生命周期
**vue2 ------------------------- vue3**
beforeMount
===>onBeforeMount
mounted
=======>onMounted
beforeUpdate
===>onBeforeUpdate
updated
=======>onUpdated
beforeUnmount
==>onBeforeUnmount
unmounted
=====>onUnmounted
<template>
<h2>当前求和为:{{sum}}</h2>
<button @click="sum++">点我+1</button>
</template>
<script>
import {ref,onBeforeMount,onMounted,onBeforeUpdate,onUpdated,onBeforeUnmount,onUnmounted} from 'vue'
export default {
name: 'Demo',
setup(){
console.log('---setup---')
//数据
let sum = ref(0)
//通过组合式API的形式去使用生命周期钩子
onBeforeMount(()=>{
console.log('---onBeforeMount---')
})
onMounted(()=>{
console.log('---onMounted---')
})
onBeforeUpdate(()=>{
console.log('---onBeforeUpdate---')
})
onUpdated(()=>{
console.log('---onUpdated---')
})
onBeforeUnmount(()=>{
console.log('---onBeforeUnmount---')
})
onUnmounted(()=>{
console.log('---onUnmounted---')
})
//返回一个对象(常用)
return {sum}
}
}
</script>
9.自定义hook函数
-
什么是hook?—— 本质是一个函数,把setup函数中使用的Composition API进行了封装。
-
类似于vue2.x中的mixin。
-
自定义hook的优势: 复用代码, 让setup中的逻辑更清楚易懂。
10.toRef 和 toRefs
1.toRef
-
作用:创一个 ref对象,其 value 值 指向另一个对象中的某个属性
-
语法;
const person = { name:"张三" } const name = toRef(person,'name')
-
应用:要将相应始终的某个属性 单独提供给外部使用时
-
案例
<template> <div> <h1>obj</h1> <hr> <h1>{{person}}</h1> <hr> <h3>{{name}}</h3> <h3>{{sex}}</h3> <h3>{{content.fit.age}}</h3> <h3>{{content.fit.money}}</h3> <button @click="name+=`--`">修改名字</button> <button @click="sex+=`-`">修改性别</button> <button @click="content.fit.age+=1">修改年龄</button> <button @click="content.fit.money+=1">修改年薪</button> </div> </template> <script> import { reactive,toRef,toRefs } from "vue"; export default { name: "App", setup() { let person = reactive({ name:'张三', sex:"男", content:{ fit:{ age:18, money:20 } } }) return { name:toRef(person,'name'), sex:toRef(person,'sex'), age:toRef(person.content.fit,'age'), money:toRef(person.content.fit,'money') }; } }; </script> <style> #app { text-align: center; color: #2c3e50; margin-top: 60px; } </style>
2.toRefs
-
作用:创一个 ref对象,将多个 value 值 指向另一个对象中的多个属性
-
语法:
person = { name:"李晓飞",age:18 } const p = toRefs(person)
-
应用:将多个响应式数据同时提供给外部使用
-
案例
<template> <div> <h1>obj</h1> <hr> <h1>{{person}}</h1> <hr> <h3>{{name}}</h3> <h3>{{sex}}</h3> <h3>{{content.fit.age}}</h3> <h3>{{content.fit.money}}</h3> <button @click="name+=`--`">修改名字</button> <button @click="sex+=`-`">修改性别</button> <button @click="content.fit.age+=1">修改年龄</button> <button @click="content.fit.money+=1">修改年薪</button> </div> </template> <script> import { reactive,toRefs } from "vue"; export default { name: "App", setup() { let person = reactive({ name:'张三', sex:"男", content:{ fit:{ age:18, money:20 } } }) return { person, ...toRefs(person) }; } }; </script> <style> #app { text-align: center; color: #2c3e50; margin-top: 60px; } </style>
三.其它 Composition API
1.shallowReactive 与 shallowRef
- shallowReactive :只处理对象的第一层数据为响应式数据(浅响应式)
- shallowRef : 被包裹的对象 或 基本数据类型,将不再具有响应式的特征
- 什么时候使用:
- 如果一个对象嵌套结构比较深,并且只有最外层的数据变动,使用 ====> shallowReactive
- 如果一个对象,后期将不对其内部的属性进行更改,那马使用 ====> shallowRef
- 案例
<template>
<div>
<h1>{{num.y}}</h1>
<h1>{{num1.y}}</h1>
<button @click="num.y++">num ++ 1</button>
<button @click="num1.y++">num1 ++ 1</button>
<hr>
<h1>{{person}}</h1>
<h3>姓名:{{ name }}</h3>
<h3>年龄:{{ age }}</h3>
<h3>薪资:{{ content.fit.salary }}</h3>
<hr>
<button @click="name+=`--`">修改名字</button>
<button @click="age++">修改年龄</button>
<button @click="content.fit.salary++">修改年薪</button>
</div>
</template>
<script>
import { shallowRef, shallowReactive,toRefs } from 'vue';
export default {
name: "App",
setup() {
// shallowReactive 浅响应式
let person = shallowReactive({
name:"张三",
age:18,
content:{
fit:{
salary:20
}
}
})
// 被 shallowRef 包裹的对象无法实现响应式
let num = shallowRef({
y:0
})
let num1 = shallowRef({
y:0
})
return {
num,
num1,
...toRefs(person)
};
}
};
</script>
<style>
#app {
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
2.readonly 和 shallowReadonly
-
readonly :让一个数据变为只读数据(深只读)
-
shallowReadonly : 让一个多层嵌套的数据变为 浅只读 数据(只有第一层数据只读)
-
应用场景: 不希望数据被修改时。
-
案例
<template> <div> <h1>{{num}}</h1> <button @click="num++">num +1</button> <hr> <h1>{{person}}</h1> <h3>姓名:{{ name }}</h3> <h3>年龄:{{ age }}</h3> <h3>薪资:{{ content.fit.salary }}</h3> <hr> <button @click="name+=`--`">修改名字</button> <button @click="age++">修改年龄</button> <button @click="content.fit.salary++">修改年薪</button> </div> </template> <script> import { readonly,shallowReadonly,toRefs, reactive, ref } from 'vue'; export default { name: "App", setup() { // shallowReactive 浅响应式 let num = ref(0) let person = reactive({ name:"张三", age:18, content:{ fit:{ salary:20 } } }) // 把 person 变为 只读 数据 num = readonly(num) // 把 person 变为 浅读 对象,只有第一层对象的数据只能读,不能修改 person = shallowReadonly(person) return { num, ...toRefs(person) }; } }; </script> <style> #app { text-align: center; color: #2c3e50; margin-top: 60px; } </style>
3.toRaw 与 markRaw
- toRaw
- 作用:将一个由
reactive
生成的响应式对象转为普通对象。 - 使用场景:用于读取响应式对象对应的普通对象,对这个普通对象的所有操作,不会引起页面更新。
- 作用:将一个由
- markRaw
- 作用:标记一个对象,使其永远不会再成为响应式对象。
- 应用场景:
- 有些值不应被设置为响应式的,例如复杂的第三方类库等。
- 当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能。
4.customRef
-
作用:自定义ref , 对其 依赖项 进行 跟踪触发 更新视图
-
案例:
<template> <div> <input v-model="keyWord" type="text"> <br> <h1>{{keyWord}}</h1> </div> </template> <script> import { customRef } from "vue"; export default { name: "App", setup() { function myref(value,delay){ let timer = null return customRef((track,trigger)=>{ return { get(){ console.log( "读取了value值",value ); track() // 追踪 最新的值 return value }, set(newVal){ console.log( "修改后的最新值时",newVal ); clearTimeout(timer) timer = setTimeout(()=>{ value = newVal trigger() // trigger vue通知模板解析 },delay) } } }) } // 自定义 ref let keyWord = myref('hello',500) return { keyWord }; }, }; </script> <style> #app { text-align: center; color: #2c3e50; margin-top: 60px; } body { background-color: pink; } </style>
5.Provide Inject 通信
- 通常,当我们需要从父组件向子组件传递数据时,我们使用 props。想象一下这样的结构:有一些深度嵌套的组件,而深层的子组件只需要父组件的部分内容。在这种情况下,如果仍然将 prop 沿着组件链逐级传递下去,可能会很麻烦。
provide
和inject
。无论组件层次结构有多深,父组件都可以作为其所有子组件的依赖提供者。这个特性有两个部分:父组件有一个provide
选项来提供数据,子组件有一个inject
选项来开始使用这些数据。
案例文件结构
案例效果图
-
祖父组件:
<template> <div id="app"> <h1>这里是根组件</h1> <button @click="sendData">点击---发送数据----修改价格</button> <Child1 /> </div> </template> <script> import Child1 from "./page/child/child1.vue"; import { reactive,provide } from 'vue'; export default { name: "App", components:{ Child1 }, setup() { let car = reactive({ name:"奔驰", price:20 }) provide('car',car) function sendData(){ car.price++ } return { car, sendData }; }, }; </script> <style> #app { color: #2c3e50; background-color: gold; padding: 10px; } </style>
-
子组件
<template> <div class="zu"> <h1>这里是子组件</h1> <Child2/> </div> </template> <script> import Child2 from "./child2.vue"; export default { components:{ Child2 } } </script> <style scoped > .zu{ width: 500px; background-color: pink; padding: 30px; } </style>
-
祖孙组件
<template> <div class="sun"> <h1>这里是孙组件</h1> <h5 v-show="car">车名:{{car.name}}</h5> <h5 v-show="car">加个:{{car.price}}</h5> </div> </template> <script> import { inject, watch } from "vue"; export default { setup(){ let car = inject("car") watch(car,(newVal)=>{ console.log( newVal ); },{deep:true,immediate:true}) return { car } } } </script> <style scoped > .sun{ background-color: skyblue; padding: 30px; } </style>
6.响应式数据的判断
- isRef: 检查一个值是否为一个 ref 对象
- isReactive: 检查一个对象是否是由
reactive
创建的响应式代理 - isReadonly: 检查一个对象是否是由
readonly
创建的只读代理 - isProxy: 检查一个对象是否是由
reactive
或者readonly
方法创建的代理
四、Composition API 的优势
1.Options API 存在的问题
使用传统OptionsAPI中,新增或者修改一个需求,就需要分别在data,methods,computed里修改
2.Composition API 的优势
我们可以更加优雅的组织我们的代码,函数。让相关功能的代码更加有序的组织在一起。
五.新的内置组件
1.Fragment
- 在Vue2中: 组件必须有一个根标签
- 在Vue3中: 组件可以没有根标签, 内部会将多个标签包含在一个Fragment虚拟元素中
- 好处: 减少标签层级, 减小内存占用
2.Teleport
-
什么是Teleport?——
Teleport
是一种能够将我们的组件html结构移动到指定位置的技术。 -
效果图
-
案例结构:
App.vue
<template> <div id="app"> <h1>这里是根组件</h1> <Child1 /> </div> </template> <script> import Child1 from "./page/child-teleport/child1.vue"; export default { name: "App", components:{ Child1 }, setup() { return { }; }, }; </script> <style> #app { color: #2c3e50; background-color: gold; padding: 10px; } </style>
child1
<template> <div class="zu"> <h1>这里是子组件</h1> <Child2/> </div> </template> <script> import Child2 from "./child2.vue"; export default { components:{ Child2 } } </script> <style scoped > .zu{ width: 500px; background-color: pink; padding: 30px; } </style>
child2
<template> <div class="sun"> <h1>这里是孙组件</h1> <button @click="ishow = true">打开弹窗</button> <teleport to="body"> <div v-if="ishow" class="mark"> <div v-if="ishow" class="dialog"> <button @click="ishow = false">关闭弹窗</button> <h1>这里是弹窗</h1> <h3>这里是内容</h3> <h3>这里是内容</h3> <h3>这里是内容</h3> <h3>这里是内容</h3> <h3>这里是内容</h3> </div> </div> </teleport> </div> </template> <script> import { ref } from "@vue/reactivity"; export default { setup() { let ishow = ref(false); return { ishow }; }, }; </script> <style scoped> .sun { background-color: skyblue; padding: 30px; } .dialog { position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%); width: 300px; height: 300px; padding: 20px; background-color: green; color: honeydew; border-radius: 10px; } .mark { position: absolute; top: 0; right: 0; bottom: 0; left: 0; background-color: rgba(0, 0, 0, 0.6); } </style>
六、其他
1.全局API的转移
-
Vue 2.x 有许多全局 API 和配置。
-
例如:注册全局组件、注册全局指令等。
//注册全局组件 Vue.component('MyButton', { data: () => ({ count: 0 }), template: '<button @click="count++">Clicked {{ count }} times.</button>' }) //注册全局指令 Vue.directive('focus', { inserted: el => el.focus() }
-
-
Vue3.0中对这些API做出了调整:
-
将全局的API,即:
Vue.xxx
调整到应用实例(app
)上2.x 全局 API( Vue
)3.x 实例 API ( app
)Vue.config.xxxx app.config.xxxx Vue.config.productionTip 移除 Vue.component app.component Vue.directive app.directive Vue.mixin app.mixin Vue.use app.use Vue.prototype app.config.globalProperties
-
2.其他改变
-
data选项应始终被声明为一个函数。
-
过度类名的更改:
-
Vue2.x写法
.v-enter, .v-leave-to { opacity: 0; } .v-leave, .v-enter-to { opacity: 1; }
-
Vue3.x写法
.v-enter-from, .v-leave-to { opacity: 0; } .v-leave-from, .v-enter-to { opacity: 1; }
-
-
移除keyCode作为 v-on 的修饰符,同时也不再支持
config.keyCodes
-
移除
v-on.native
修饰符-
父组件中绑定事件
<my-component v-on:close="handleComponentEvent" v-on:click="handleNativeClickEvent" />
-
子组件中声明自定义事件
<script> export default { emits: ['close'] } </script>
-
-
移除过滤器(filter)
过滤器虽然这看起来很方便,但它需要一个自定义语法,打破大括号内表达式是 “只是 JavaScript” 的假设,这不仅有学习成本,而且有实现成本!建议用方法调用或计算属性去替换过滤器。
-
…
更多推荐
所有评论(0)