最近在听开课吧村长老师的课,一些笔记与大家分享出来共同学习!
初体验:hello vue3
在文件目录下面,新建一个hello-vue3.html文件
<div id="app">
<h3>{{title}}</h3>
<h3>{{state.title}}</h3>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
// new Vue
const {createApp, reactive, h} = Vue
const app = createApp({
data() {
return {
title: 'hello vue3!'
}
},
setup() {
return {
state: reactive({
title: 'hello vue3!!!!!'
})
}
},
})
app.mount('#app')
</script>
vue3设计理念
- 函数式: 类型支持更好,ts
- 标准化、简化、一致性:render函数,sync修饰符删除,指令定义,v-model调整
- tree-shaking
- 复用性:composition api
- 性能优化:响应式、编译期优化
- 扩展性:自定义渲染器
手写vue3初始化流程
代码如下:
<div id="app">
<h3>{{title}}</h3>
</div>
<script>
// createApp返回应用程序实例是什么样子
const Vue = {
createApp(options) {
// 暴露给浏览器平台
const renderer = Vue.createRenderer({
querySelector(selector) {
return document.querySelector(selector)
},
insert(child, parent, anchor) {
parent.insertBefore(child, anchor || null)
}
})
return renderer.createApp(options)
},
createRenderer({ querySelector, insert }) {
// 返回自定义渲染器
return {
createApp(options) {
// 返回的就是app实例
return {
mount(selector) {
// mount的目标是什么?
const parent = querySelector(selector)
// 需要将组件配置解析为dom
// 通过render函数实现
if (!options.render) {
options.render = this.compile(parent.innerHTML)
}
// 兼容options api
if (options.setup) {
this.setupState = options.setup()
} else {
this.data = options.data()
}
// Proxy
// 确定render中数据从哪获取
this.proxy = new Proxy(this, {
get(target, key) {
if (key in target.setupState) {
return target.setupState[key]
} else {
return target.data[key]
}
},
set(target, key, val) {
if (key in target.setupState) {
target.setupState[key] = val
} else {
target.data[key] = val
}
}
})
const el = options.render.call(this.proxy)
// 追加到宿主元素上去
parent.innerHTML = ''
// parent.appendChild(el)
insert(el, parent)
},
compile(template) {
// 没有用到template
return function render() {
const h3 = document.createElement('h3')
h3.textContent = this.title
return h3
}
}
}
}
}
}
}
</script>
<script>
// new Vue
const { createApp } = Vue
const app = createApp({
data() {
return {
title: 'hello vue3!'
}
},
setup() {
// 调函数等等
// 规避this
return {
title: 'hello vue3!!!!!!'
}
},
})
app.mount('#app')
</script>
源码分析
源码地址(村长老师GitHub)搜索vue-next
补充一个老师所提到的面试题: vue3中mount的目标是什么?
将组件配置解析为dom,然后追加到宿主元素上去 大白话概述就是: 根据用户传入的选择器,获取当前的宿主元素,拿到宿主元素所依赖的innerHtml把它作为template,通过编译的方式作为渲染函数,得到真正当前的dom节点,最后追加进去
后面会陆续分享,大家一块学习,加油!!!