组装页面

来源:转载

在码农中最持久的一个口号就是:

低耦合、高内聚

先来看低耦合,在用Java写代码的时候大家已经习惯用 共享内存 的方式来实现多线程间的通信(就不举栗子了),有点问题的时候排查起来比较头疼,而另外一种思路是:

用通信的方式来共享内存

比如在古老的 Erlang 中是这样的:

receive Message1 [when Guard1] -> Actions1 ; Message2 [when Guard2] -> Actions2 ; ...end

而比较新的 Golang 中是这样的:

func Producer (queue chan<- int){for i:= 0; i < 10; i++ {queue <- i}}func Consumer( queue <-chan int){for i :=0; i < 10; i++{v := <- queuefmt.Println("receive:", v)}}func main(){queue := make(chan int, 1)go Producer(queue)go Consumer(queue)time.Sleep(1e9) //让Producer与Consumer完成}

再回过头来看HTML其实也是通过消息来驱动的,页面上的每个操作都会转换成事件传递给JavaScript进行处理,在JavaScript中的事件处理方式如下(单线程):

在可视化编程中这种方式还是挺给力的,在使用一个组件时,需要根据它的事件来让用户去扩展(写代码):

@input(name = "abc") @on(click) ...... @on(change) ......

用户在编写代码的时候只需要关注两个对象:

event :事件对象 this :订阅了事件的组件,也就是当前组件

组件可以监听另一个组件的事件,这样两个组件就可以实现交互(和HTML的区别是动作与展示结合在一起):

@input(name = "abc")[email protected](...)@target(abc)@on(click)[email protected](target = "abc" type="click")....

在event中包含的字段有:

字段 作用 target 产生事件的组件名称 type 事件类型 data 数据

实现事件的订阅/发布需要三个操作:

绑定 取消绑定 发送

在组件从页面上消失的时候是需要取消绑定的,不然可能会有问题,配置完成页面上组件之间的关系如下:

在接收到事件的时候可以做任何你想做的事情,比如更新一下页面的展示。因为组件已经封装的比较彻底了,暴露给用户的只有数据,那么只能通过更新数据来更新展示:

@table @on(click) setState({list:[1,2,3,4]});

如果对应的模板为:

@render for(var i in list){ <li>${i}</li> }

那么得到的HTML的代码如下:

<li>1</li><li>2</li><li>3</li><li>4</li>

在更新展示时如果直接用 innerHTML 或者 outerHTML 实现起来比较简单,但问题是体验比较差:

用户的输入(或者列表的选择)都会消失,感觉有点像区域被刷新了一下。

另外在全部更新的情况下要比逐个更新元素要快一些,但是很多情况下我们只需要更新页面上的一小部分,那么就可以考虑用JS原生的DOM操作来搞:

操作 作用 createElement 创建HTML元素 appendChild 将一个节点插入到指定的父节点的最末尾处 removeChild 从某个父节点中移除指定的子节点,并返回那个子节点 replaceChild 用指定的节点替换当前节点的一个子节点,并返回被替换掉的节点 insertBefore 在当前节点的某个子节点之前再插入一个子节点

虽然没有 insertAfter 方法,但是实现起来非常简单。DOM结构中另一个变化的大头就是属性:

操作 作用 getAttribute 获取属性 setAttribute 设置属性 removeAttribute 移除属性

最后想修改标签中的字符时可以用 innerHTML 或者 textContent 直接搞定,最后一个问题就是如何更新DOM结构:

追求性能可以根据 增 、 删 、 改 的成本用动态规划算出一个最优的修改方式,但是长期来看处理的数据都相当有限,只需要用贪心地策略来保证用户体验即可。


分享给朋友:
您可能感兴趣的文章:
随机阅读: