Github源码: vue-next
前言
由于vue更新后与文中demo不兼容 ,再此说明一下, 本文的所有内容是基于3.0.0-alpha.1
版本编写,各位小伙伴在学习的时候注意下版本哦

Vue3 相对于 Vue2 有那些更改?
- Object.defineProperty => Proxy
- 重构了虚拟DOM
- OptionApi => Composition API
如何调试 (可跳过 直接使用 vite 创建项目 [2020.6.1])
首先,在GitHub上拉取最新代码
$ git pull https://github.com/vuejs/vue-next.git
$ cd vue-next && yarn
下载完成之后打开代码, 开启sourceMap
1、tsconfig.json
把sourceMap字段修改为true

rollup.config.js
中,手动键入output.sourcemap = true

yarn dev


第一个Hello World!!!
/demo/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.container {
text-align: center;
font-size: 24px;
padding: 32px;
}
</style>
<script src="../packages/vue/dist/vue.global.js"></script>
</head>
<body>
<div id="app"></div>
</body>
<script src="./index.js"></script>
</html>
/demo/index.js
const { reactive } = Vue
var App = {
template: `
<div class="container">
{{message}}
</div>`,
setup() {
const state = reactive({message: "Hello World!!!"})
return {
...state
}
}
}
Vue.createApp().mount(App, '#app')
在浏览器打开咱们编写的html文件,

serve
库来创建的,有兴趣的话可以看下serve
anyway,咱们接着看咱们的/demo/index.js
文件,可以看到,咱们用了setup, reactive
等函数,这就是Vue3的Composition API
,相对于Vue2的组件来说 3 可以让我们很简单的通过组合API的方式创建一个 基于Vue3 响应式 Web 应用。 下边我会通过一个个的demo为大家详细解释这些API。
接下来咱们实现一个双向绑定的demo!!!
双向绑定的demo
const { reactive } = Vue
let App = {
template: `
<div class="container">
<input v-model="state.value"/>{{state.value}}
</div>`,
setup() {
const state = reactive({ value: '' })
return { state }
}
}
Vue.createApp().mount(App, '#app')

beforeCreate
和 Created
这两个生命周期。
setup接受两个参数,第一个参数是props, 另一个参数是context,所以大家在使用2.0时习惯的在this下获取属性的方式 ,在 vue3.0 中,变成了:
setup(props, ctx) {
console.log(props, ctx)
}
不过在模板中仍然可以直接使用props的属性值,例如:
let Child = {
template: `<div>{{title}}</div>`,
setup(props, context) {
console.log(props)
}
}
let App = {
template: `
<div class="container">
<Child title="test props"/>
</div>`,
components: { Child }
}
Vue.createApp().mount(App, '#app')


那reactive???之前用的 data呢??? 在Vue3中,我们可以把数据经过 reactive 加工变成响应式的对象,用于模版的渲染数据, 当然Vue的向下兼容 还是允许我们使用data的方式实现,但既然Vue3出新的写法了,何不尝试一波呢
计数器 demo
const { reactive, toRefs } = Vue
let App = {
template: `
<div class="container">
count: {{count}}
<button @click="handlerCountAdd"> Click ++ </button>
</div>`,
setup() {
const state = reactive({ count: 0 })
const handlerCountAdd = () => {
state.count++
}
return { ...toRefs(state), handlerCountAdd }
}
}
Vue.createApp().mount(App, '#app')

const App = {
template: `
<div class="container">
{{value}}
</div>`,
setup() {
const value = ref(1)
return { value }
}
}
Vue.createApp().mount(App, '#app')

reactive
创建的响应式对象 在模板中访问的话,则需要state.xxx
, 例:
const App = {
template: `
<div class="container">
{{state.value}}
</div>`,
setup() {
const state = reactive({ value: 'reactive' })
return { state }
}
}
Vue.createApp().mount(App, '#app')
这样访问属性确实有点麻烦,vue3提供的toRefs
正是为我们解决这个问题的,toRefs把一组的响应式对象拆成单个的响应式对象,就能够在模板中直接访问了,及:
const App = {
template: `
<div class="container">
{{value}}
</div>`,
setup() {
const state = reactive({ value: 'reactive' })
return toRefs(state)
}
}
Vue.createApp().mount(App, '#app')
反转字符串 demo
let App = {
template: `
<div class="container">
value: <input v-model="value"/>
<br/>
rvalue: {{rvalue}}
</div>`,
setup() {
const state = reactive({
value: '',
rvalue: computed(() =>
state.value
.split('')
.reverse()
.join('')
)
})
return toRefs(state)
}
}
Vue.createApp().mount(App, '#app')

computed
计算属性实现了反转字符串的功能,这个函数虽然简单,但是功能很强大,正如vue官网所说:对于任何复杂逻辑,你都应当使用计算属性。
数据响应式
大家都知道, 在Vue3中实现数据响应式的方案由Vue2中的Object.defineProperty 换成了 Proxy,关于数据响应式的Api上边说到了一些,还剩下effect和watch没有提及到,effect是数据响应式中重要的一部分,watch和computed都是基于 effect 的,下边来看下代码
let App = {
template: `
<div class="container">
count: {{count}}
<button @click="handlerCountAdd"> Click ++ </button>
</div>`,
setup() {
const state = reactive({ count: 0, value: 1 })
const handlerCountAdd = () => {
state.count++
}
watch(
() => state.count,
val => {
console.log('watch', state.count)
console.log('watch', state.value)
}
)
effect(() => {
console.log('effect', state.count)
console.log('effect', state.value)
})
return { ...toRefs(state), handlerCountAdd }
}
}
Vue.createApp().mount(App, '#app')

首先,effect 在响应式数据变化的时候就会执行,执行次数根据响应式数据的个数来决定,例如
let App = {
template: `
<div class="container">
<button @click="handlerCountAdd"> Click ++ </button>
</div>`,
setup() {
const r = ref(1)
const s = ref(1)
const t = ref(1)
const handlerCountAdd = () => {
r.value *= 1
s.value *= 2
t.value *= 3
}
effect(() => {
console.log('effect', [r.value, s.value, t.value])
})
return { handlerCountAdd }
}
}
Vue.createApp().mount(App, '#app')

而watch则点击一次 ,只会触发执行一次
let App = {
template: `
<div class="container">
<button @click="handlerCountAdd"> Click ++ </button>
</div>`,
setup() {
const state = reactive({ count: 0, value: 1 })
const r = ref(1)
const s = ref(1)
const t = ref(1)
const handlerCountAdd = () => {
r.value *= 1
s.value *= 2
t.value *= 3
}
watch([r, s, t], val => {
console.log('watch', val)
})
return { handlerCountAdd }
}
}
Vue.createApp().mount(App, '#app')

好了,vue3Composition Api
中常用的一些函数在咱上边的demo中使用了,接下来咱们对比一下2和3的生命周期函数有什么改变
Vue2 | Vue3 |
---|---|
beforeCreate | setup(替代) |
created | setup(替代) |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeDestroy | onBeforeUnmount |
destroyed | onUnmounted |
errorCaptured | onErrorCaptured |
Tips: 为什么不直接运行 yarn dev,而要先开启sourceMap?
虽然Vue官方说可以直接运行run dev 就可以对其进行调试,可是运行该命令后,是生成过后的代码,不能对其编写的ts源码进行调试。

Thank You
篇幅很大,感谢大家耐心观看,文中如有错误欢迎指正。

我是
Colin
,可以扫描下方二维码加我微信,备注交流。

感谢H5兽超进化前端菜鸡兽指正文章中的问题