WebWorker 中将已处理好的 VDOM 数据提交主线程渲染 DOM

上篇文章讲了 WebWorker 的简单用法,其实网上很多类似的文章,我写的也比较垃圾。不会的建议可以网上看比较好点的资料。

这里我会先讲下我的大致思路。然后会贴上一堆不实用的垃圾代码供参考。

WebWorker 中必然是无法访问 DOM 的,更无法创建 DOM 元素。如果想要实现把 Worker 中的东西渲染出来,只能把相关数据什么的放到主线程去渲染。这用消息机制是可以实现的。

DOM 既然只能在主线程渲染,那么事件 Worker 线程自然也是无能为力了。而更关键的是 Worker 和主线程通信的时候不能传递函数作为参数(toString 这种方式不作数),而事件处理程序都是函数。那么就只好通过一个标识来代替函数,在 Worker 里通过这个标识来决定具体执行什么操作。

Worker 和主线程的分工相对是明确的,完善后的代码也基本上不怎么会去写执行在主线程上代码的,主要还是去写执行在 Worker 里面的代码。而等下次要讨论的是如何把 HTML 编译成类似在下边的 worker.js 代码的 render 函数中直接用 JSON 写的那部分。

再之后要讨论 VDOM 相关的算法,到时候不管写的多烂,能用就行。

之后的之后就讨论一些动画,事件防抖等的处理方式,要放到很久之后才讨论了,还有很多没想好应该什么时候讨论的事情,一步步来吧,想到哪里就写到哪里,我一个纯高技术的,还是乱七八糟都学的人确实写不出多好的东西来,多练习下也许N年后就好些了吧。

这里直接不涉及任何 VDOM 相关的东西。所有的东西都是用 JSON 来表示而已。也说过以后的文章才会讨论 VDOM,我对 VDOM 也是一知半解。搞出的东西不会有多么高的保障。自己懂得的还是自己去研究的好,但好在这些算法开源的实现很多。学习后换成好点的就行了。

HTML 里面没有什么东西:

1 <div id="root"></div>
2 <script src="main.js"></script>

在主线程中运行的 main.js 中主要是为了渲染 DOM,绑定事件。这里的代码远远不足以满足正常使用,但这里只是为了讲一部分想法,没必要写那么复杂。能够渲染 DOM,绑定个事件就行了。至于更多的需求以后慢慢再讨论。这里声明,这些代码完全不足以在项目中使用,不要拿着乱用,不然里面很多问题你会很难解决的。

 1 var worker = new Worker('worker.js');
 2 
 3 worker.addEventListener('message', function (event) {
 4     console.log(event.data);
 5     var message = event.data;
 6 
 7     switch (message.type) {
 8         case 'render':
 9             render(message.payload);
10             break;
11     }
12 });
13 
14 
15 function render(data) {
16     var root = document.getElementById('root');
17 
18     root.innerHTML = '';
19 
20     root.appendChild(createElement(data));
21 }
22 
23 function setAttrs(element, attrs) {
24     if (attrs) {
25         for (var name in attrs) {
26             element.setAttribute(name, attrs[name]);
27         }
28     }
29 }
30 
31 function setProps(element, props) {
32     if (props) {
33         for (var name in props) {
34             element[name] = props[name];
35         }
36     }
37 }
38 
39 function setEvents(element, events) {
40     if (events) {
41         for (var name in events) {
42             attachEvent(element, name, events[name]);
43         }
44     }
45 }
46 
47 function setChildren(element, children) {
48     if (children && children instanceof Array) {
49         children.forEach(function (item) {
50             element.appendChild(createElement(item));
51         });
52     }
53 }
54 
55 function createElement(data) {
56     if (!data) {
57         return null;
58     }
59 
60     var element = document.createElement(data.type);
61 
62     setAttrs(element, data.attrs);
63     setProps(element, data.props);
64     setEvents(element, data.events);
65     setChildren(element, data.children);
66 
67     return element;
68 }
69 
70 var eventBinders = {
71     onTap: {
72         bind: function (element, name, value) {
73             element.addEventListener('click', function () {
74                 worker.postMessage({
75                     type: 'command',
76                     payload: {
77                         name: value
78                     }
79                 });
80             });
81         }
82     }
83 };
84 
85 function attachEvent(element, name, value) {
86     eventBinders[name].bind(element, name, value);
87 }
88 
89 function createAttribute(element, name, value) {
90     element.setAttribute(name, value);
91 }

在 Worker 线程中中执行的 worker.js 会处理很多事务。基本上逻辑什么的都在里面了。

 1 var data = {
 2     value: 1
 3 };
 4 
 5 function onDecreaseClick() {
 6     data.value -= 1;
 7     render(data);
 8 }
 9 
10 function onIncreaseClick() {
11     data.value += 1;
12     render(data);
13 }
14 
15 function handleCommand(data) {
16     switch (data.name) {
17         case 'onDecreaseClick':
18             onDecreaseClick(data);
19             break;
20         case 'onIncreaseClick':
21             onIncreaseClick(data);
22             break;
23     }
24 }
25 
26 function render(data) {
27     self.postMessage({
28         type: 'render',
29         payload: {
30             type: 'div',
31             attrs: {},
32             props: {},
33             children: [
34                 {
35                     type: 'button',
36                     events: {
37                         onTap: 'onDecreaseClick',
38                     },
39                     props: {
40                         textContent: 'Decrease'
41                     }
42                 },
43                 {
44                     type: 'span',
45                     props: {
46                         textContent: data.value
47                     }
48                 },
49                 {
50                     type: 'button',
51                     events: {
52                         onTap: 'onIncreaseClick',
53                     },
54                     props: {
55                         textContent: 'Increase'
56                     }
57                 }
58             ]
59         }
60     });
61 }68 
69 self.addEventListener('message', function (event) {
70     var message = event.data;
71 
72     switch (message.type) {
73         case 'command':
74             handleCommand(message.payload);
75             break;
76     }
77 });
78 80 render(data);

代码都很简单粗暴。虽然确实可以跑起来。但是无论是 DOM 渲染 还是 Worker 中的处理都是很简单的,同时也是不可实际生产使用的。接下来讨论过 VDOM 之后会进一步完善。

这次的东西写是写完了,但不知道是不是只有我自己能看懂自己写的啥。就当练手把。有空把整个项目的实现都写一遍,复习下也行,感觉不仅文笔差,思路好像也不是很好吧。

猜你喜欢

转载自www.cnblogs.com/javennie/p/10193427.html