真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

element中ScrollBar滾動(dòng)組件怎么用-創(chuàng)新互聯(lián)

這篇文章將為大家詳細(xì)講解有關(guān)element中ScrollBar滾動(dòng)組件怎么用,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。

創(chuàng)新互聯(lián)公司主要從事成都做網(wǎng)站、成都網(wǎng)站制作、成都外貿(mào)網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)新絳,十多年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):18980820575

scrollbar組件根目錄下包括index.js文件和src文件夾,index.js是用來注冊(cè)Vue插件的地方,沒什么好說的,不了解的童鞋可以看一下Vue官方文檔中的插件,src目錄下的內(nèi)容才是scrollbar組件的核心代碼,其入口文件是main.js。

在開始分析源碼之前,我們先來說一下自定義滾動(dòng)條的原理,方便大家更好的理解。

element中ScrollBar滾動(dòng)組件怎么用

如圖,黑色wrap為滾動(dòng)的可顯示區(qū)域,我們的滾動(dòng)內(nèi)容就是在這個(gè)區(qū)域中滾動(dòng),view是實(shí)際的滾動(dòng)內(nèi)容,超出wrap可顯示區(qū)域的內(nèi)容都將被隱藏。右側(cè)track是滾動(dòng)條的滾動(dòng)滑塊thumb上下滾動(dòng)的軌跡

當(dāng)wrap中的內(nèi)容溢出的時(shí)候,就會(huì)產(chǎn)生各瀏覽器的原生滾動(dòng)條,要實(shí)現(xiàn)自定義滾動(dòng)條,我們必須將原生滾動(dòng)條消滅掉。假設(shè)我們給wrap外面再包一層div,并且把這個(gè)div的樣式設(shè)為 overflow:hidden ,同時(shí)我們給wrap的marginRight,marginBottom設(shè)置一個(gè)負(fù)值,值得大小正好等于原生滾動(dòng)條的寬度,那么這個(gè)時(shí)候由于父容器的overflow:hidden屬性,正好就可以將原生滾動(dòng)條隱藏掉。然后我們?cè)賹⒆远x的滾動(dòng)條絕對(duì)定位到wrap容器的右側(cè)和下側(cè),并加上滾動(dòng)、拖拽事件等滾動(dòng)邏輯,就可以實(shí)現(xiàn)自定義滾動(dòng)條了。

接下來我們從main.js入口開始,詳細(xì)分析一下element是如何實(shí)現(xiàn)這些邏輯的。

main.js文件中直接導(dǎo)出一個(gè)對(duì)象,這個(gè)對(duì)象采用render函數(shù)的方式渲染scrollbar組件,組件對(duì)外暴漏的接口如下:

props: {
 native: Boolean, // 是否采用原生滾動(dòng)(即只是隱藏掉了原生滾動(dòng)條,但并沒有使用自定義的滾動(dòng)條)
 wrapStyle: {}, // 內(nèi)聯(lián)方式 自定義wrap容器的樣式
 wrapClass: {}, // 類名方式 自定義wrap容器的樣式
 viewClass: {}, // 內(nèi)聯(lián)方式 自定義view容器的樣式
 viewStyle: {}, // 類名方式 自定義view容器的樣式
 noresize: Boolean, // 如果 container 尺寸不會(huì)發(fā)生變化,最好設(shè)置它可以優(yōu)化性能
 tag: { 				// view容器用那種標(biāo)簽渲染,默認(rèn)為div
 type: String,
 default: 'div'
 }
}

可以看到,這就是整個(gè)ScrollBar組件對(duì)外暴露的接口,主要包括了自定義wrap,view樣式的接口,以及用來優(yōu)化性能的noresize接口。

然后我們?cè)賮矸治鲆幌聄ender函數(shù):

render(){
	let gutter = scrollbarWidth(); // 通過scrollbarWidth()方法 獲取瀏覽器原生滾動(dòng)條的寬度
 let style = this.wrapStyle;

 if (gutter) {
 const gutterWith = `-${gutter}px`;
 
 // 定義即將應(yīng)用到wrap容器上的marginBottom和marginRight,值為上面求出的瀏覽器滾動(dòng)條寬度的負(fù)值
 const gutterStyle = `margin-bottom: ${gutterWith}; margin-right: ${gutterWith};`;

 // 這一部分主要是根據(jù)接口wrapStyle傳入樣式的數(shù)據(jù)類型來處理style,最終得到的style可能是對(duì)象或者字符串
 if (Array.isArray(this.wrapStyle)) {
  style = toObject(this.wrapStyle);
  style.marginRight = style.marginBottom = gutterWith;
 } else if (typeof this.wrapStyle === 'string') {
  style += gutterStyle;
 } else {
  style = gutterStyle;
 }
 }
 
 ...
}

這一塊代碼中最重要的知識(shí)點(diǎn)就是獲取瀏覽器原生滾動(dòng)條寬度的方式了,為此element專門定義了一個(gè)方法scrllbarWidth,這個(gè)方法是從外部導(dǎo)入進(jìn)來的 import scrollbarWidth from 'element-ui/src/utils/scrollbar-width'; ,我們一起來看一下這個(gè)函數(shù):

import Vue from 'vue';

let scrollBarWidth;

export default function() {
 if (Vue.prototype.$isServer) return 0;
 if (scrollBarWidth !== undefined) return scrollBarWidth;

 const outer = document.createElement('div');
 outer.className = 'el-scrollbar__wrap';
 outer.style.visibility = 'hidden';
 outer.style.width = '100px';
 outer.style.position = 'absolute';
 outer.style.top = '-9999px';
 document.body.appendChild(outer);

 const widthNoScroll = outer.offsetWidth;
 outer.style.overflow = 'scroll';

 const inner = document.createElement('div');
 inner.style.width = '100%';
 outer.appendChild(inner);

 const widthWithScroll = inner.offsetWidth;
 outer.parentNode.removeChild(outer);
 scrollBarWidth = widthNoScroll - widthWithScroll;

 return scrollBarWidth;
};

其實(shí)也很簡(jiǎn)單,就是動(dòng)態(tài)創(chuàng)建一個(gè)body的子元素outer,給固定寬度100px,并且將overflow設(shè)置為scroll,這樣wrap就產(chǎn)生滾動(dòng)條了,這個(gè)時(shí)候再動(dòng)態(tài)創(chuàng)建一個(gè)outer的子元素inner,將其寬度設(shè)置為100%。由于outer有滾動(dòng)條存在,inner的寬度必然不可能等于outer的寬度,此時(shí)用outer的寬度減去inner的寬度,得出的就是瀏覽器滾動(dòng)條的寬度了。是不是也很簡(jiǎn)單啊,最后記得從body中銷毀動(dòng)態(tài)創(chuàng)建outer元素哦。

回過頭來我們接著看render函數(shù),在根據(jù)瀏覽器滾動(dòng)條寬度及wrapStyle動(dòng)態(tài)生成樣式變量style之后,接下來就是在render函數(shù)中生成ScrollBar組件的 HTML了。

// 生成view節(jié)點(diǎn),并且將默認(rèn)slots內(nèi)容插入到view節(jié)點(diǎn)下
const view = h(this.tag, {
 class: ['el-scrollbar__view', this.viewClass],
 style: this.viewStyle,
 ref: 'resize'
}, this.$slots.default);

// 生成wrap節(jié)點(diǎn),并且給wrap綁定scroll事件
const wrap = (
 
  { [view] }
);

接著是根據(jù)native來組裝wrap,view生成整個(gè)HTML節(jié)點(diǎn)樹了。

let nodes;

if (!this.native) {
 nodes = ([
 wrap,
 ,
		
	]);
} else {
 nodes = ([
 
   { [view] }
]); } return h('div', { class: 'el-scrollbar' }, nodes);

可以看到如果native為false,則使用自定義的滾動(dòng)條,如果為true,則不使用自定義滾動(dòng)條。簡(jiǎn)化上面的render函數(shù)生成的HTML如下:


 
 
 	this.$slots.default
 
 
   

最外層的el-scrollbar設(shè)置了overflow:hidden,用來隱藏wrap中產(chǎn)生的瀏覽器原生滾動(dòng)條。使用ScrollBar組建時(shí),寫在ScrollBar組件中的內(nèi)容都將通過slot分發(fā)到view內(nèi)部。另外這里使用move,size和vertical三個(gè)接口調(diào)用了Bar組件,這個(gè)組件就是原理圖上的Track和Thumb了。下面我們來看一下Bar組件:

