Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

「微信小程序」剖析(四):原生的实时DOM转Virtual DOM #30

Open
phodal opened this issue Sep 27, 2016 · 9 comments
Open

Comments

@phodal
Copy link
Owner

phodal commented Sep 27, 2016

在之前的几篇文章里,我们讨论了MINA的一些原理。晚上在想着怎么结合Vux + Virtual Dom实现一个名为WINV框架的时候,在探索WCC功能才发现:自己又忽略掉了一个很重要的性能优化细节。这个WCC如果内置在浏览器里,就是可以实时的将DOM转换为以JSON表示的DOM。

先将DOM转换为Virtual Dom,再转换回去的优点是可以分离数据和样式。这也就是为什么React的学习成本高的原因之一了。

Virtual Dom的表现形式

为了将真实的DOM转换为Virtual DOM,我们需要将DOM以一定的形式保存下来,如MINA的:

<map longitude="23.099994" latitude="113.324520" markers="{{markers}}" covers="{{covers}}" style="width: 375px; height: 200px;"></map>

如:

{
    "attr": {
        "covers": "",
        "latitude": "113.324520",
        "longitude": "23.099994",
        "markers": "",
        "style": "width: 375px; height: 200px;"
    },
    "children": [],
    "tag": "wx-map"
}

又或者是React中的:

{"type":"ul","key":null,"ref":null,"props":{"className":"my-list","children":{"type":"li","key":null,"ref":null,"props":{"children":"Text Content"},"_owner":null,"_store":{}}},"_owner":null,"_store":{}}

当然我们也可以自己实现一个比较简单的DOM转为Virtual DOM,如将

  var newDiv = document.createElement("div"); 
  var newContent = document.createTextNode("Hi there and greetings!"); 
  newDiv.appendChild(newContent); //add the text node to the newly created div. 

转换为接近原生的:

{"nodeType":1,"tagName":"div","attributes":[],"childNodes":[{"nodeType":3,"nodeName":"#text","nodeValue":"Hi there and greetings!","childNodes":[]}]}

原生的Parser与JS Parser

我会假装你已经知道了浏览器相关的很多细节,我也假装我已经对这些细节很清晰。下图一份Webkit浏览器的早期架构图:

如果我们使用JS实现一个将WXML将换为DOM JSON,我们就需要间接通过JavaScript Engine(即JSCore )来转换这个JSON文件。当有大量的DOM的时候,这就不是一件轻松的事了。所以,在WCC的生成代码里对DOM的数量限制为16000

我们可以用原生的接口来将WX DOM转换为JSON,但是我们没有办法用原生的接口来将DOM JSON转换DOM——毕竟我们还有大量的数据和绑定函数。

而这一点对于混合应用来说,就特别有帮助:

如果这个插件可以用在Cordova上,那么它将改善混合应用的性能。

数据绑定

当我们触发了generateFunc方法的时候:

document.dispatchEvent(new CustomEvent("generateFuncReady", {
    detail: {
        generateFunc: $gwx('src/index.wxml')
    }
})

我们调用下面的方法去初始化我们的DOM,并把数据传输进去:

var node = generateFunc((0, DataClass.getData)());

函数绑定

MINA的函数绑定机制是由函数名来决定的,如:

"bind" === propKey.slice(0, 4) ? createEventHandle(domElement, propKey.slice(4), propValue);
"catch" === propKey.slice(0, 5) ? createEventHandle(domElement, propKey.slice(5), propValue, !0);
"on" === propKey.slice(0, 2) ? createEventHandle(domElement, propKey.slice(2), propValue);

对于其他类型的绑定则是:

"style" === propKey ? domElement.setAttribute(propKey, (0, r.transformRpx)(propValue)) : domElement.setAttribute(propKey, propValue)
  - "animation" === propKey && "object" === ("undefined" == typeof propValue ? "undefined" : i(propValue)) && propValue.actions && propValue.actions.length > 0 && !function() {})

PS:我突然就不想看这个if else经过minify以后的代码了,太恶心了。。。

如,我们的wxml:

<view  bindtap="bindViewTap" class="userinfo"></view>

我们的propKey是bindtap,我们的propValue是bindViewTap,随后我们就会根据当前的函数名去创建相应的事件。

微信小程序」剖析系列

@dingyiming
Copy link

赞!

@phodal
Copy link
Owner Author

phodal commented Sep 27, 2016

@dingyiming 好快~~,我的文章还没排版好呢。

@dingyiming
Copy link

@phodal 哈哈,刚巧,刚刚看到自己github动态第一条就是你的文章

@hzuhyb
Copy link

hzuhyb commented Sep 27, 2016

一棵探索的心

@gantoday
Copy link

gantoday commented Nov 2, 2017

image
请问这里的dom是怎么得到的呢?
萌新没看懂。

@NoraGithub
Copy link

我们可以用原生的接口来将WX DOM转换为JSON,但是我们没有办法用原生的接口来将DOM JSON转换DOM——毕竟我们还有大量的数据和绑定函数。
我们可以通过修改这个JSON来间接达到修改dom的目的吗?这里说的原声接口是哪个呢?没找着 T_T

@phodal
Copy link
Owner Author

phodal commented Jan 8, 2018

@NoraGithub 理论上是可以的,但是成本比较高。就是 wxss 命令

@NoraGithub
Copy link

NoraGithub commented Jan 8, 2018

@phodal 谢谢答复。我再研究下。

@wind4gis
Copy link

额,我现在没法看到楼主写的源码,现在开发者工具下的JS文件全都做了混淆处理,变量名也被简写了。。。现在没法看到里边的运行逻辑。。。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants