用 Weex Vanilla 寫 Todolist 的嘗試
關于如何在 Weex 上使用 Vanilla 代碼寫頁面, 在前面有一篇文章已經介紹過了:
https://hashnode.com/post/run...
大致上, 可以參考這個 Demo, 其實就是一些 DOM 操作,
https://github.com/alibaba/we...
所以我明確的一個事實是 Weex 確實有一套 DOM API,
而且這套 API 應該說是所有基于 Weex 的框架的基礎, 像 Weex, Rax, 甚至如果有 Angular 版本.
在 Weex 倉庫里可以看到目前有 4 個框架, 其中 Vanilla 對應沒有框架,
https://github.com/apache/inc...
但實際上這個代碼已經過時了, 比如后來的 weex 全局變量沒有的完成,
所以為了方便我在本地開發, 我自己基于 Vue fork 了一個版本, 用來試驗,
https://gist.github.com/jiyin...
試驗項目可以從 GitHub 上看, 用單個文件生成的 Todolist:
https://github.com/mvc-works/...
最終的界面:
在這個 Todolist 當中我實現了基本的增刪改功能, 但明顯確實一下功能:
-
清除已讀的任務
-
排序
沒有做是因為太難實現了, 雖然也不是那么難, 但作為試驗項目主要的目的吧,
我主要還是未來試驗 Weex 的 DOM API 能不能寫出像樣的頁面,
經過簡單的封裝, DOM 部分的寫法在 CoffeeScript 里挺清晰的,
# 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())
熟悉 DOM 操作的應該能腦補出我的代碼來:
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
然后是事件處理, 這就有點問題了, 實際上有兩個地方需要處理, Model 和 View,
熟悉 jQuery 的同學應該就能猜到了, 需要通過 event.target 做 DOM 操作,
兩邊都處理, 保證界面上沒有出現狀態不一致的情況, 當然寫起來很啰嗦, 維護性差,
onRemove = (taskId) -> (event) ->
store.tasks = store.tasks.filter (task) -> task.id isnt taskId
# DOM operations
taskElement = event.target.parentNode
taskElement.parentNode.removeChild taskElement
modifyRaw()
如果頁面當中還有 Tab 的話, Tab 頁之間的狀態管理會讓頁面變得非常復雜,
當然為了方便使用, 我模仿了 React 的 ref 寫法用來指定 DOM 的特定引用,
這樣在小的頁面當中也沒有使用 jQuery 選擇 DOM 節點的必要了.
所以看上去整個頁面還是可以跑通的, 雖然效果實在很奇怪.
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()
其實可以從這個試驗反思一下 Vue React 這些東西在移動端是否合適,
可以用這些框架主要是為了桌面平臺的單頁面 App 建造起來的,
附帶了各種狀態管理, 組件化, DSL, 編程風格在里邊, 以及各種開發工具,
最主要的是聲明式的寫法確實提高了開發速度和組件的復用.
不過手機上狀態管理的沒有桌面端復雜倒是, 未必需要 React 那么強的功能.
手寫 DOM 操作的方法基本上都是效率低下, 可維護性極差, 之類的,
除非是為了寫幾乎靜態的頁面, 這種方案完全可以被扔進歷史的廢紙簍...
不過也有一點好處, 就是沒有太多抽象, 頁面啟動非常快, 提交很小.
雖然 Weex 一直運行在一個 js runtime 中, 但初始化組件多多少少有一點開銷.
也許說是微乎其微... 但是從理論上而言, 啟動過程需要執行的代碼總是有區別的.
當然總體上說這樣寫幾乎沒什么用, 只是證明 Native DOM API 能正常用:
http://weex.apache.org/refere...
沒有明確的觀點, 只是換著思路想想寫 Weex 遇到的一些問題...
來自:https://segmentfault.com/a/1190000008726905