![](/assets/images/pic09.jpg)
No more than code.
// 安装
npm install -g @vue/cli
$ vue -V
@vue/cli 4.3.1
// 创建项目
vue create vue-next-test
// 下载插件
vue add vue-next
// 运行
npm run serve
编译模板的优化
模板渲染生成 PatchFlag(>0的number) 标记,仅带有 PatchFlag 标记的节点会被真正追踪,且无论层级嵌套多深,它的动态节点都直接与 Block 根节点绑定,无需再去遍历静态节点。模板编译网站
// PatchFlag 枚举定义,源码:`packages/shared/src/patchFlags.ts`
export const PatchFlagNames = {
[PatchFlags.TEXT]: `TEXT`,
[PatchFlags.CLASS]: `CLASS`,
[PatchFlags.STYLE]: `STYLE`,
[PatchFlags.PROPS]: `PROPS`,
[PatchFlags.FULL_PROPS]: `FULL_PROPS`,
[PatchFlags.HYDRATE_EVENTS]: `HYDRATE_EVENTS`,
[PatchFlags.STABLE_FRAGMENT]: `STABLE_FRAGMENT`,
[PatchFlags.KEYED_FRAGMENT]: `KEYED_FRAGMENT`,
[PatchFlags.UNKEYED_FRAGMENT]: `UNKEYED_FRAGMENT`,
[PatchFlags.DYNAMIC_SLOTS]: `DYNAMIC_SLOTS`,
[PatchFlags.NEED_PATCH]: `NEED_PATCH`,
[PatchFlags.HOISTED]: `HOISTED`,
[PatchFlags.BAIL]: `BAIL`
}
混入(mixin) 将不再作为推荐使用, Composition API可以实现更灵活且无副作用的复用代码。文档参考
Composition API 包含了六个主要API
<template>
<div class='Test'>
<h1>test count: 8</h1>
<div>count * 2 = </div>
<div>state from vuex </div>
<button @click="add">add</button>
<button @click="update">update a</button>
<HelloWorld msg="Hello word"></HelloWorld>
</div>
</template>
<script>
import { ref, toRefs, computed, watch, getCurrentInstance, reactive, watchEffect, watch } from 'vue'
export default {
name: 'Test',
props: {
msg: String
},
/**
* 1.调用时间:在 props 初始化后,beforeCreate 执行之前
* 2.ref 接受一个参数值并返回一个响应式且可改变的 ref 对象。ref 对象拥有一个指向内部值的单一属性 .value。在 setup 中使用时需要`.value`,在模板中使用不需要`.value`,例如:count
* 3.setup 可以返回一个对象,也可以返回一个 render function
* 4.setup 中 this 不能获取 vue 实例
* 5.computed:传入一个 getter 函数,返回一个默认不可手动修改的 ref 对象
*/
setup(props, context) {
/**
* 1. 函数中接收 props 作为第一个参数,使用 watchEffect or watch 可以监听 props 的改变,注意:若参数使用解构赋值形式(setup({msg}){})则监* 听不到数据改变
* 2. 接收对象 context 作为第二个参数,可使用解构赋值形式(setup(props,{attrs,slots,emit}){})
*/
watchEffect(() => { console.log(`name is: ` + props.msg)}) // 响应,msg 改变即执行
watch(() => { console.log(`name2 is: ` + props.msg)}) // 响应,msg 改变即执行
console.log(`name3 is: ` + props.msg) // 非响应,只执行一次
/** 状态: */
const count = ref(0)
/** 事件绑定 */
const add = () => { count.value++ }
/** 计算属性 */
const doubleCount = computed(() => count.value * 2)
console.log("setup -> doubleCount", doubleCount)
/** 获取当前组件的实例 ctx */
const { ctx } = getCurrentInstance()
console.log("组件实例 -> ", ctx)
/** 获取路由 */
console.log("路由 -> ", ctx.$router.currentRoute.value)
/** 通过计算属性来引用 Vuex 中的状态 */
const a = computed(() => { return ctx.$store.state.test.a })
/** 更新 Vuex 状态 */
const update = () => { ctx.$store.commit('setTestA', count) }
/** reactive 设置对象可响应 */
const object = reactive({ foo: 'bar' }) // 数据发生改变触发相应更新
// const object = { foo: 'bar' } // 数据发生改变,视图不会相应更新
const updateobject = () => { object.foo = "ss" }
/** ref */
const state = reactive({ count })
console.log("setup -> state", state)
const arr = reactive([ref(0)])
// need .value here
console.log("setup -> arr", arr[0].value)
const map = reactive(new Map([ ['foo', ref(0)] ]))
// need .value here
console.log("setup -> map", map.get('foo').value)
/** computed 计算属性 */
// const plusOne = computed(() => count.value + 1)
// plusOne.value++ // error
/** with get and set functions to create a writable ref object */
const plusOne = computed({
get: () => count.value + 1,
set: val => { count.value = val - 1 }
})
plusOne.value = 5
console.log("setup -> plusOne", plusOne.value)
/** readonly 只读 */
const original = reactive({ count: 0 })
const copy = readonly(original)
watchEffect(() => { console.log("setup -> copy.count", copy.count) })
original.count++ // mutating original will trigger watchers relying on the copy
copy.count++ // mutating the copy will fail and result in a warning
/**
* watchEffect
* 1. 组件卸载自动停止
* 2. 调用返回值 stop,停止监听
*/
const stop = watchEffect(() => console.log("watchEffect ->", count.value))
stop()
/** 异步请求数据 */
// const data = ref(null)
// watchEffect(async () => { data.value = await fetchData(props.id) })
/**
* watch
* 1参-监听的值
* 2参-触发监听,执行的回调函数
*/
watch(() => count.value, val => { console.log(`count is ${val}`) })
const state = reactive({ count: 0 })
watch( () => state.count, (count, prevCount) => { }) // watching a getter
watch(count, (count, prevCount) => { }) // directly watching a ref
watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => { }) // Watching Multiple Sources
/** 返回对象 */
return { count, doubleCount, add, a, update }
/** 返回 render 函数 */
// return () => h('div', [count.value, object.foo])
},
}
</script>
Mapping between 2.x Lifecycle Options and Composition API:
New hooks(debug hooks):