<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      代碼改變世界

      Omi樹組件omi-tree編寫指南

      2017-05-02 14:53  【當耐特】  閱讀(1397)  評論(0)    收藏  舉報

      Omi框架能夠以少量的代碼聲明式地編寫可拖拽移動節點的樹形組件。
      通常樹組件能夠考驗UI框架的健壯性,因為需要使用到UI框架的如下特性:

      • 組件嵌套
      • 組件傳值
      • 組件批量傳值
      • 組件依賴自身遞歸嵌套(nest-self)
      • 子、孫或炎黃子孫訪問根組件實例

      下面來介紹下使用 omi-tree 的開發全過程。你也可以無視文章,先體驗一把和直接編輯源碼試一把:

      omi-tree playground

      類劃分

      • 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相關

      主站蜘蛛池模板: 少妇粗大进出白浆嘿嘿视频| 日韩成人福利视频在线观看| 人妻一本久道久久综合鬼色| 蜜桃草视频免费在线观看 | 久久综合色之久久综合色| 国产精品夜夜春夜夜爽久久小说| 99中文字幕精品国产| 永久无码天堂网小说区| 日本一区二区三区免费播放视频站| 国产麻豆成人传媒免费观看| 国产精品粉嫩嫩在线观看| 国产特级毛片aaaaaa毛片| 奇米777四色在线精品| 国产69精品久久久久人妻刘玥| 美女内射福利大全在线看| 无码内射中文字幕岛国片| 欧美18videosex性欧美黑吊| 精品日本免费一区二区三区| 国产无遮挡又黄又爽不要vip软件 国产成人精品一区二区秒拍1o | 午夜福利国产盗摄久久性| 777米奇色狠狠俺去啦| 国产精品久久久久久妇女| 免费观看全黄做爰大片| 成在人线av无码免费| 成人亚洲狠狠一二三四区| 成人亚洲av免费在线| 亚洲成人一区二区av| 午夜成人性爽爽免费视频| 人人综合亚洲无线码另类| 久久久久免费看成人影片| 日本高清在线观看WWW色| 国偷自产av一区二区三区| 国产在线视频精品视频| 亚洲一区二区中文字幕| 日本少妇xxx做受| 亚洲欧美日韩综合一区二区| 免费无码一区无码东京热| 亚洲国产精品久久久天堂麻豆宅男| 久久99久久99精品免观看| 无码国产69精品久久久久网站| 湄潭县|