最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

微信小程序?qū)崿F(xiàn)可以截?cái)嗟钠俨剂鹘M件的示例代碼

 更新時(shí)間:2022年01月23日 09:30:28   作者:豌豆公主技術(shù)部  
本文主要介紹了微信小程序?qū)崿F(xiàn)可以截?cái)嗟钠俨剂鹘M件

瀑布流是一種常見的布局方式,實(shí)現(xiàn)的方式有許多,比如直接分兩列,然后控制在左右兩列加入元素;還有一種方式就是通過絕對(duì)定位的方式來放置兩邊。本文所要介紹的瀑布流不同于常規(guī)的,因?yàn)槠俨剂髦虚g可能會(huì)被截?cái)啵?/p>

對(duì)于上面的布局,如果強(qiáng)制分成兩列去做布局就不太適合了,因此我采用了絕對(duì)定位的方式來進(jìn)行布局,由于瀑布流中的元素高度都不是固定的,因此我得想辦法獲取到每個(gè)元素的高度,然后判定元素到底是放一整行,還是左側(cè),亦或者右側(cè)。

首先我們來看下模板部分的實(shí)現(xiàn):

<view class="container" style="height:{{height}}px;">
?? ?<view wx:for="{{list}}" wx:key="index" style="{{item.style}}" class="wrapper">
?? ??? ?<abstract item="{{item}}"/>
?? ?</view>
</view>
<view wx:if="{{tmp}}" class="computed-zone">
?? ?<view class="wrapper">
?? ??? ?<abstract item="{{tmp}}"/>
?? ?</view>
</view>

模板比較簡(jiǎn)單,一個(gè) container 容器,然后循環(huán)數(shù)組,平級(jí)渲染出一堆 wrapper 容器。

wrapper 容器是一個(gè)絕對(duì)定位的包裹元素,wrapper 容器里面需要放置需要實(shí)際渲染的組件,為了靈活性更高一點(diǎn),我把這個(gè)渲染組件設(shè)置成了虛擬節(jié)點(diǎn),在使用組件的時(shí)候可以指定實(shí)際渲染的自定義組件。

因?yàn)?wrapper 元素是絕對(duì)定位的,因此我們需要手動(dòng)去維護(hù)整個(gè) container 容器的高度。

這里有個(gè)問題是,我們?cè)趺传@取里面元素的高度呢?模板中的 computed-zone 就是來解決這個(gè)問題的,在將元素放置到數(shù)組之前,我們先把元素在 computed-zone 中進(jìn)行渲染,然后通過 WXML api 來獲取其中元素的實(shí)際渲染尺寸,這樣我們就可以知道這個(gè)元素實(shí)際渲染的寬高度了。

有了每個(gè)元素的渲染尺寸信息之后,我們需要確認(rèn)元素到底是占滿整行,還是占半邊:

  • 如果元素的渲染寬度跟容器一樣,那么就可以判斷這個(gè)元素沾滿一整行,需要將包裹容器 wrapper 設(shè)置為一整行的寬度;
  • 如果不滿足1條件,那么就需要基于左右元素的總高度,將 wrapper 放在左側(cè)或者右側(cè)。

分析下來,需要稍微寫點(diǎn)兒邏輯的就是對(duì) wrapper 計(jì)算偏移量,處理到底放左邊還是放右邊,亦或者占滿整行,核心的代碼實(shí)現(xiàn)如下:

