Vue 3.0 于 2020-09-18 发布了,使用了 Typescript 进行了大规模的重构,带来了 Composition API RFC 版本,类似 React Hook 一样的写 Vue,可以自定义自己的 hook ,让使用者更加的灵活。

为什么推出3.0?

  • 对 TypeScript 支持不友好(所有属性都放在了 this 对象上,难以推倒组件的数据类型)
  • 大量的 API 挂载在 Vue 对象的原型上,难以实现 TreeShaking
    • TreeShaking:当我引入一个模块的时候,我不引入这个模块的所有代码,我只引入我需要的代码
  • 架构层面对跨平台 dom 渲染开发支持不友好
  • CompositionAPI。受 ReactHook 启发
  • 更方便的支持了 jsx
  • Vue 3 的 Template 支持多个根标签,Vue 2 不支持
  • 对虚拟 DOM 进行了重写、对模板的编译进行了优化操作

一、setup

为我们使用 vue3 的 Composition API 新特性提供了统一的入口, 有些文章说setup 函数会在 beforeCreate 之后、created 之前执行但实践证明这个说法不正确如下图打印顺序, vue3 也是取消了这两个钩子,统一用 setup 代替, 该函数相当于一个生命周期函数,vue 中过去的 data,methods,watch 等全部都用对应的新增 api 写在 setup()函数中。

1、setup参数

  1. props: 组件传入的属性
  2. context:attrs,emit,slots

props

  setup中接受的props是响应式的, 当传入新的props 时,会及时被更新。由于是响应式的, 所以不可以使用ES6解构,解构会消除它的响应式。需要结构可以用toRefs()

context

  setup中不能访问Vue2中最常用的this对象,所以context中就提供了this中最常用的三个属性:attrsslot 和emit,分别对应Vue2.x中的 $attr属性、slot插槽 和$emit发射事件。

简单用法

2、reactive、ref与toRefs

在vue2.x中, 定义数据都是在data中, 但是Vue3.x 可以使用reactiveref来进行数据定义。

区别

  reactive用于处理对象的双向绑定,ref则处理js基础类型的双向绑定,reactive不能代理基本类型,例如字符串、数字、boolean等。

简单用法

<template>
<div>
<span>{{ year }}</span
><span>{{ user.name }}</span
><span>{{ user.label }}</span>
</div>
</template> <script>
import { reactive, ref } from "vue";
export default {
props: {
data: {
type: Object,
default: {
id: 1,
name: "匹配",
},
},
},
components: {}, setup(props, con) {
const year = ref(10);
const user = reactive({
name: "夏利",
label: "",
});
  //这里ref取值需要加value
if (year.value > 5) {
user.label = "牛逼";
} else {
user.label = "一般";
}
return {
year,
user,
};
},
};
</script>

  不能直接对user进行结构, 这样会消除它的响应式, 这里就和上面我们说props不能使用ES6直接解构就呼应上了。那我们就想使用解构后的数据怎么办,解决办法就是使用toRefs

   return {
year,
// 使用reRefs
...toRefs(user)
}

3、生命周期

  我们可以看到beforeCreatecreatedsetup替换了(但是Vue3中你仍然可以使用, 因为Vue3是向下兼容的, 也就是你实际使用的是vue2的)。其次,钩子命名都增加了on; Vue3.x还新增用于调试的钩子函数onRenderTriggeredonRenderTricked

<script>
import {
defineComponent,
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted,
onErrorCaptured,
onRenderTracked,
onRenderTriggered,
} from "vue"; export default defineComponent({
// beforeCreate和created是vue2的
beforeCreate() {
console.log("------beforeCreate-----");
},
created() {
console.log("------created-----");
},
setup() {
console.log("------setup-----"); // vue3.x生命周期写在setup中
onBeforeMount(() => {
console.log("------onBeforeMount-----");
});
onMounted(() => {
console.log("------onMounted-----");
});
// 调试哪些数据发生了变化
onRenderTriggered((event) => {
console.log("------onRenderTriggered-----", event);
});
},
});
</script>

4、全局定义属性 globalProperties

  在项目中往往会全局定义公共属性或方法,方便我们组件间调用。

import { createApp } from 'vue'
import App from './App.vue'
import utils from './utils' // vue2.0写法
let vue=new Vue()
vue.prototype.utils=utils
// vue3.0写法
const app=createApp(App)
app.config.globalProperties.utils=utils

