vueコンポーネントのtableテーブル
19913 ワード
tableテーブルコンポーネントプレビューアドレス(展示公式サイトは略カードで、最初はロードしにくい)
vueベースでtableコンポーネントを書く
当面のところ完成予定の機能固定ヘッダ 固定列 固定ソート、ソート関数を受け入れ、バックエンドソート を要求するリクエスト時期のアニメーション 複数選択ボックス 展開行 構造とapiはAntDesignの
api設計: data、表示されるテーブルデータは、配列であり、配列内の各オブジェクトには、 columnsヘッダ、内の属性名は
固定ヘッダー
効果は図のようだ
実現原理と構造
残念なことに
Api設計と幅の制御
まず、頭部を固定するには、
ここでヘッダ部の
今どのように格子の幅を制御して、穴を踏み始めたとき、私はjsで
ここでは
その後、絶対位置決めで上を覆うことができます.
最大高さを固定し、超えた部分はスクロール可能
まず、
固定列
実現原理は固定頭部と似ているが,複雑であることが多い.固定列は左固定と右固定に分けられ、ユーザーが設定する必要があります.つまり
すべての
3つの部分のヘッダ配列収集
3つの部分の配列を収集し,格子の
横スクロール
結合固定ヘッド
列を固定しながら頭部を固定することも考えられるので、左右の構造はこれまでとほぼ同じです
vueベースでtableコンポーネントを書く
当面のところ完成予定の機能
"columns1"
:data="data">
api設計:
key
を確認するために一意のindex
が必要です.{key:1,name:'JavaScript',price:80,year:12},
data
内の属性名に対応します. columns1:[
{text:' ',field:'name'},
{text:' ',field:'price'},
{text:' ',field:'year'},
],
固定ヘッダー
効果は図のようだ
実現原理と構造
残念なことに
table
の頭部はcssだけで固定できず、これは非常に特殊です.そこで、ここを2つの部分、body
とheader
に分けます.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
に包まれたときにmaxWidth
とoverflow: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