props: {
 vertical: Boolean, // 當(dāng)前Bar組件是否為垂直滾動(dòng)條
 size: String, // 百分?jǐn)?shù),當(dāng)前Bar組件的thumb長(zhǎng)度 / track長(zhǎng)度的百分比 
 move: Number // 滾動(dòng)條向下/向右發(fā)生transform: translate的值
},

Bar組件的行為都是由這三個(gè)接口來進(jìn)行控制的,在前面的分析中,我們可以看到,在scrollbar中調(diào)用Bar組件時(shí),分別傳入了這三個(gè)props。那么父組件是如何初始化以及更新這三個(gè)參數(shù)的值,從而達(dá)到更新Bar組件的呢。首先在mounted鉤子中調(diào)用update方法對(duì)size進(jìn)行初始化:

update() {
 let heightPercentage, widthPercentage;
 const wrap = this.wrap;
 if (!wrap) return;

 heightPercentage = (wrap.clientHeight * 100 / wrap.scrollHeight);
 widthPercentage = (wrap.clientWidth * 100 / wrap.scrollWidth);

 this.sizeHeight = (heightPercentage < 100) ? (heightPercentage + '%') : '';
 this.sizeWidth = (widthPercentage < 100) ? (widthPercentage + '%') : '';
}

可以看到,這里核心的內(nèi)容就是計(jì)算thumb的長(zhǎng)度heightPercentage/widthPercentage。這里使用wrap.clientHeight / wrap.scrollHeight得出了thumb長(zhǎng)度的百分比。這是為什么呢

分析前面我們畫的那張scrollbar的原理圖,thumb在track中上下滾動(dòng),可滾動(dòng)區(qū)域view在可視區(qū)域wrap中上下滾動(dòng),可以將thumb和track的這種相對(duì)關(guān)系看作是wrap和view相對(duì)關(guān)系的一個(gè) 微縮模型 (微縮反應(yīng)),而滾動(dòng)條的意義就是用來反映view和wrap的這種相對(duì)運(yùn)動(dòng)關(guān)系的。從另一個(gè)角度,我們可以將view在wrap中的滾動(dòng)反過來看成是wrap在view中的上下滾動(dòng),這不就是一個(gè)放大版的滾動(dòng)條嗎?

根據(jù)這種相似性,我們可以得出一個(gè)比例關(guān)系: wrap.clientHeight / wrap.scrollHeight = thumb.clientHeight / track.clientHeight。在這里,我們并不需要求出具體的thumb.clientHeight的值,只需要根據(jù)thumb.clientHeight / track.clientHeight的比值,來設(shè)置thumb 的css高度的百分比就可以了。

另外還有一個(gè)需要注意的地方,就是當(dāng)這個(gè)比值大于等于100%的時(shí)候,也就是wrap.clientHeight(容器高度)大于等于 wrap.scrollHeight(滾動(dòng)高度)的時(shí)候,此時(shí)就不需要滾動(dòng)條了,因此將size置為空字符串。

接下來我們?cè)賮砜匆幌耺ove,也就是滾動(dòng)條滾動(dòng)位置的更新。

handleScroll() {
 const wrap = this.wrap;

 this.moveY = ((wrap.scrollTop * 100) / wrap.clientHeight);
 this.moveX = ((wrap.scrollLeft * 100) / wrap.clientWidth);
}

moveX/moveY用來控制滾動(dòng)條的滾動(dòng)位置,當(dāng)這個(gè)值傳給Bar組件時(shí),Bar組件render函數(shù)中會(huì)調(diào)用 renderThumbStyle 方法將它轉(zhuǎn)化為trumb的樣式 transform: translateX(${moveX}%) / transform: translateY(${moveY}%) 。由之前分析的相似關(guān)系可知,當(dāng)wrap.scrollTop正好等于wrap.clientHeight的時(shí)候,此時(shí)thumb應(yīng)該向下滾動(dòng)它自身長(zhǎng)度的距離,也就是transform: translateY(100%)。所以,當(dāng)wrap滾動(dòng)的時(shí)候,thumb應(yīng)該向下滾動(dòng)的距離正好是 transform: translateY(wrap.scrollTop / wrap.clientHeight )。這就是wrap滾動(dòng)函數(shù)handleScroll中的邏輯所在。

現(xiàn)在我們已經(jīng)完全弄清楚了scrollbar組件中的所有邏輯,接下來我們?cè)倏纯碆ar組件在接收到props之后是如何處理的。