app.mount('#app')

vue3.0中使用全局定义的属性

<script>

import { getCurrentInstance } from "vue";

export default {
components: {},
setup(props, con) {

const { ctx } = getCurrentInstance();
console.log(ctx.utils);

},
};
</script>

5、use与plugin

定义一个组件

通过use引入

6、readonly 只读属性

在使用readonly后重新进行复制是不允许修改的,这个api不常用

7、computed计算api

这里引入了proxy内的类似写法,有了set与get的内容写法,该函数用来创造计算属性,和过去一样,它返回的值是一个 ref 对象。里面可以传方法,或者一个对象,对象中包含 set()、get()方法。

7.1 创建只读的计算属性

<template>
<div>
<p>refCount: {{refCount}}</p>
<p>计算属性的值computedCount : {{computedCount}}</p>
<button @click="refCount++">refCount + 1</button>
</div>
</template> <script>
import { computed, ref } from '@vue/composition-api'
export default {
setup() {
const refCount = ref(1)
// 只读
let computedCount = computed(() => refCount.value + 1) //2
console.log(computedCount)
return {
refCount,
computedCount
}
}
};
</script>

7.2 通过 set()、get()方法创建一个可读可写的计算属性

<template>
<div>
<p>refCount: {{refCount}}</p>
<p>计算属性的值computedCount : {{computedCount}}</p>
<button @click="refCount++">refCount + 1</button>
</div>
</template> <script>
import { computed, ref } from '@vue/composition-api'
export default {
setup() {
const refCount = ref(1)
// 可读可写
let computedCount = computed({
// 取值函数
get: () => refCount.value + 1,
// 赋值函数
set: val => {
refCount.value = refCount.value -5
}
})
  //触发get函数
console.log(computedCount.value)

// 为计算属性赋值的操作,会触发 set 函数
computedCount.value = 10
console.log(computedCount.value)
// 触发 set 函数后,count 的值会被更新
console.log(refCount.value)

return {
refCount,
computedCount
}
}
};
</script>

8、watch与watchEffect

8.1watch

  watch 函数用来侦听特定的数据源,并在回调函数中执行副作用。默认情况是惰性的,也就是说仅在侦听的源数据变更时才执行回调。

    *   1、需要一个明确的数据资源
         *   2、需要有一个回调函数
         *   3、等到改变才会执行函数
<script>
import { ref, watch } from "vue";
export default {
components: {},
setup(props, con) {
const count = ref(0);
const name = ref("iuuggu");
setTimeout(() => {
(count.value = 1), (name.value = "这一行山");
}, 200);
watch(
() => {
/*
* 1、需要一个明确的数据资源
* 2、需要有一个回调函数
* 3、等到改变才会执行函数
*
*/
return count.value;
},
() => {}
);
// 4、ref简写 ,reactive不可以
watch(count, () => {});
// 5、监听多个
watch(
() => {
return [count, name];
},
([newv, oldv], [newv, oldv]) => {}
);
// 6、onTrack,onTrigger
watch(
() => {
return [count, name];
},
([newv, oldv], [newv, oldv]) => {},
{
onTrack(e) {},
onTrigger(e) {},
}
);
},
};
</script>

8.1.1 监听数据源

reactive

setup(props, context) {
const state = reactive<Person>({ name: 'vue', age: 10 }) watch(
() => state.age,
(age, preAge) => {
console.log(age); // 100
console.log(preAge); // 10
}
)
// 修改age 时会触发watch 的回调, 打印变更前后的值
state.age = 100
return {
...toRefs(state)
}
}

ref

setup(props, context) {
const age = ref<number>(10); watch(age, () => console.log(age.value)); // 100 // 修改age 时会触发watch 的回调, 打印变更后的值
age.value = 100
return {
age
}
}

8.1.2监听多个

setup(props, context) {
const state = reactive<Person>({ name: 'vue', age: 10 }) watch(
[
      () => state.age,
      () => state.name
    ],
([newName, newAge], [oldName, oldAge]) => {
console.log(newName);
console.log(newAge); console.log(oldName);
console.log(oldAge);
}
)
// 修改age 时会触发watch 的回调, 打印变更前后的值, 此时需要注意, 更改其中一个值, 都会执行watch的回调
state.age = 100
state.name = 'vue3'
return {
...toRefs(state)
}
}

