用 Weex Vanilla 写 Todolist 的尝试

knhk5997 7年前
   <p>关于如何在 Weex 上使用 Vanilla 代码写页面, 在前面有一篇文章已经介绍过了:</p>    <p><a href="/misc/goto?guid=4959742125719232459" rel="nofollow,noindex">https://hashnode.com/post/run...</a></p>    <p>大致上, 可以参考这个 Demo, 其实就是一些 DOM 操作,</p>    <p><a href="/misc/goto?guid=4959742125811659421" rel="nofollow,noindex">https://github.com/alibaba/we...</a></p>    <p>所以我明确的一个事实是 Weex 确实有一套 DOM API,</p>    <p>而且这套 API 应该说是所有基于 Weex 的框架的基础, 像 Weex, Rax, 甚至如果有 Angular 版本.</p>    <p>在 Weex 仓库里可以看到目前有 4 个框架, 其中 Vanilla 对应没有框架,</p>    <p><a href="/misc/goto?guid=4959742125896731304" rel="nofollow,noindex">https://github.com/apache/inc...</a></p>    <p>但实际上这个代码已经过时了, 比如后来的 weex 全局变量没有的完成,</p>    <p>所以为了方便我在本地开发, 我自己基于 Vue fork 了一个版本, 用来试验,</p>    <p><a href="/misc/goto?guid=4959742125984373434" rel="nofollow,noindex">https://gist.github.com/jiyin...</a></p>    <p>试验项目可以从 GitHub 上看, 用单个文件生成的 Todolist:</p>    <p><a href="/misc/goto?guid=4959742126076214924" rel="nofollow,noindex">https://github.com/mvc-works/...</a></p>    <p>最终的界面:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/5234eb4889a79ef973ebcef97dd52afe.jpg"></p>    <p>在这个 Todolist 当中我实现了基本的增删改功能, 但明显确实一下功能:</p>    <ul>     <li> <p>清除已读的任务</p> </li>     <li> <p>排序</p> </li>    </ul>    <p>没有做是因为太难实现了, 虽然也不是那么难, 但作为试验项目主要的目的吧,</p>    <p>我主要还是未来试验 Weex 的 DOM API 能不能写出像样的页面,</p>    <p>经过简单的封装, DOM 部分的写法在 CoffeeScript 里挺清晰的,</p>    <pre>  <code class="language-javascript"># DOM tree    mainTree = ->    div style: styleBody,      div style: styleContainer,        div style: styleHeader,          input            ref: 'input'            style: styleInput            attr: {value: '', placeholder: 'Some task...'}            event: {input: onDraft}          text            style: styleButton            attr: {value: 'Add task'}            event: {click: onAdd}        text          ref: 'raw'          attr: {value: getRaw()}          style: styleContent        div          ref: 'content'          style: styleContent    # mounting document    doc.documentElement.appendChild (helicalExpandTree mainTree())</code></pre>    <p>熟悉 DOM 操作的应该能脑补出我的代码来:</p>    <pre>  <code class="language-javascript">helicalExpandTree = (tree) ->    # console.log '\n\nExpanding:', JSON.stringify(tree)    [name, props, children] = tree    element = doc.createElement name,      style: props.style      attr: props.attr    if props.event      for key, value of props.event        element.addEvent key, value    if children?      # console.log 'CHILDREN:', JSON.stringify(children)      for child in children        childElement = helicalExpandTree child        # console.log '\n\nChild to append:', JSON.stringify(childElement)        element.appendChild childElement    if props.ref?      domRefs[props.ref] = element    element</code></pre>    <p>然后是事件处理, 这就有点问题了, 实际上有两个地方需要处理, Model 和 View,</p>    <p>熟悉 jQuery 的同学应该就能猜到了, 需要通过 event.target 做 DOM 操作,</p>    <p>两边都处理, 保证界面上没有出现状态不一致的情况, 当然写起来很啰嗦, 维护性差,</p>    <pre>  <code class="language-javascript">onRemove = (taskId) -> (event) ->    store.tasks = store.tasks.filter (task) -> task.id isnt taskId    # DOM operations    taskElement = event.target.parentNode    taskElement.parentNode.removeChild taskElement    modifyRaw()</code></pre>    <p>如果页面当中还有 Tab 的话, Tab 页之间的状态管理会让页面变得非常复杂,</p>    <p>当然为了方便使用, 我模仿了 React 的 ref 写法用来指定 DOM 的特定引用,</p>    <p>这样在小的页面当中也没有使用 jQuery 选择 DOM 节点的必要了.</p>    <p>所以看上去整个页面还是可以跑通的, 虽然效果实在很奇怪.</p>    <pre>  <code class="language-javascript">onAdd = (event) ->    newTask = id: getId(), done: 'false', text: store.draft    store.draft = ''    store.tasks.unshift newTask    # DOM operations    console.log 'DOM operations!!!'    domRefs.input.setAttr 'value', ''    newElement = helicalExpandTree (taskTree newTask)    console.log '\nnewElement:', newElement    domRefs.content.appendChild newElement    modifyRaw()</code></pre>    <p>其实可以从这个试验反思一下 Vue React 这些东西在移动端是否合适,</p>    <p>可以用这些框架主要是为了桌面平台的单页面 App 建造起来的,</p>    <p>附带了各种状态管理, 组件化, DSL, 编程风格在里边, 以及各种开发工具,</p>    <p>最主要的是声明式的写法确实提高了开发速度和组件的复用.</p>    <p>不过手机上状态管理的没有桌面端复杂倒是, 未必需要 React 那么强的功能.</p>    <p>手写 DOM 操作的方法基本上都是效率低下, 可维护性极差, 之类的,</p>    <p>除非是为了写几乎静态的页面, 这种方案完全可以被扔进历史的废纸篓...</p>    <p>不过也有一点好处, 就是没有太多抽象, 页面启动非常快, 提交很小.</p>    <p>虽然 Weex 一直运行在一个 js runtime 中, 但初始化组件多多少少有一点开销.</p>    <p>也许说是微乎其微... 但是从理论上而言, 启动过程需要执行的代码总是有区别的.</p>    <p>当然总体上说这样写几乎没什么用, 只是证明 Native DOM API 能正常用:</p>    <p><a href="/misc/goto?guid=4959742126159799289" rel="nofollow,noindex">http://weex.apache.org/refere...</a></p>    <p>没有明确的观点, 只是换着思路想想写 Weex 遇到的一些问题...</p>    <p> </p>    <p>来自:https://segmentfault.com/a/1190000008726905</p>    <p> </p>