render(h) {
 const { size, move, bar } = this;

 return (
 
  
  
 
 ); }

render函數(shù)獲取父組件傳遞的size,move之后,通過 renderThumbStyle 來生成thumb,并且給track和thumb分別綁定了onMousedown事件。

clickThumbHandler(e) {
 this.startDrag(e);
 // 記錄this.y , this.y = 鼠標(biāo)按下點(diǎn)到thumb底部的距離
 // 記錄this.x , this.x = 鼠標(biāo)按下點(diǎn)到thumb左側(cè)的距離
 this[this.bar.axis] = (e.currentTarget[this.bar.offset] - (e[this.bar.client] - e.currentTarget.getBoundingClientRect()[this.bar.direction]));
},
 
// 開始拖拽函數(shù)
startDrag(e) {
 e.stopImmediatePropagation();
 // 標(biāo)識(shí)位, 標(biāo)識(shí)當(dāng)前開始拖拽
 this.cursorDown = true;

 // 綁定mousemove和mouseup事件
 on(document, 'mousemove', this.mouseMoveDocumentHandler);
 on(document, 'mouseup', this.mouseUpDocumentHandler);
 
 // 解決拖動(dòng)過程中頁(yè)面內(nèi)容選中的bug
 document.onselectstart = () => false;
},
 
mouseMoveDocumentHandler(e) {
 // 判斷是否在拖拽過程中,
 if (this.cursorDown === false) return;
 // 剛剛記錄的this.y(this.x) 的值
 const prevPage = this[this.bar.axis];

 if (!prevPage) return;

 // 鼠標(biāo)按下的位置在track中的偏移量,即鼠標(biāo)按下點(diǎn)到track頂部(左側(cè))的距離
 const offset = ((this.$el.getBoundingClientRect()[this.bar.direction] - e[this.bar.client]) * -1);
 // 鼠標(biāo)按下點(diǎn)到thumb頂部(左側(cè))的距離
 const thumbClickPosition = (this.$refs.thumb[this.bar.offset] - prevPage);
 // 當(dāng)前thumb頂部(左側(cè))到track頂部(左側(cè))的距離,即thumb向下(向右)偏移的距離 占track高度(寬度)的百分比
 const thumbPositionPercentage = ((offset - thumbClickPosition) * 100 / this.$el[this.bar.offset]);
	// wrap.scrollHeight / wrap.scrollLeft * thumbPositionPercentage得到wrap.scrollTop / wrap.scrollLeft
 // 當(dāng)wrap.scrollTop(wrap.scrollLeft)發(fā)生變化的時(shí)候,會(huì)觸發(fā)父組件wrap上綁定的onScroll事件,
 // 從而重新計(jì)算moveX/moveY的值,這樣thumb的滾動(dòng)位置就會(huì)重新渲染
 this.wrap[this.bar.scroll] = (thumbPositionPercentage * this.wrap[this.bar.scrollSize] / 100);
},

mouseUpDocumentHandler(e) {
 // 當(dāng)拖動(dòng)結(jié)束,將標(biāo)識(shí)位設(shè)為false
 this.cursorDown = false;
 // 將上一次拖動(dòng)記錄的this.y(this.x)的值清空
 this[this.bar.axis] = 0;
 // 取消頁(yè)面綁定的mousemove事件
 off(document, 'mousemove', this.mouseMoveDocumentHandler);
 // 清空onselectstart事件綁定的函數(shù)
 document.onselectstart = null;
}

上面的代碼就是thumb滾動(dòng)條拖拽的所有處理邏輯,整體思路就是在拖拽thumb的過程中,動(dòng)態(tài)的計(jì)算thumb頂部(左側(cè))到track頂部(左側(cè))的距離占track本身高度(寬度)的百分比,然后利用這個(gè)百分比動(dòng)態(tài)改變wrap.scrollTop的值,從而觸發(fā)頁(yè)面滾動(dòng)以及滾動(dòng)條位置的重新計(jì)算,實(shí)現(xiàn)滾動(dòng)效果。

element中ScrollBar滾動(dòng)組件怎么用

上一個(gè)圖方便大家理解吧( ̄▽ ̄)"

關(guān)于“element中ScrollBar滾動(dòng)組件怎么用”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。


當(dāng)前文章:element中ScrollBar滾動(dòng)組件怎么用-創(chuàng)新互聯(lián)
文章位置:http://weahome.cn/article/pdiij.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部