8.1.3stop 停止监听

在 setup() 函数内创建的 watch 监视,会在当前组件被销毁的时候自动停止。如果想要明确地停止某个监视,可以调用 watch() 函数的返回值即可,语法如下:

setup(props, context) {
const state = reactive<Person>({ name: 'vue', age: 10 }) const stop = watch(
[() => state.age, () => state.name],
([newName, newAge], [oldName, oldAge]) => {
console.log(newName);
console.log(newAge); console.log(oldName);
console.log(oldAge);
}
)
// 修改age 时会触发watch 的回调, 打印变更前后的值, 此时需要注意, 更改其中一个值, 都会执行watch的回调
state.age = 100
state.name = 'vue3' setTimeout(()=> {
stop()
// 此时修改时, 不会触发watch 回调
state.age = 1000
state.name = 'vue3-'
}, 1000) // 1秒之后讲取消watch的监听 return {
...toRefs(state)
}
}

8.2 watchEffect

 该函数有点像update函数,但他执行在update与beforeuodate之前。

       *    1、首次加载会立即执行
* 2、响应的最终所有依赖监听变化(数据改变)
* 3、在卸载onUnmounte时自动停止
* 4、执行stop就会停止监听,否则一直监听
* 5、异步函数先执行再去监听改变
<script>
import { watchEffect, ref, onMounted } from "vue";
export default {
components: {},
//con==context(attrs,emit,slots)
setup(props, con) {
const count = ref(0);
setTimeout(() => {
count.value = 1;
}, 2000);
const stop = watchEffect(
() => {
/*
* 1、首次加载会立即执行
* 2、响应的最终所有依赖监听变化(数据改变)
* 3、在卸载onUnmounte时自动停止
* 4、执行stop就会停止监听,否则一直监听
* 5、异步函数先执行再去监听改变
*/
},
{
// 6、在update之后执行
flush: "post",
// 同步执行
flush: "async",
}
);
setTimeout(() => {
stop();
}, 4000); // 7、组件挂在ref
const myRef = ref(null);
// 避免监听时先见听到null 在监听到h1
onMounted(() => {
watchEffect(() => {
console.log(myRef.value);
});
});
// 8、debugging 开发模式使用
watchEffect(
() => {
console.log(count.value);
},
{
onTrack(e) {
// 监听到count和改变count
},
onTrigger(e) {
// count改变了会触发
},
}
);
return {
myRef,
count,
};
},
};
</script>

9、ref,torefs,isref,unref

9.1ref

ref() 函数用来根据给定的值创建一个响应式的数据对象,ref() 函数调用的返回值是一个对象,这个对象上只包含一个 .value 属性:

ref数据

<template>
<div class="mine">
{{count}} // 10
</div>
</template> <script >
import {ref } from 'vue';
export default {
setup() {
const count = ref(10)
// 在js 中获取ref 中定义的值, 需要通过value属性
console.log(count.value);
return {
count
}
}
}
</script>

ref 访问dom

在 reactive 对象中访问 ref 创建的响应式数据

当把 ref() 创建出来的响应式数据对象,挂载到 reactive() 上时,会自动把响应式数据对象展开为原始的值,不需通过 .value 就可以直接被访问,例如:

<template>
<div class="mine">
{{count}} -{{t}} // 10 -100
</div>
</template> <script >
import reactive, ref, toRefs } from 'vue';
export default {
setup() {
const count = ref(10)
const obj = reactive({
t: 100,
count
})
// 通过reactive 来获取ref 的值时,不需要使用.value属性
console.log(obj.count);
return {
...toRefs(obj)
}
}
}
</script>

9.2 toRefs() 函数

toRefs() 函数可以将 reactive() 创建出来的响应式对象,转换为普通的对象,只不过,这个对象上的每个属性节点,都是 ref() 类型的响应式数据

<template>
<div>
<p>{{ count }} - {{ name }}</p>
<button @click="count += 1">+1</button>
<button @click="add">+1</button>
</div>
</template> <script>
import { reactive, toRefs } from "@vue/composition-api";
export default {
setup() {
// 响应式数据
const state = reactive({ count: 0, name: "zs" });
// 方法
const add = () => {
state.count += 1;
};
return {
// 非响应式数据
// ...state,
// 响应式数据
...toRefs(state),
add
};
}
};
</script>

