vueコンポーネントのtableテーブル

19913 ワード

tableテーブルコンポーネントプレビューアドレス(展示公式サイトは略カードで、最初はロードしにくい)
vueベースでtableコンポーネントを書く
当面のところ完成予定の機能
  • 固定ヘッダ
  • 固定列
  • 固定ソート、ソート関数を受け入れ、バックエンドソート
  • を要求する
  • リクエスト時期のアニメーション
  • 複数選択ボックス
  • 展開行
  • 構造とapiはAntDesignの
     "columns1"
     :data="data">
     
    

    api設計:
  • data、表示されるテーブルデータは、配列であり、配列内の各オブジェクトには、keyを確認するために一意のindexが必要です.
  • {key:1,name:'JavaScript',price:80,year:12},
    
  • columnsヘッダ、内の属性名はdata内の属性名に対応します.
  •           columns1:[
                    {text:'  ',field:'name'},
                    {text:'  ',field:'price'},
                    {text:'  ',field:'year'},
                ],
    

    固定ヘッダー
    効果は図のようだ
    実現原理と構造
    残念なことにtableの頭部はcssだけで固定できず、これは非常に特殊です.そこで、ここを2つの部分、bodyheaderに分けます.headerは斬新なtableであり、このtableアセンブリの中にはしかなく、bodyの頭部を絶対的に位置決めすることによって、頭部を固定する目的を達成する.
    
    

    Api設計と幅の制御
    まず、頭部を固定するには、maxHeightという最大の高さが必要です.
            "columns1"
                     :data="data"
                     //.....
                     maxHeight="300"
            >
            
    

    ここでヘッダ部のtableは、bodyがないため、2つのtableに対応する各格子の幅が異なるため、位置合わせの問題が生じ、固定幅が必要となる.columnsから入力された各データにwidthを加えることは、各列の対応する格子の幅を意味する.
                   columns1:[
                        {text:'  ',field:'name',width:200},
                        ],
    

    今どのように格子の幅を制御して、穴を踏み始めたとき、私はjsで .style.widthに値を割り当てましたが、このようなやり方は全くできません.WebページでelementUI tableコンポーネントのHTML構造をチェックしたところ、colgroupで作りました.
                   
                     "(column,index) in columns" :key="index" :style="{width:`${column.width}px`}">
                   
    

    ここではcheckBoxの影響も考慮しなければならない.これは後述する.
    その後、絶対位置決めで上を覆うことができます.
                position: absolute;
                left: 0;
                top: 0;
    

    最大高さを固定し、超えた部分はスクロール可能
    まず、tableの外層は、最大高さを制御するためにdivの層を包む必要がある.css:overflow:auto;を設定します.`
    固定列
    実現原理は固定頭部と似ているが,複雑であることが多い.固定列は左固定と右固定に分けられ、ユーザーが設定する必要があります.つまり
            columns1:[
                {.......,fixed:'left'},
                {........,fixed:'right'},
            ],
    

    すべてのfixed:'left'は左側に、fixed:'right'は右側に置かれています.今では全体が3つの部分に分けることができます.左列固定、中間スクロール領域、右列固定.
    3つの部分のヘッダ配列収集
    3つの部分の配列を収集し,格子のtableの中を遍歴した.
         '    '(){
               let [left,right,main] = [[],[],[]]
                    this.columns.forEach(item=>{
                      [item.fixed].push(item)
                    })
                        this.fixedLeft = left.concat(main,right)
                        this.fixedRight = right.concat(main,left)
                        this.scrollArea = left.concat(main,right)
         }
                    
    
    concat対でつなぎ合わせると、外層divに包まれたときにmaxWidthoverflow:hiddenで表示されている部分を直接切り取ることができます.
    
                    //    
                       '  '>
                            "width: 60px">
                                "(column,index) in fixedLeft" :key="index" :style="{width:`${column.width}px`}">
                            
                             //.....
                                
    "column in fixedLeft" :key="column.field"> {{column.text}}
    // ' '> "width: 60px"> "(column,index) in fixedLeft" :key="index" :style="{width:`${column.width}px`}"> //.....
    "column in fixedLeft" :key="column.field"> {{column.text}}
    // ' '> "width: 60px"> "(column,index) in fixedLeft" :key="index" :style="{width:`${column.width}px`}"> //.....
    "column in fixedLeft" :key="column.field"> {{column.text}}

    横スクロールtableの幅は、外側divのラップ層の幅によって影響されることに注意されたい.だから最初からtableの幅を固定する必要があります.次に、親にmaxWidthを与えます.
        setMainWidth(){
                let [width,$refs] = [getComputedStyle(this.$refs.table).width,this.$refs]
                $refs.table.style.width = width
                $refs.wrapper.style.width = this.maxWidth +'px'
                  //......
        },
    

    結合固定ヘッド
    列を固定しながら頭部を固定することも考えられるので、左右の構造はこれまでとほぼ同じです
    "main">
    "left">
    "right">

    css , 。

    • checkbox, ,CheckBox 。
    • colgroup CheckBox 。
    • 。( , )

    hover

    hover

              hoverChangeBg(index,e){
                  let typeName = {
                      mouseenter:'#FCF9F9',
                      mouseleave:''
                  }
                  this.$refs.trMain[index].style.backgroundColor = typeName[e.type]
                  if(this.fixedLeft.length>0){
                      this.$refs.trLeft[index].style.backgroundColor = typeName[e.type]
                  }
                  if(this.fixedRight.length>0){
                      this.$refs.trRight[index].style.backgroundColor = typeName[e.type]
                  }
              },
    
    はスクロールバーの さの を し、 とカバー
  • まず の のスクロールバーを す
  • .
                '           '{
                      &::-webkit-scrollbar{
                      display: none;
                  }
                  -ms-overflow-style: none;
                  scrollbar-width: none;
                  -ms-overflow-style: none;
                  overflow: -moz-scrollbars-none;
                }
                //  chrome,firefox IE(?)         。
    
  • に の が め に
  • が .
    position:absolute;
    right:0;
    top:0;
    
    は、 スクロール の スクロールバーを う.
  • はスクロールバーの さを し、 の の さからその さ( に すように)を し、なければ0とする.
  •             '            '(){
                     const scrollBar = document.createElement('div')
                         let style = {
                             height:'50px',
                             overflow:'scroll',
                             position:'absolute',
                             top:'-9999px',
                             width:'50px'
                         }
                          Object.keys(style).forEach(item=>{
                             scrollBar.style[item]=style[item]
                          })
                          document.body.appendChild(scrollBar)
                          this.scrollBarWidth= scrollBar.offsetWidth - scrollBar.clientWidth
                          document.body.removeChild(scrollBar)
       }
    
    この の の については、しばらく されていません. スクロールの も な は、まだ に されていませんが、 にはelementUIにも し があります.まず の を します. の み( ): はmouserwheelを して したが、 に があった.ブラウザが
    const isFirefox = typeof navigator !== 'undefined' && navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
    
    であるかどうかを し、mouserwheelまたは のDOMMouseScrollを する.もちろん、 の はbeforeDestroyフックから する があります.
    const mousewheel = function(element, callback,name) {
        if (element && element.addEventListener) {
            element.addEventListener(isFirefox ? 'DOMMouseScroll' : 'mousewheel', function(event) {
                callback && callback.apply(this, [event,name]);
            });
        }
    };
    
    export default {
        bind(el, binding,name) {
            mousewheel(el, binding.value,name);
        }
    };
    
    
    deltaYで の2つの のscrollTopを すると えられていますが、 にはこれ(かなりの )はなく、いくつかのライブラリのサポートが です. するに、 の き は、 の
    '         '.scrollTop += e.deltaY
    
    のように かれているだけで があります.ローラーの 、ターゲット が ずしも がっているとは りません. またはwindowかもしれませんが、mousewheelイベントがトリガーされます.これで のシフトが します.その 、nつの 、
    '         '.scrollTop += e.deltaY
    'wheel    '.scrollTop  += e.deltaY
    
    の 2の :オリジナルのscrollイベントを いて、scrollTop
    '         '.scrollTop = scrollTop
    
    を うには、3つの のscrollイベントを する があるが、そのうちの1つがscrollイベントをトリガーすると、 の2つのscrollTopが され、その 、 の2つの のscrollイベントがトリガーされる.すなわち,リスニング び しが じ であると すると,この は1 ロールアップすると3 び される.(Chrome のブラウザで に トリガされる が く、これもスクロールが い です)この 、chrome のブラウザではスクロールが に いです. している2つの :
  • は、 のaddEventListenerおよびremoveEventListenerを する. scrollTopは、 を してから する.
  • は、hoverの を し、hoverの のみがscrollをトリガすることができる.
  •              scrollGradient(part){
                  if(part!=='  hover   ')return
                    let position = {
                        left:[`tableLeftWrapper`,`tableMainWrapper`,`tableRightWrapper`],
                        main:[`tableMainWrapper`,`tableLeftWrapper`,`tableRightWrapper`],
                        right:[`tableRightWrapper`,`tableMainWrapper`,`tableLeftWrapper`],
                    }
                    let scrollTop = this.$refs[position[part][0]].scrollTop
                    //........
                    }
    
  • にpc でスクロールバーをスクロールするときにマウスもスクロールバーを する に かぶので、この は ないように えます.しかし、 のプログラムを ている は、hoverページはトリガーされず、returnになります.

  • また、mousewheelの が ずしもスクロールするとは らない があります. の ( えばwindow)の の かもしれません.scrollTopを するたびに をし、scrollGradientをトリガーするたびに、 の のscrollTopが のscrollTopに しいかどうかを し、returnです.これにより、ある がスクロールして の のscrollTopを するたびに、 の がないことが されます.スクロールずれは スクロールの で、 のscrollTopを することによってscrollの またはa をスクロールすると に、スクロールb を に り え、コールバックをトリガーしてa のscrollTopを することは けられない.これは
  • ローカルにレンダリングされていないか、 されていないなど、 くの ずれや が します.
  • の めて いオーバーヘッドは、カートンのフレームダウンによる い です.

  • した
  • pointer-events:none( なし)
  • vueのpassive( なし)
  • div (かえってバグ)
  • の れ と り( やかな がり が なため、 はあまり していない)が、 がり は である.
  • Firefoxでは、1 のスクロールで トリガされ、 なスクロール があり、 バグはほとんど しません.
  • (elementソースコードを してください)は、 のmousewheelを し、 スクロール のscrollTopを し、 スクロール によって のscrollTopを させる.(バグは として れるが、 はかなり ない)
  • に、 および パッケージ は、Firefoxにおいて、3つの をリスニングするscrollを し、そのうちの1つのscrollTopを いて の scrollTopを する の である. のブラウザは、 の のmouserwheelイベントを し、 のwheelを する. スクロール のscrollTopを し、その 、 のscrollTopに を り てて3つの を する. は、いくつかの なスクロール り えの において、 の をスクロールしながら のscrollTopを び する を することである.この は かに の を した.
    //    
    const isFirefox = typeof navigator !== 'undefined' && navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
    const data={
        currentScrollLeft:0,
        currentScrollTop:0,
    }
    const wheel =  function fixedWheel(e,target,scrollArea){
        //Chrome
        //....
        event.preventDefault()
        '      '.scrollTop += e.deltaY
        //....
    }
    
    const scroll = function (event,el,partArr) {
    //Firefox
       let {scrollTop} = el
        if(data.currentScrollTop===scrollTop)return
        //....
           this.$refs.tableMain.classList.remove('transformClass')
                window.requestAnimationFrame(()=>{
                //'          '
                  '      '&&'     '.scrollTop = scrollTop//          ,           
                       window.requestAnimationFrame(()=>{
                            this.$refs.'      '.classList.add('transformClass')
                        })
                   })
    }
    const xScroll = function('    ') {
        if (el && el.addEventListener) {
             el.addEventListener(!isFirefox?'mousewheel':'scroll', function(event) {
                 !isFirefox && wheel.apply(this, ['    '])
                 isFirefox && scroll.apply(this, ['    '])
            })
        }
    }
    
    export default {
        bind(el, binding,name) {
            xScroll('    ');
        },
        data
    };
    
    
    を する は
    
    import xScroll from './    '
        export default {
            directives:{
                xScroll
            },
    
    の の だけです. のtableコンポーネントは で、 があるところは してほしいです. に、 かましくほめてください.もしあなたがまだいいと ったら、ははは. :https://juejin.im/post/5cceb057f265da03474e1421