{
?? ?// 將 setData Promise 化,方便使用
?? ?$setData(data) {
?? ??? ?return new Promise(resolve => {
?? ??? ??? ?this.setData(data, () => {
?? ??? ??? ??? ?resolve();
?? ??? ??? ?});
?? ??? ?});
?? ?},
?? ?// 獲取元素的渲染尺寸
?? ?getRect(item) {
?? ??? ?return this.$setData({
?? ??? ??? ?tmp: item,
?? ??? ?}).then(() => {
?? ??? ??? ?return new Promise((resolve, reject) => {
?? ??? ??? ??? ?const query = this.createSelectorQuery(); // 注意要使用 this,不要再使用 wx 前綴了
?? ??? ??? ??? ?query.select('.computed-zone .wrapper').boundingClientRect();
?? ??? ??? ??? ?query.exec(ret => {
?? ??? ??? ??? ??? ?if (ret[0]) {
?? ??? ??? ??? ??? ??? ?resolve(ret[0]);
?? ??? ??? ??? ??? ?} else {
?? ??? ??? ??? ??? ??? ?reject('not found dom!');
?? ??? ??? ??? ??? ?}
?? ??? ??? ??? ?});
?? ??? ??? ?});
?? ??? ?});
?? ?},
?? ?// 添加元素,內(nèi)部使用
?? ?addItem(item) {
?? ??? ?let tick = this.tick;
?? ??? ?return this.getRect(item).then(rect => {
?? ??? ??? ?if (tick !== this.tick) {
?? ??? ??? ??? ?return Promise.reject('tick');
?? ??? ??? ?}
?? ??? ??? ?const { margin } = this.data;
?? ??? ??? ?let { height, width } = rect;
?? ??? ??? ?const windowWidth = this.sysInfo.windowWidth;
?? ??? ??? ?let [ leftTotal, rightTotal ] = this.height; // leftTotal 左側(cè)欄高度,rightTotal 右側(cè)欄高度,
?? ??? ??? ?let marginPx = this.sysInfo.getPx(margin);
?? ??? ??? ?let style = '';

?? ??? ??? ?if (Math.abs(width - windowWidth) < 3) {
?? ??? ??? ??? ?// 占滿屏幕寬度
?? ??? ??? ??? ?style = `left:0;top:${ Math.max(leftTotal, rightTotal) }px;width:100%;`;
?? ??? ??? ??? ?leftTotal = rightTotal = Math.max(leftTotal + height, rightTotal + height);
?? ??? ??? ?} else if (rightTotal < leftTotal) {
?? ??? ??? ??? ?// 放入右邊
?? ??? ??? ??? ?style = `right:${ marginPx }px;top:${ rightTotal }px;`;
?? ??? ??? ??? ?rightTotal += height;
?? ??? ??? ?} else {
?? ??? ??? ??? ?// 放入左邊
?? ??? ??? ??? ?style = `left:${ marginPx }px;top:${ leftTotal }px;`;
?? ??? ??? ??? ?leftTotal += height;
?? ??? ??? ?}

?? ??? ??? ?const { list = [] } = this.data;
?? ??? ??? ?const targetKey = `list[${list.length}]`; // 利用直接操作數(shù)組下標(biāo)的方式來觸發(fā)數(shù)組修改,性能有很大提升
?? ??? ??? ?this.height = [leftTotal, rightTotal]; // 記錄最新的左右側(cè)高度
?? ??? ??? ?return this.$setData({
?? ??? ??? ??? ?[targetKey]: {
?? ??? ??? ??? ??? ?data: item,
?? ??? ??? ??? ??? ?style,
?? ??? ??? ??? ?},
?? ??? ??? ??? ?height: Math.max(leftTotal, rightTotal),
?? ??? ??? ?});
?? ??? ?});
?? ?},
?? ?// 實(shí)際添加元素使用,自建Promise隊(duì)列,保證順序一致
?? ?add(item) {
?? ??? ?let pending = this.pending || Promise.resolve();
?? ??? ?return this.pending = pending.then(() => {
?? ??? ??? ?return this.addItem(item);
?? ??? ?}).catch(err => {
?? ??? ??? ?console.error(err);
?? ??? ??? ?this.pending = null;
?? ??? ??? ?throw err;
?? ??? ?});
?? ?},
?? ?clear() {
?? ??? ?this.tick = tick++;
?? ??? ?this.height = [0, 0];
?? ??? ?this.pending = null;
?? ??? ?this.setData({
?? ??? ??? ?list: [],
?? ??? ??? ?height: 0,
?? ??? ?});
?? ?},
}

在使用該組件的時(shí)候我們就不能直接通過賦值數(shù)組的方式來渲染元素了,而是得通過組件實(shí)例方法add(item) 的方式,因?yàn)槲覍?shí)現(xiàn)了隊(duì)列,因此可以直接循環(huán) add 就行。如果關(guān)心狀態(tài)就判斷最后一個(gè)元素的 add 操作是否完成即可。

通過這種方式來實(shí)現(xiàn)的瀑布流靈活性相對(duì)較高,但是性能消耗也是不低的,需要挨個(gè)獲取元素的實(shí)際渲染尺寸,如果要支持窗口的resize的話,那消耗是恐怖。

對(duì)于需要看代碼細(xì)節(jié)的同學(xué),我將實(shí)際的demo放到了 Github 微信代碼片段,有需要的同學(xué)可以試一試。

基于上面的模型,其實(shí)也可以優(yōu)化成只渲染可視區(qū)范圍內(nèi)的元素,可以大大提升瀑布流的性能 

到此這篇關(guān)于微信小程序?qū)崿F(xiàn)可以截?cái)嗟钠俨剂鹘M件的示例代碼的文章就介紹到這了,更多相關(guān)小程序截?cái)嗟钠俨剂鹘M件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

宕昌县| 孙吴县| 腾冲县| 江西省| 丹凤县| 稻城县| 崇信县| 都昌县| 苍南县| 察雅县| 特克斯县| 中方县| 浮梁县| 武邑县| 黎城县| 枞阳县| 堆龙德庆县| 肥西县| 琼中| 永年县| 沂南县| 农安县| 景谷| 金坛市| 正阳县| 贵阳市| 苏州市| 龙江县| 乌兰县| 濮阳县| 噶尔县| 通化县| 定南县| 全椒县| 迁安市| 东莞市| 淮南市| 蕲春县| 兖州市| 新宾| 白河县|