- 重构响应式系统,使用
Proxy
替换Object.defineProperty
,使用Proxy
优势: - 可直接监听数组类型的数据变化
- 监听的目标为对象本身,不需要像
Object.defineProperty
一样遍历每个属性,有一定的性能提升 - 可拦截
apply
、ownKeys
、has
等13种方法,而Object.defineProperty
不行 - 直接实现对象属性的新增/删除
- 新增 Composition API,更好的逻辑复用和代码组织
- 重构 Virtual DOM
- 模板编译时的优化,将一些静态节点编译成常量
-
slot
优化,将slot
编译为lazy
函数,将slot
的渲染的决定权交给子组件 - 模板中内联事件的提取并重用(原本每次渲染都重新生成内联函数)
- 代码结构调整,更便于
Tree shaking
,使得体积更小 - 使用
Typescript
替换Flow
使用 Composition API
- setup
export default {
props: {
str: String
},
setup(props, context) {
console.log(props) // str
console.log(context) // attrs, slots, parent, root, emit, refs
},
}
- relative
import { reactive } from 'vue'
export default {
setup() {
const state = reactive({count: 0}) // 创建响应式数据对象
return state //将响应式数据对象 return 出去,供 template 使用
}
}
- ref
ref() 函数根据给定的值创建一个响应式的数据对象,返回值是一个对象,这个对象上只包含一个 .value 属性
import { ref } from 'vue'
export default {
setup() {
const count = ref(0) // 创建响应式数据对象 count,初始值为 0
console.log(count.value) // 在setup内访问count值需要.value 属性才可以,但在template中可以直接访问
return {
count
}
},
}
- toRefs
toRefs() 函数可以将 reactive() 创建出来的响应式对象,转换为普通的对象,只不过,这个对象上的每个属性节点,都是 ref() 类型的响应式数据
import { reactive, toRefs } from 'vue'
export default {
setup() {
const state = reactive({count: 0, name:'weedsFly'}) // 用reactive集中创建多个响应式对象
const add = () => { // methods写在setup内
state.count++
}
return {
// ...state, // 使用展开运算符后 用reactive创建的响应式数据 变成了 固定的值
...toRefs(state), // 可以用toRefs函数 将传进来的非响应式对象 转成 ref() 类型的响应式数据
add
}
},
}
- watch
- 监视单个数据源变动
监视单个 reactive 创建的数据源
import { reactive, watch } from 'vue'
export default {
setup() {
const state = reactive({count: 100})
watch(
() => state.count,
(newVal, oldVal) => { console.log(newVal, oldVal)},
{lazy: true} // 在 watch 被创建的时候,不执行回调函数中的代码
)
setTimeout(() => {
state.count++
}, 1500)
}
}
监视单个 ref 创建的数据源
import { ref, watch } from 'vue'
export default {
setup() {
const count = ref(100)
watch(
count,
(newVal, oldVal) => { console.log(newVal, oldVal)},
{lazy: true} // 在 watch 被创建的时候,不执行回调函数中的代码
)
setTimeout(() => {
count++
}, 1500)
}
}
- 监视多个数据源
监视多个 reactive 创建的数据源
import { reactive, watch } from 'vue'
export default {
setup() {
const state = reactive({count: 100, name: 'Laiyj'})
watch(
[() => state.count, () => state.name],
([newCount, newName], [oldCount, oldName]) => {
console.log(newCount, oldCount)
console.log(newName, oldName)
},
{lazy: true} // 在 watch 被创建的时候,不执行回调函数中的代码
)
setTimeout(() => {
state.count++
state.name = 'Lucy'
}, 1000)
}
}
监视多个 ref 创建的数据源
import { ref, watch } from 'vue'
export default {
setup() {
const count = ref(100)
const name = ref('Laiyj')
watch(
[count, name],
([newCount, newName], [oldCount, oldName]) => {
console.log(newCount, oldCount)
console.log(newName, oldName)
},
{lazy: true} // 在 watch 被创建的时候,不执行回调函数中的代码
)
setTimeout(() => {
count++
name = 'Lucy'
}, 1000)
}
}
- 清除watch监视
import { ref, watch } from 'vue'
export default {
setup() {
const count = ref(100)
const stop = watch( // 创建监视,并得到 停止函数
count,
(newVal, oldVal) => {
console.log('I am watching.')
console.log(newVal, oldVal)
},
{lazy: true} // 在 watch 被创建的时候,不执行回调函数中的代码
)
setTimeout(() => {
count++
}, 1000)
const clearWatch = () => {
stop()
}
return {
count,
clearWatch
}
}
}
- 在 watch 中清除无效的异步任务(与节流防抖同效)
import { ref, watch } from 'vue'
export default {
setup() {
const keyword = ref('')
const asyncPrint = (val) => { // 执行异步任务,并得到关闭异步任务的 timerId
return setTimeout(() => {
console.log(val)
}, 1000)
}
watch(
keyword,
(newVal, oldVal, onClean) => {
const timeId = asyncPrint()
onClean(() => {clearTimeout(timeId)}) // 如果 watch 监听被重复执行了,则会先清除上次未完成的异步任务
}
)
return {
keyword
}
}
}
- provide & inject
provide() 和 inject() 可以实现嵌套组件之间的数据传递。
这两个函数只能在 setup() 函数中使用。
父级组件中使用 provide() 函数向下传递数据;子级组件中使用 inject() 获取上层传递过来的数据。
网友评论