render

主题: render
解决问题:
1.h是什么?有什么用?
h是hyperScript. 作用: 使用JS去写html.因为html最后也是render成JS
1,when to use render?
当使用template遇到困难的时候.
2.h怎么使用?
render(){
return h(‘div’,{class:‘colorName’,id:‘gridID’},[‘span’,‘hello’])
}
上面的等价于

hello

h(标签名称, 标签属性, 标签中的值)
3.vue怎么写?
create(App).mount(‘#app’) 将写好的JS代码挂载在一个div上
组件需要在components中告诉要使用它

<script src="https://unpkg.com/vue@next"></script>
<style>.mt-4{margin:10px;color:red;}
</style>
<div id="app"></div>
<script>const {h,createApp} = Vueconst Stack={props:'size',render(){const slot=this.$slots.default? this.$slots.default(): []console.log(slot)console.log(this.$props.size)// return h('div',{class:'stack'},slot.map(item=> {return h('div',{class:`mt-${this.$props.size}`},[item])}) )return h('div', { class:'stack'}, slot.map(item=>{return h('div', { class:`mt-${this.$props.size}`},[item])}))}}const App={components: {Stack},template: `<Stack size="4"><div>hello</div><Stack size="4"><div>hello</div><div>hello</div></Stack></Stack>`}createApp(App).mount('#app')
</script>

mount 写一个mount函数

主题:mount
1…怎么写一个mount函数?
其实就是h函数的三个入参的功能.
(1).创建标签 (2).添加属性 (3).添加children.把这三个功能实现了就好了

<style>.red{color:red;}
</style>
<div id="app"></div>
<script>
function h(tag,props,children){return {tag,props,children}
}
function mount(vnode , container){const el=document.createElement(vnode.tag)if(vnode.props){for(const key in vnode.props){const value=vnode.props[key]el.setAttribute(key, value)}}if(vnode.children){// contentif(typeof vnode.children==='string'){el.textContent=vnode.children} else {console.log(vnode.children)// tagvnode.children.forEach(child=>{mount(child,el)})}}container.appendChild(el)
}
const vdom=h('div',{class:'red'},[h('span',null,'hello')])
mount(vdom,document.getElementById('app'))
</script>

自己写的mount一些错误点

    function mount(app,root='#div'){let el=document.createElement(app.tag)let props=app.props||[]if(app.props){/*   //props是对象, 不是数组props.forEach(item=>{el.setAttribute(item)})*/for(let item in props){el.setAttribute(item,props[item])}}if(app.children){if(app.children==='string'){el.textContent=app.children}else{//children是一个数组如果不是string的话, 不是一个值app.children.forEach(child=>{mount(app.children)})}}root.appendChild(el)}

patch

主题:patch
1…怎么写一个patch函数?
删除, 插入
基本还是从h(div,props,children)这三个入手, 去比较, 其中props比较用到removeAttribute和setAttribute;
children比较用到textcontent和mount和patch和removeChild; 可以看出patch只是原地比较, 没有任何优化的地方。
2.解释上面代码:
1.1和1.2代表对props的处理; 2.1和2.3代表对children的处理
3.el是什么?
el相当于’#id’选择器选择的div标签

<style>.red{color:red;}
</style>
<div id="app"></div>
<script>const vdom=h('div',{class:'red'},[h('span',null,'hello')])
mount(vdom,document.getElementById('app'))function patch(n1,n2){// patch, 当两个都是div标签的时候if(n1.tag==n2.tag){const el=n1.el=n2.elconst oldProps=n1.props||{}const newProps=n2.props||{}// props设置为新节点的属性, 当两个props不相等的时候 1.1for(const key in newProps){const oldValue=oldProps[key]const newValue=newProps[key]if(oldValue!==newValue){el.setAttribute(key,newValue)}}// 删除props, 当只有旧节点中有props的时候 1.2for(const key in oldProps){if(!(key in newProps)){el.removeAttribute(key)}}const oldChildren=n1.chrildrenconst newChildren=n2.chrildren//textcontent直接为新节点的值, 当新节点没有子节点的时候 2.1if(typeof newChildren=='string'){if(typeof oldChildren=='string'){if(newChildren!==oldChildren){el.textContent=newChildren}} else {el.textContent=newChildren}}else{// 新节点的子节点挂载上去, 当只有新节点有子节点的时候 2.2if(typeof oldChildren=='string'){el.innerrHTML=''newChildren.forEach(item=>{mount(item,el)})}else{//比较, 当两个都有子节点span的时候 2.3const commomLength=Math.min(oldChildren.length,newChildren.length)for(let i=0;i<commomLength;i++){patch(oldChildren[i],newChildren[i])}if(newChildren.length<oldChildren.length){oldChildren.slice(newChildren.length).forEach(item=>{el.removeChild(item.el)})}if(newChildren.length>oldChildren.length){oldChildren.slice(newChildren.length).forEach(item=>{mount(item,el)})}}}} else {// replace, 当两个dom不相同的时候}
}</script>

reactivity和reactivity API

这部分没太看明白

写一个mini vue

<div id="app"></div>
<script>function h(tag, props, children) {return {tag,props,children}}function mount(vnode, container) { // 参数: (h('span',null,'hello'), '#div')const el = document.createElement(vnode.tag)if (vnode.props) {for (const key in vnode.props) {const value = vnode.props[key]el.setAttribute(key, value)}}if (vnode.children) {// contentif (typeof vnode.children === 'string') {el.textContent = vnode.children} else {console.log(vnode.children)// tagvnode.children.forEach(child => {mount(child, el)})}}container.appendChild(el)}function patch(n1, n2) {// patch, 当两个都是div标签的时候const el = n1.el = n2.elif (n1.tag == n2.tag) {const oldProps = n1.props || {}const newProps = n2.props || {}// props设置为新节点的属性, 当两个props不相等的时候 1.1for (const key in newProps) {const oldValue = oldProps[key]const newValue = newProps[key]if (oldValue !== newValue) {el.setAttribute(key, newValue)}}// 删除props, 当只有旧节点中有props的时候 1.2for (const key in oldProps) {if (!(key in newProps)) {el.removeAttribute(key)}}const oldChildren = n1.childrenconst newChildren = n2.children//textcontent直接为新节点的值, 当新节点没有子节点的时候 2.1if (typeof newChildren == 'string') {if (typeof oldChildren == 'string') {if (newChildren !== oldChildren) {el.textContent = newChildren}} else {el.textContent = newChildren}} else {// 新节点的子节点挂载上去, 当只有新节点有子节点的时候 2.2if (typeof oldChildren == 'string') {el.innerHTML = ''newChildren.forEach(item => {mount(item, el)})} else {//比较, 当两个都有子节点span的时候 2.3const commonLength = Math.min(oldChildren.length, newChildren.length)for (let i = 0; i < commonLength; i++) {patch(oldChildren[i], newChildren[i])}if (newChildren.length < oldChildren.length) {oldChildren.slice(newChildren.length).forEach(item => { el.removeChild(item.el) })}if (newChildren.length > oldChildren.length) {oldChildren.slice(newChildren.length).forEach(item => { mount(item, el) })}}}} else {// replace, 当两个dom不相同的时候}}let activeEffect;// 依赖收集器class Dep {subscribers = new Set()depend() {if (activeEffect) {this.subscribers.add(activeEffect)}}notify() {this.subscribers.forEach(effect => {effect()})}}function watchEffect(effect) {activeEffect = effecteffect()activeEffect = null}const targetMap = new WeakMap()function getTarget(target, key) {// depsMap为Map类型 里面存储要响应的对象的Map/*** {*  [target]: Map()*}*/let depsMap = targetMap.get(target)if (!depsMap) {depsMap = new Map()targetMap.set(target, depsMap)}// 为每一个key设置Dep监听类let dep = depsMap.get(key)if (!dep) {dep = new Dep()depsMap.set(key, dep)}return dep}const reactiveHandler = {get(target, key, receiver) {const dep = getTarget(target, key)// 收集依赖dep.depend()return Reflect.get(target, key, receiver)},set(target, key, value, receiver) {const dep = getTarget(target, key)const result = Reflect.set(target, key, value, receiver)dep.notify()return result}}function reactive(raw) {return new Proxy(raw, reactiveHandler)}const App = {data: reactive({count: 0}),render() {return h('div', {onClick: () => {this.data.count++}}, String(this.data.count))}}function mountApp(component, container) {let isMounted = falselet prevVdomwatchEffect(() => {if (!isMounted) {prevVdom = component.render()mount(prevVdom, container)isMounted = true} else {const newVdom = component.render()patch(prevVdom, newVdom)prevVdom = newVdom}})}mountApp(App, document.getElementById('app'))
</script>

尤雨溪-写一个mini vue相关推荐

  1. 尤雨溪自述:打造Vue 3背后的故事

    尤雨溪在今年年初Vue 3正式发布之前撰写了这篇长文,详述Vue 3的设计过程.前端之巅将全文翻译如下,希望能帮助你更好地了解Vue 3背后的故事 在过去的一年中,Vue 团队一直都在开发 Vue.j ...

  2. Vue 3.2 发布了,那尤雨溪是怎么发布 Vue.js 的?

    1. 前言 大家好,我是若川.最近组织了源码共读活动,感兴趣的可以加我微信 ruochuan12,长期交流学习. 之前写的<学习源码整体架构系列> 包含jQuery.underscore. ...

  3. 尤雨溪写的100多行的“玩具 vite”,十分有助于理解 vite 原理

    1. 前言 大家好,我是若川.最近组织了源码共读活动,感兴趣的可以加我微信 ruochuan12 想学源码,极力推荐之前我写的<学习源码整体架构系列>jQuery.underscore.l ...

  4. 学习尤雨溪写的 Vue3 源码中的简单工具函数

    大家好,我是若川.最近组织了源码共读活动.每周读 200 行左右的源码.很多第一次读源码的小伙伴都感觉很有收获,感兴趣可以加我微信ruochuan12,拉你进群学习. 初学者也能看懂的 Vue3 源码 ...

  5. 尤雨溪回应:为什么 Vue 在国际上越来越没影响力?

    来源: https://www.zhihu.com/question/472193255/answer/2235015723 前段时间,知乎上一条「为什么 Vue 在国际上越来越没影响力?」的问题火了 ...

  6. 尤雨溪告诉你为什么Vue比yox优秀

    2019年6月8日来自全球各地的开发者齐聚上海交通大学文治堂,VueConf 2019 在上海成功举办. VUE 3.0  最新进展 更快 使用 Object.defineProperty -> ...

  7. 尤雨溪携手字节前端专家,畅聊 Vue 3.0 前端技术新趋势

    前端这个技术领域,在应用化以后,涵盖的内容越来越广--纯表现层.应用实现层.应用架构层.基础设施层到改进开发范式的理念层,都有太多可以去钻研的技术点,衍生出了无数前端开发的发展路线."别更新 ...

  8. 尤雨溪:VUE 3 之后会休息一下

    此文转载自:https://my.oschina.net/u/4487475/blog/4631827 LiteOS Studio图形化调测能力,物联网打工人必备!>>> 9 月 1 ...

  9. Vite 与 Vue Cli 对比 - 尤雨溪: Vite 会取代 vue-cli 吗?

    本文完整版:<Vite 与 Vue Cli 对比 - 尤雨溪: Vite 会取代 vue-cli 吗> Vite 与 Vue Cli 对比 一.Vite 与 Vue CLI 是什么? Vu ...

最新文章

  1. linux如何查看内存最大的几个文件,详解Linux如何查看当前占用CPU或内存最多的几个进程...
  2. sublime text 3 中改变.vue文件的颜色
  3. 数据结构与算法(一):链表
  4. Python验证和可视化冰雹猜想、角谷猜想、考拉兹猜想
  5. 58岁退休女士,想出去旅游却很难约到合适的伴,怎么办?
  6. linux多线程select定时器,linux使用select实现精肯定时器详解
  7. 2017 CIMS计算机集成制造系统 paper 数字孪生及其应用探索
  8. 2016年WiFi行业技术发展趋势解析
  9. 计算机指法游戏警察抓小偷,警察抓小偷打字游戏游戏
  10. 【加密工具】2019年网络安全加密工具排行,好用的计算机加密软件推荐
  11. 如何切换apache中的php5与php7
  12. 企业信息化系列: 什么是企业信息化
  13. python文件加减法_python生成PDF文件20以内加减法,给上小学的宝宝
  14. 神州战神系列装系统过程,其他电脑大同小异
  15. poi 获取excel单元格超链接和设置excel单元格超链接及导出excel
  16. linux 启动openfire
  17. oceanus-58总体框架理解
  18. python学习之路(3)turtle画奥运五环
  19. 计算机组装有哪些,电脑组装的配件有哪些
  20. 企业蝉知系统如何安装?企业系统是否满足要求?

热门文章

  1. 基岩版服务器开启坐标显示,mc基岩版怎么看坐标 mc基岩版如何看坐标
  2. 电脑开机无logo,进不了bios
  3. 2019年成功与失败的危机公关案例分析
  4. Java 面向对象 习题2(基础篇)
  5. Spring Boot制作个人博客-标签页
  6. 想学开服技术,先了解服务端的组成
  7. android错误之解析包时出现问题(一)
  8. composer设置国内源
  9. 高通骁龙410系列-MSM8916(M9+) ( Cortex-A53架构)
  10. 姜小白的Python日记Day8 字符串编码转换与函数简介