9.3 isref

isRef() 用来判断某个值是否为 ref() 创建出来的对象

 setup(props, context) {
const name: string = 'vue'
const age = ref(18)
console.log(isRef(age)); // true
console.log(isRef(name)); // false return {
age,
name
}
}

9.4 unref

unRef() 用来判断某个值是否为 ref() 创建出来的对象有抛出该对象

 setup(props, context) {
const name: string = 'vue'
const age = ref(18)
console.log(unRef(age)); // 18
console.log(unRef(name)); // vue return {
age,
name
}
}

vue3.0API详解的更多相关文章

  1. Vue3 setup详解

    setup执行的时机 在beforeCreate之前执行(一次),此时组件对象还没创建: this是undefined,不能通过this来访问data/computed/methods/props: ...

  2. Linq之旅:Linq入门详解(Linq to Objects)

    示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...

  3. 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)

    一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...

  4. EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解

    前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...

  5. Java 字符串格式化详解

    Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...

  6. Android Notification 详解(一)——基本操作

    Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...

  7. Android Notification 详解——基本操作

    Android Notification 详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 前几天项目中有用到 Android 通知相关的内容,索性把 Android Notificatio ...

  8. Git初探--笔记整理和Git命令详解

    几个重要的概念 首先先明确几个概念: WorkPlace : 工作区 Index: 暂存区 Repository: 本地仓库/版本库 Remote: 远程仓库 当在Remote(如Github)上面c ...

  9. Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)

    Android XML shape 标签使用详解   一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...

随机推荐

  1. Linux入门视频笔记三(常用工具集)

    一.全局变量(Linux中的全局变量指在整个系统中都能用的变量) 1.USER:当前登录系统的用户的用户名 2.HOME:当前用户的主目录 cd $HOME 或 cd ~可以进入用户主目录 3.PAT ...

  2. linux程序开机自动启动

    linux如果需要实现开机启动, 可以找到 $HOME/.config/autostart 目录(没有的话新建一个),在该文件夹下创建一个空文件,文件名自拟,后缀必须是desktop,如:dingda ...

  3. Java 读取Word文本/段落格式属性

    本文介绍通过Java后端程序代码来读取Word文本和段落格式的方法. 本次测试环境如下: Word版本:2013 编译环境:IntelliJ IDEA2018 Work库:free spire.doc ...

  4. 使用ffmpeg 操作音频文件前后部分静音移除.

    指令特别简单, 但是却琢磨了一下午. 总结看文档时要细心, 主要ffmpeg的版本要 8.2.1 以上 ffmpeg -i in.mp3 -af silenceremove=start_periods ...

  5. Java生鲜电商平台-API接口设计之token、timestamp、sign 具体设计与实现

    转载:https://www.cnblogs.com/jurendage/p/12653865.html 说明:在实际的业务中,难免会跟第三方系统进行数据的交互与传递,那么如何保证数据在传输过程中的安 ...

  6. Leedcode算法专题训练(数组与矩阵)

    1. 把数组中的 0 移到末尾 283. Move Zeroes (Easy) Leetcode / 力扣 class Solution { public void moveZeroes(int[] ...

  7. JVM(一)内存结构

    今日开篇 什么是JVM 定义 Java Virtual Machine,JAVA程序的运行环境(JAVA二进制字节码的运行环境) 好处 一次编写,到处运行 自动内存管理,垃圾回收机制 数组下标越界检查 ...

  8. 【macOS】屏蔽Big Sur更新提示 消除更新红点

    下面介绍如何屏蔽macOS系统更新,屏蔽Big Sur更新提示,消除更新红点. 取消自动更新选项 请选取苹果菜单  > "系统偏好设置",然后点按"软件更新&qu ...

  9. Spring Security框架中踢人下线技术探索

    1.背景 在某次项目的开发中,使用到了Spring Security权限框架进行后端权限开发的权限校验,底层集成Spring Session组件,非常方便的集成Redis进行分布式Session的会话 ...

  10. Selenium 3 常用 API

    元素定位 获取页面元素属性 元素判断 元素操作 操作输入框/单击 双击 下拉框操作 键盘操作 鼠标操作 单选框操作 多选框操作 拖动窗口 操作 JS 框 切换 frame 使用 JS 操作页面对象 操 ...