Omi樹元件omi-tree編寫指南
Omi框架能夠以少量的程式碼宣告式地編寫可拖拽移動節點的樹形元件。
通常樹元件能夠考驗UI框架的健壯性,因為需要使用到UI框架的如下特性:
- 元件巢狀
- 元件傳值
- 元件批量傳值
- 元件依賴自身遞迴巢狀(nest-self)
- 子、孫或炎黃子孫訪問根元件例項
下面來介紹下使用 omi-tree 的開發全過程。你也可以無視文章,先體驗一把和直接編輯原始碼試一把:
類劃分
- tree.js 樹元件的根容器類,包含節點移動,根據id獲取節點等通用方法,這裡把其排除在tree-node之外
- tree-node.js 樹節點,自遞迴巢狀元件,因為tree-node中可以包含tree-node
樹的資料規則:
{ name: 'Root', children: [ { name: 'A', id: 1, children: [ { id: 4, name: 'A1', children: [] }, { id: 7, name: 'A2', children: [] } ] }, { name: 'B', id: 2, children: [ { id: 5, name: 'B1', children: [] }, { id: 8, name: 'B2', children: [] } ] }, { name: 'C', id: 3, children: [ { id: 6, name: 'C1', children: [] }, { id: 9, name: 'C2', children: [] } ] } ] }
可以看到,每個節點都有唯一的id來標識,每個節點也有children屬性來存放自己的子節點的資訊。
元件HTML結構
tree結構:
<ul>
<tree-node o-repeat="child in children" group-data="data.children"></tree-node>
</ul>
- 通過 o-repeat 生成所有 tree-node
- group-data 把 data.children 的資料批量傳遞給各個 tree-node
這裡需要特別注意的是:
- o-repeat 等所有指令對應的 scope 資料是 this.data
- group-data,data等等 的 scope 是 this
tree-node結構:
<li data-node-id="{{id}}" draggable="true" ondragstart="dragStartHandler" ondragleave="dragLeaveHandler" ondrop="dropHandler" ondragover="dragOverHandler" >
<div data-node-id="{{id}}">{{name}}</div>
<ul data-node-id="{{id}}" o-if="children.length > 0">
<tree-node o-repeat="child in children" group-data="data.children"></tree-node>
</ul>
</li>
可以看到每個tree-node都標記了draggable代表可以拖拽,drag和drop的支援情況大家可以caniuse一把。
- 每個tree-node 既是拖拽對應,也是drop容器物件
- li、div和ul都標記了 data-node-id 來存放id在dom元素上方便js裡讀取和傳遞
完整程式碼解析
先看tree:
class Tree extends Omi.Component {
//移動節點
moveNode(id, parentId) {
if (id === parentId) {
return
}
if(this.check(parentId, id)) {
let parent = this.getChildById(parentId, this.data.children)
let child = this.removeChildById(id, this.data.children)
parent.children.push(child)
this.update()
}
}
//驗證子節點的孩子節點是否包含父親節點,這裡主要是為了防止把父節點拖拽到自己的孩子節點當中,這是個錯誤的邏輯操作
check(parentId, childId){
let current = this.getChildById(childId, this.data.children),
children = current.children
for (let i = 0, len = children.length; i < len; i++) {
let child = children[i]
if (child.id === parentId) {
return false
}
let errorIds = this.check(parentId, child.id )
if (!errorIds) {
return false
}
}
return true
}
//根據id移除child節點資料
removeChildById(id, children) {
for (let i = 0, len = children.length; i < len; i++) {
let child = children[i]
if (child.id === id) {
children.splice(i, 1)
return child
}
let target = this.removeChildById(id, child.children)
if (target) {
return target
}
}
}
//根據id獲取child節點資料
getChildById(id, children) {
for (let i = 0, len = children.length; i < len; i++) {
let child = children[i]
if (child.id === id) {
return child
}
let target = this.getChildById(id, child.children)
if (target) {
return target
}
}
}
render() {
return `<ul>
<tree-node o-repeat="child in children" group-data="data.children"></tree-node>
</ul>`
}
}
//生成標籤用於宣告式嵌入其他元件
Omi.tag('tree', Tree)
下面來看 tree-node:
class TreeNode extends Omi.Component {
dropHandler(evt) {
//通過evt.dataTransfer.getData接收傳遞過來的資料
this.getRootInstance(this.parent).moveNode(parseInt(evt.dataTransfer.getData("node-id")), parseInt(evt.target.dataset['nodeId']))
this.node && this.node.classList.remove('drag-over')
evt.stopPropagation()
evt.preventDefault()
}
getRootInstance(parent){
if(parent.moveNode){
return parent
}else{
return this.getRootInstance(parent.parent)
}
}
dragOverHandler(evt){
this.node.classList.add('drag-over')
evt.stopPropagation()
evt.preventDefault()
}
dragLeaveHandler(){
this.node.classList.remove('drag-over')
}
dragStartHandler(evt){
//設定要傳遞的資料
evt.dataTransfer.setData("node-id",this.data.id)
evt.stopPropagation()
}
//區域性樣式,drag-over是拖拽在node之上的一個啟用樣式
style(){
return `
.drag-over{
border:1px dashed black;
}
`
}
render(){
return `
<li data-node-id="{{id}}" draggable="true" ondragstart="dragStartHandler" ondragleave="dragLeaveHandler" ondrop="dropHandler" ondragover="dragOverHandler" >
<div data-node-id="{{id}}">{{name}}</div>
<ul data-node-id="{{id}}" o-if="children.length > 0">
<tree-node o-repeat="child in children" group-data="data.children"></tree-node>
</ul>
</li>
`
}
}
//生成標籤用於宣告式嵌入其他元件
Omi.tag('tree-node',TreeNode)
- dragStart的時候通過evt.dataTransfer.setData設定需要傳遞的資料,這裡存放了拖拽的節點id
- drop的時候通過evt.dataTransfer.getData讀取傳遞過來的資料,這裡取drag的node的節點id
- 通過 o-if="children.length > 0" 決定是否生成 ul 標籤
- getRootInstance元件是遞迴去調取tree的物件的例項(因為tree-node可能包含tree-node,所以需要遞迴讀parent)
- 拿到tree的例項之後,呼叫tree的物件的例項的moveNode方法去移動節點,moveNode的本質就是修改節點資料,然後update元件
到此位置,複雜的拖拽移動都完成了。增刪改查就更加簡單了,大家可以接著試試~~~
Omi相關
- 如果想使用Omi框架或者開發完善Omi框架,可以訪問 Omi使用文件
- 如果你想獲得更佳的閱讀體驗,可以訪問 Docs Website
- 如果你懶得搭建專案腳手架,可以試試 omi-cli
- 如果你有Omi相關的問題可以 New issue
- 如果想更加方便的交流關於Omi的一切可以加入QQ的Omi交流群(256426170)
相關推薦
Omi樹元件omi-tree編寫指南
Omi框架能夠以少量的程式碼宣告式地編寫可拖拽移動節點的樹形元件。 通常樹元件能夠考驗UI框架的健壯性,因為需要使用到UI框架的如下特性: 元件巢狀 元件傳值 元件批量傳值 元件依賴自身遞迴巢狀(nest-self) 子、孫或炎黃子孫訪問根元件例項 下面來介紹下使用 omi-tree 的開發全過程。你也可
[Vue.js — iView — Tree] 點選樹元件父節點名稱時展開、收縮後代節點
適用於iview tree。 ``` <Tree ref="tree" :data="data" :load-data="loadData" @on-select-change="selectChange" show-checkbox/> ``` ``` data() {
Omi教程-元件通訊攻略大全
元件通訊 Omi框架組建間的通訊非常遍歷靈活,因為有許多可選方案進行通訊: 通過在元件上宣告 data-* 傳遞給子節點 通過在元件上宣告 data 傳遞給子節點 (支援複雜資料型別的對映) 父容器設定 childrenData 自動傳遞給子節點 宣告 group-data 傳遞(支援複雜資料型別的對映)
easyui tree樹元件無限迴圈
在學習jquery easyui的tree元件的時候,在url為連結地址的時,發現如果最後一個節點的state為closed時,未節點顯示為資料夾,單擊會重新載入動態(Url:連結地址)形成無限迴圈。如: tree.json [{ "id":1,
BZOJ 2631 tree 動態樹(Link-Cut-Tree)
數據 val string sta root 樹形 () print access 題目大意:維護一種樹形數據結構。支持下面操作: 1.樹上兩點之間的點權值+k。 2.刪除一條邊。添加一條邊,保證加邊之後還是一棵樹。 3.樹上兩點之間點權值*k。 4.詢問樹上兩點時間點
sqlmap-tamper編寫指南
pos firebird gre message nor quotes .py 代碼 內置 註:最近遇到了一些奇怪的waf,想自己寫一些tamper但是發現沒有參考材料可以使用,因此在寫了這篇文章,一方便進行自定義的tamper編寫。筆者筆力有限,如有錯誤,敬請讀者們指正。
【bzoj4605】嶗山白花蛇草水 權值線段樹套KD-tree
復雜 接下來 efi ora 這也 多少 線段樹 會有 如果 題目描述 神犇Aleph在SDOI Round2前立了一個flag:如果進了省隊,就現場直播喝嶗山白花蛇草水。憑借著神犇Aleph的實力,他輕松地進了山東省省隊,現在便是他履行諾言的時候了。蒟蒻Bob特地為他準
決策樹(Decision Tree)SkLearn
true predict mat ray int lec pytho next() action #!/usr/bin/env python # -*- coding: utf-8 -*- from sklearn.feature_extraction import Di
設備樹(Device Tree)
輸出 mpat vim ring 開源協議 add kernel 匹配 dev 設備樹介紹: 設備樹是一個描述設備硬件資源的文件,該文件是由節點組成的樹形結構。如下: / { node1 { a-string-property = "A string"; a-string-
ARM Linux 3.x的設備樹(Device Tree)宋寶華
3rd else 命名 number 部分 kernel 傳統 rtc trigge 1. ARM Device Tree起源 Linus Torvalds在2011年3月17日的ARM Linux郵件列表宣稱“this whole ARM thing is a f*
【Spark MLlib速成寶典】模型篇05決策樹【Decision Tree】(Python版)
back filter oms sse mlu eval ffffff size red 目錄 決策樹原理 決策樹代碼(Spark Python) 決策樹原理 詳見博文:http://www.cnblogs.com/itmorn/p/79
決策樹(decision tree)
方法 生成算法 ogr np完全 信息熵 cti 標記 ges 樹形 決策樹是一種基本的分類和回歸方法。本章主要討論用於分類的決策樹,決策樹模型呈樹形結構,在分類問題中,表示基於特征對實例進行分類的過程,它可以認為是if-then規則的集合,也可以認為是定義在特征空間與類空
決策樹(decision tree)
from ase size eat for pan ted count import 代碼還好懂,但是後面選擇更好的劃分數據集的方法,有點不知道為什麽那樣選。 還要好好理解推導。 from math import log #計算香農熵 def calcShannonEnt
通達OA應用中心使用手冊(腳本編寫指南)
cit ted 點擊 ble 計算 文本 ppp 必須 組合 腳本編寫必備基礎 1.1 什麽是腳本 腳本是一段 PHP 代碼,可以被應用中心執行以實現特定功能。應用中心支持通過腳本 實現以下功能: 自定義計算函數。 自定義提取觸發
平衡二叉樹Balanced Binary Tree
play trees define 分享圖片 gif gpo -c complex 沒有 [抄題]: Given a binary tree, determine if it is height-balanced. For this problem, a height-ba
矩陣樹定理(Matrix Tree)學習筆記
cstring 相關 () str eof bsp lld open csdn 如果不談證明,稍微有點線代基礎的人都可以在兩分鐘內學完所有相關內容。。 行列式隨便找本線代書看一下基本性質就好了。 學習資源: https://www.cnblogs.com/candy99/p
紅黑樹( Red-Black Tree ) - 筆記
沖突 性能 tro 紅黑樹特性 最短路徑 方式 筆記 nbsp 一個 1. 紅黑樹屬性:根到葉子的路徑中,最長路徑不大於最短路徑的兩倍。 2. 紅黑樹是一個二叉搜索樹,並且有 a. 每個節點除了有左、右、父節點的屬性外,還有顏色屬性,紅色或者黑色。 b. ( 根屬
決策樹(Decision Tree)原理
範圍 思想 選擇 規則 是我 概念 而是 tree 個人 決策樹的思想在生活中很常見,其實就是根據條件去做決定,選擇最符合我們自己東西,例如買房子,我們要考慮的有城市/地段/是否有地鐵/開發商/戶型等等這些因數,這些因數在我們決策樹中就叫做特征,我們就是根據這些特
平衡二叉樹(Balanced Binary Tree 或 Height-Balanced Tree)又稱AVL樹
binary strong 但是 inf ++i 平衡二叉樹 data 效率 assert 平衡二叉樹(Balanced Binary Tree 或 Height-Balanced Tree)又稱AVL樹 (a)和(b)都是排序二叉樹,但是查找(b)的93節點就需要查找6
windows基線編寫指南-powershell版
csdn copy event cedit off https error ping 讀取配置 前言: 因為工作的原因,要寫windows下的基線檢查腳本。之前沒接觸過,在網上找了半天也沒找到現成的,無奈只好自己研究,最後還是成功完成了工作。 在我編寫之後發現wi