


Let's talk about how to implement a truncated waterfall flow component in a small program
How to implement a truncated waterfall flow component in a small program? The following article will introduce to you how to implement a WeChat applet that can cut off waterfall flow components. I hope it will be helpful to you!
Waterfall flow is a common layout method. There are many ways to implement it, such as dividing it into two columns directly, and then controlling the addition of elements in the left and right columns; there is another way It is to place both sides through absolute positioning. [Related learning recommendations: 小program development tutorial]
The waterfall flow to be introduced in this article is different from the conventional one, because the waterfall flow may be truncated in the middle:
For the above layout, it is not suitable to force the layout into two columns, so I used absolute positioning for layout. Since the height of the elements in the waterfall flow is not fixed, Therefore, I have to find a way to get the height of each element, and then determine whether the element should be placed on the entire row, on the left, or on the right.
First let's look at the implementation of the template part:
<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>
The template is relatively simple, a container
container, then loops the array, and renders a bunch of horizontally wrapper
Container.
wrapper
The container is an absolutely positioned wrapping element. wrapper
The container needs to place components that need to be actually rendered. For greater flexibility, I render this The component is set as a virtual node. When using the component, you can specify the custom component that is actually rendered.
Because the wrapper
element is absolutely positioned, we need to manually maintain the height of the entire container
container.
The question here is, how do we get the height of the elements inside? The computed-zone
in the template is to solve this problem. Before placing the elements into the array, we first render the elements in computed-zone
and then use the WXML api to Get the actual rendering size of the element, so that we can know the actual rendered width and height of this element.
After having the rendering size information of each element, we need to confirm whether the element occupies the entire row or half of it:
If the rendering width of the element is the same as If the container is the same, then you can judge that this element fills the entire row. You need to set the wrapping container
wrapper
to the width of the entire row;If it does not satisfy 1 Condition, then you need to place
wrapper
on the left or right based on the total height of the left and right elements.
After analysis, what needs to be written a little bit is to calculate the offset of wrapper
and decide whether to put it on the left or right, or whether it will occupy the entire line. , the core code is implemented as follows:
{ // 将 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!'); } }); }); }); }, // 添加元素,内部使用 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 左侧栏高度,rightTotal 右侧栏高度, 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}]`; // 利用直接操作数组下标的方式来触发数组修改,性能有很大提升 this.height = [leftTotal, rightTotal]; // 记录最新的左右侧高度 return this.$setData({ [targetKey]: { data: item, style, }, height: Math.max(leftTotal, rightTotal), }); }); }, // 实际添加元素使用,自建Promise队列,保证顺序一致 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, }); }, }
When using this component, we cannot render elements directly by assigning arrays, but must use the component instance method add(item)
way, because I implemented the queue, I can just loop add directly. If you care about the status, just determine whether the add operation of the last element is completed.
The waterfall flow achieved in this way is relatively flexible, but the performance consumption is not low. You need to obtain the actual rendering size of the elements one by one. If you want to support the resize of the window, the consumption is terrible. .
For students who need to see the details of the code, I have put the actual demo on Github and WeChat code snippets. Students in need can give it a try.
Based on the above model, it can actually be optimized to only render elements within the visible area, which can greatly improve the performance of waterfall flow. I hope that students who have time can improve it. I will fork and like it~o ( ̄▽ ̄)d
For more programming-related knowledge, please visit: Programming Video! !
The above is the detailed content of Let's talk about how to implement a truncated waterfall flow component in a small program. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

EditPlus Chinese cracked version
Small size, syntax highlighting, does not support code prompt function

PhpStorm Mac version
The latest (2018.2.1) professional PHP integrated development tool

Zend Studio 13.0.1
Powerful PHP integrated development environment

WebStorm Mac version
Useful JavaScript development tools

MantisBT
Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.