vue3.0学习笔记
一、复习vue 2中的一些特性
- 动态参数 :
- 防抖和节流:
- 混入
- 实用新功能:
- 位于根目录中,可以指定项目的目标浏览器范围
- 对于vue2来说,vue3主要添加和改进,并无重大更改
- vue3源代码是用typescript写的
二、v3.0新特性
- reactive() 接收一个对象,返回一个响应式对象
将 vue2中只需要在data() 中定义数据变成 vue3中需要用reactive函数或ref来创建响应式数据
1)用reactive创建响应式对象// 在组件库中引入 reactive import { reactive } from '@vue/composition-api'
setup() {
// 创建响应式对象
const state = reactive({
count:0
});
// 将响应式对象return出去,暴露给模板使用
return state;
}
2)使用响应式对象
<p>当前的count的值为:{{count}}</p>
<button @click=“count++”>点击增加count<button>
- ref() 根据给定的值 创建 一个响应式对象,返回值是一个对象,且只包含一个.value属性
1)用ref 创建响应式对象// 引入 ref import { ref } from '@vue/composition-api'
-
setup() {
// 创建响应式对象
const count = ref(0);return { count }
}
reactive() 和 ref() 创建出来的响应式对象的区别:
用 reactive() 创建的响应式对象,整个对象是响应式的,但对象里的值不是。
而用 ref() 创建的响应式的值,本身就是响应式的,并不依赖于其他对象。2) 使用响应式对象
<p>当前的count的值为:{{count}}</p>
<button @click=“count++”>点击增加count</button>
3)ref注意事项
在setup()函数中,ref()创建的响应式数据返回的是对象,需要 用.value来访问,而在setup()函数外部则不需要
可以在reactive对象中访问ref()函数创建的响应式数据
新的ref()会覆盖旧的ref() - computed() 只读计算属 性,返回一个ref()实例
const count = ref(1)
-
// 创建一个计算属性,使其值比 count 大 1
const bigCount = computed(() => count.value + 1)console.log(bigCount.value) // 输出 2
bigCount.value++ // error 不可写const count = ref(1)
// 创建一个 computed 计算属性,传入一个对象
const bigCount = computed({
// 取值函数
get: () => (count.value + 1),
// 赋值函数
set: val => {
count.value = val - 1
}
})// 给计算属性赋值的操作,会触发 set 函数
bigCount.value = 9
// 触发 set 函数后,count 的值会被更新
console.log(count.value) // 8 - readonly() 返回一个只读的对象代理
const state = reactive({ count: 0 })
-
const copy = readonly(state)
watchEffect(() => {
// 依赖追踪
console.log(copy.count)
})// state 上的修改会触发 copy 上的侦听
state.count++// 这里只读属性不能被修改
copy.count++ // warning! - watchEffect() 初次渲染执行,在传入的函数依赖变更时重新运行
//基本用法 : const count = ref(0)
-
// 初次直接执行,打印出 0
watchEffect(() => console.log(count.value))setTimeout(() => {
// 被侦听的数据发生变化,触发函数打印出 1
count.value++
}, 1000)
/*****************************************************************************/
const stop = watchEffect(() => {
/* … */
})// 停止侦听
stop() - watch 与vue2基本一样
与watchEffect不同:
1)初次渲染不执行
2)侦听更具体
3)可以访问侦听变化前后的值
侦听单个数据源:// 侦听一个 getter const state = reactive({ count: 0 }) watch( () => state.count, (count, prevCount) => { /* ... */ } )
-
// 直接侦听一个 ref
const count = ref(0)
watch(count, (count, prevCount) => {
/* … */
})watch([ref1, ref2], ([newRef1, newRef2], [prevRef1, prevRef2]) => { /* ... */ })
composition-API 依赖工具
- isRef() 判断某个值是否为ref()创建 出来的响应式的值
import { isRef } from '@vue/composition-api'
const unwrapper = isRef(foo) ? foo.value : foo
- isRef() 判断某个值是否为ref()创建 出来的响应式的值
- toRefs() 可以将 reactive()创建出来的响应式对象转换成内容为ref响应式的值的普通对象,当你需要展开 reactive()时,希望它的值也是响应式的就会用到它。
import { toRefs } from '@vue/composition-api'
-
setup() {
// 定义响应式数据对象
const state = reactive({
count: 0
})// 定义简单的函数,使count每次+1 const add = () => { state.count++ } // 将setup函数的内容return出去,供外界使用 return { // 将 state 展开导出,同时将其属性都转化为 ref 形式的响应式数据 ...toRefs(state), add }
}
<template> <div> <p>当前的count值为:{{count}}</p> <button @click="add">点击+1</button> </div> </template>
4. Fragments, 不再限制只有一个template根节点, render函数 也可以返回数据,有点像React。Fragments。5. 支持Typescript。6. Custom Renderer API 实现用DOM方式进行WebGL编程,也就是说可以在canvas上渲染了。详情:https://blog.csdn.net/liubangbo/article/details/114079301三、vue3.0体验
初始化项目1. 使用脚手架创建 项目vue create my-Project
2. 安装 composition-apinpm i @vue/composition-api -s
3. 使用插件//main.js import Vue from 'vue' import VueCompositionAPI from '@vue/composition-api‘
Vue.use(VueCompositionAPI )
四、Setup 函数
专门为组件提供的新属性, 为基于 Composition API 的新特性提供了统一入口methods、watch 、computed、data 的数据都会放在setup()函数中1. 执行时机beforeCreate >stepup>created2. 接口props数据props是setup()的一个形参,组件接收的数据可以在setup函数内访问到3. context 上下文对象context是setup()的第二个形参,它是一个上下文对象,可以通过context来访问Vue实例的thissetup(props, context){ // 查看或使用props中的参数 // 查看或使用context }
get 拦截-
在 vue2 中,
computed
、watch
、render
函数都会封装成一个watcher
对象,这个watcher
对象可以储存收集到的依赖,也可以触发收集到的依赖。vue3 中取消watcher
这个概念,变为effect
,依赖通过全局的weakMap
进行储存。
-
依赖储存在一个全局变量
weakMap
中(上面源码中的targetMap
),key 是proxy
代理的对象,value 是一个新的map
,我们称为 map2 , map2 的 key 是我们读取的属性值,value 是被此属性收集到的所有依赖,是个set
对象。为什么依赖用weakMap
储存,其实是为了性能优化,假设我们监听的对象被我们手动的销毁掉,因为weakMap
对对象的引用都是弱引用,所以对象和他的依赖占用的内存都会被自动清除。
-
在
proxy
的get
劫持中,我们将收集到的依赖储存到全局的weakMap
中,为了性能优化,只有触发get
且属性值为 object 类型,才会继续的递归进行数据的监听。总结(摘抄).
- 事实上分析到现在来说,vue3 并没有什么太大变化,远不及 react 15 和 16 的变化。
- 新 api proxy 毫无疑问更加强大,那么可以说 vue 彻底放弃低版本 ie 的兼容。
- 新 diff 算法虽然速度快一点,但是多了最长递归子序列需要的空间。那么最终新 diff 带来的价值我个人感觉未必有那么大。
- 块优化,典型的空间复杂度换时间复杂度,且严重依赖于模板解析。可是在复杂应用中基本都要靠 jsx/render 函数来替代模板。那么对于复杂应用来说是不是浪费了一大波空间,但是时间复杂度倒没有发生改善。
- ref 包装一层 value 的结构,会不会当时间久了,或者数据传递层级多了。你都分不清 value 是因为数据自身本来就有 vue 还是因为 ref 包装的 value。
-
ts 更加完美支持是好事,之前 vue2 出现类型推导断层确实是难受,vue3 算是用函数的方式完美支持了 ts,但是模板里面的 ts 推导怎么处理,目前还不确定,这个应该
vetur
、vue
团队一起发力。
感想如下:
- 将 computed,data,生命周期全部放到 setup 函数里面。ts 对函数的类型推导已经很完美,也不需要考虑如何弥补逻辑断层从而挂载在 this 上。render 函数里面直接传递 methods 等值,感觉 新语法+tsx 很完美。
- 类 hooks 语法,逻辑复用的粒度更细,也解决了命名冲突,额外组件实例等问题。
- 看解释说 createComponent 内部实现是个 noop(直接返回参数本身)。这个作用是给 TSX 和 Vetur 的模版自动补全。
- 之前 options base 的时候,data,methods,watch 等等都清晰的分开,现在全部放在 setup,会不会很乱?
- 新api proxy毫无疑问更加强大,那么可以说vue彻底放弃低版本ie的兼容。
- 新diff算法虽然速度快一点,但是多了最长递归子序列需要的空间。那么最终新diff带来的价值我个人感觉未必有那么大。
- 块优化,典型的空间复杂度换时间复杂度。但是毕竟严重依赖于模板解析。但是在复杂应用中基本都要靠jsx表达式来替代模板。那么对于复杂应用来说是不是浪费了一大波空间,但是时间复杂度倒没有发生改善。
- ref包装一层value的结构,会不会当时间久了,或者数据传递层级多了。你都分不清value是因为数据自身本来就有vue还是因为ref。
-
在 vue2 中,