vue2源码简单实现stage3
2021/12/20 11:20:08
本文主要是介绍vue2源码简单实现stage3,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
在上一节中我们已经将代码整理了一下,这一节我们要做的是比较新旧dom,然后通过diff算法判断虚拟dom时候有变化,是否需要刷新视图。为了让代码更加清晰,我们这边还是做了简化,假设父节点下只有一个元素。并且手动调用更新方法,暂时不做数据双向绑定更新视图。
理解patch函数
不管是第一次挂载到视图还是后续的手动更新,我们都要触发构建新的dom,这时候我们可以将这个逻辑写到update的函数里面,但是 要根据不同的情况触发不同的更新逻辑,所以用到了patch函数
;(function () { function vnode (tag, data, children, text, elm) { this.tag = tag; this.data = data; this.children = children; this.text = text; this.elm = elm; } function normalizeChildren (children) { if (typeof children === 'string') { return [createTextVNode(children)] } return children } function createTextVNode (val) { return new vnode(undefined, undefined, undefined, String(val)) } function createElement (tag, data, children) { return new vnode(tag, data, normalizeChildren(children), undefined, undefined); } function createElm (vnode) { var tag = vnode.tag; var data = vnode.data; var children = vnode.children; if (tag !== undefined) { vnode.elm = document.createElement(tag); if (data.attrs !== undefined) { var attrs = data.attrs; for (var key in attrs) { vnode.elm.setAttribute(key, attrs[key]) } } if (children) { createChildren(vnode, children) } } else { vnode.elm = document.createTextNode(vnode.text); } return vnode.elm; } function createChildren (vnode, children) { for (var i = 0; i < children.length; ++i) { vnode.elm.appendChild(createElm(children[i])); } } function sameVnode (vnode1, vnode2) { return vnode1.tag === vnode2.tag } function emptyNodeAt (elm) { return new vnode(elm.tagName.toLowerCase(), {}, [], undefined, elm) } function patchVnode (oldVnode, vnode) { var elm = vnode.elm = oldVnode.elm; var oldCh = oldVnode.children; var ch = vnode.children; if (!vnode.text) { if (oldCh && ch) { updateChildren(oldCh, ch); } } else if (oldVnode.text !== vnode.text) { elm.textContent = vnode.text; } } function updateChildren (oldCh, newCh) { // 假设每一个元素下面只有一个子元素 if (sameVnode(oldCh[0], newCh[0])) { patchVnode(oldCh[0], newCh[0]) } else { patch(oldCh[0], newCh[0]) } } function patch (oldVnode, vnode) { var isRealElement = oldVnode.nodeType !== undefined; // virtual node has no `nodeType` property if (!isRealElement && sameVnode(oldVnode, vnode)) { patchVnode(oldVnode, vnode); } else { if (isRealElement) { oldVnode = emptyNodeAt(oldVnode); } var elm = oldVnode.elm; var parent = elm.parentNode; createElm(vnode); parent.insertBefore(vnode.elm, elm); parent.removeChild(elm); } return vnode.elm } function initData (vm) { var data = vm.$data = vm.$options.data; var keys = Object.keys(data); var i = keys.length // 代理之后可以直接使用this.key 而不是this.data.key while (i--) { proxy(vm, keys[i]) } } function proxy (vm, key) { Object.defineProperty(vm, key, { configurable: true, enumerable: true, get: function () { return vm.$data[key] }, set: function (val) { vm.$data[key] = val } }) } function Vue (options) { var vm = this; vm.$options = options; initData(vm); vm.mount(document.querySelector(options.el)) } Vue.prototype.mount = function (el) { var vm = this; vm.$el = el; vm.update(vm.render()) } Vue.prototype.update = function (vnode) { var vm = this; var prevVnode = vm._vnode; vm._vnode = vnode; if (!prevVnode) { vm.$el = vm.patch(vm.$el, vnode); } else { vm.$el = vm.patch(prevVnode, vnode); } } Vue.prototype.patch = patch; Vue.prototype.render = function () { var vm = this; return vm.$options.render.call(vm) } var vm = new Vue({ el: '#app', data: { message: 'Hello world', isShow: true }, render () { return createElement( 'div', { attrs: { 'class': 'wrapper' } }, [ this.isShow ? createElement( 'p', { attrs: { 'class': 'inner' } }, this.message ) : createElement( 'h1', { attrs: { 'class': 'inner' } }, 'Hello world' ) ] ) } }) // test setTimeout(function () { vm.message = 'Hello'; vm.update(vm.render()) }, 1000) setTimeout(function () { vm.isShow = false; vm.update(vm.render()) }, 2000) })();
diff算法简介
diff算法一直是比较难的,想深入了解可以参考
[组件更新]https://ustbhuangyi.github.io/vue-analysis/v2/reactive/component-update.html#新旧节点相同
这篇关于vue2源码简单实现stage3的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-16Vue3资料:新手入门必读教程
- 2024-11-16Vue3资料:新手入门全面指南
- 2024-11-16Vue资料:新手入门完全指南
- 2024-11-16Vue项目实战:新手入门指南
- 2024-11-16React Hooks之useEffect案例详解
- 2024-11-16useRef案例详解:React中的useRef使用教程
- 2024-11-16React Hooks之useState案例详解
- 2024-11-16Vue入门指南:从零开始搭建第一个Vue项目
- 2024-11-16Vue3学习:新手入门教程与实践指南
- 2024-11-16Vue3学习:从入门到初级实战教程