ホームページ  >  記事  >  WeChat アプレット  >  小さなプログラムで切り詰められたウォーターフォール フロー コンポーネントを実装する方法について話しましょう

小さなプログラムで切り詰められたウォーターフォール フロー コンポーネントを実装する方法について話しましょう

青灯夜游
青灯夜游転載
2022-01-24 10:32:312599ブラウズ

切り詰められたウォーターフォール フロー コンポーネントをミニ プログラムに実装するにはどうすればよいですか?以下の記事では、ウォーターフォールフローの要素をカットできるWeChatアプレットの実装方法を紹介しますので、ご参考になれば幸いです。

小さなプログラムで切り詰められたウォーターフォール フロー コンポーネントを実装する方法について話しましょう

ウォーターフォールフローは一般的なレイアウト手法ですが、直接2列に分割し、左側の要素の追加を制御するなど、実装方法はさまざまです。と右側の列; 絶対配置によって両側を配置する別の方法もあります。 [関連する学習の推奨事項: 小さなプログラム開発チュートリアル ]

この記事で紹介するウォーターフォール フローは、従来のものとは異なります。これは、ウォーターフォール フローが途中で切れている場合があるためです。

小さなプログラムで切り詰められたウォーターフォール フロー コンポーネントを実装する方法について話しましょう

##上記のレイアウトでは、無理に2列にレイアウトするのは適切ではないので、絶対配置でレイアウトしました。したがって、各要素の高さを取得する方法を見つけて、要素を行全体に配置するか、左側に配置するか、右側に配置するかを決定する必要があります。

まず、テンプレート部分の実装を見てみましょう:

<view class="container"   style="max-width:90%">
	<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>

テンプレートは比較的単純な

container コンテナで、配列をループし、多数のレンダリングを行います。 水平ラッパー コンテナー。

wrapper コンテナは、絶対的に配置されたラッピング要素です。 wrapper コンテナは、実際にレンダリングする必要があるコンポーネントを配置する必要があります。より柔軟にするために、 render this コンポーネントを仮想ノードとして設定し、コンポーネントを使用する際に実際にレンダリングするカスタムコンポーネントを指定できます。

wrapper 要素は絶対位置に配置されているため、container コンテナ全体の高さを手動で維持する必要があります。

ここでの質問は、内部の要素の高さをどうやって取得するかということです。テンプレートの

computed-zone は、この問題を解決するためのものです。要素を配列に配置する前に、まず computed-zone で要素をレンダリングし、次に WXML API を使用して取得します要素の実際のレンダリング サイズ。これにより、この要素の実際にレンダリングされた幅と高さを知ることができます。

各要素のレンダリング サイズ情報を取得した後、要素が行全体を占めるか行の半分を占めるかを確認する必要があります。要素が同じである場合、コンテナが同じ場合、この要素が行全体を埋めると判断でき、ラッピング コンテナ

wrapper

を行全体の幅に設定する必要があります。
  • 1 の条件を満たさない場合は、左右の要素の高さの合計に基づいて、wrapper を左右に配置する必要があります。

  • 分析後、少し書く必要があるのは、wrapper のオフセットを計算し、それを左に配置するか右に配置するか、またはどちらに配置するかを決定することです。行全体を占めます。コア コードは次のように実装されます:

    {
    	// 将 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(&#39;.computed-zone .wrapper&#39;).boundingClientRect();
    				query.exec(ret => {
    					if (ret[0]) {
    						resolve(ret[0]);
    					} else {
    						reject(&#39;not found dom!&#39;);
    					}
    				});
    			});
    		});
    	},
    	// 添加元素,内部使用
    	addItem(item) {
    		let tick = this.tick;
    		return this.getRect(item).then(rect => {
    			if (tick !== this.tick) {
    				return Promise.reject(&#39;tick&#39;);
    			}
    			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 = &#39;&#39;;
    
    			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,
    		});
    	},
    }
  • このコンポーネントを使用する場合、配列を割り当てて要素を直接レンダリングすることはできませんが、コンポーネント インスタンス メソッド
add(item) を使用する必要があります。 )

ちなみに、キューを実装したので、直接ループ追加するだけです。ステータスが気になる場合は、最後の要素の追加操作が完了したかどうかだけを判断してください。 この方法で実現されるウォーターフォール フローは比較的柔軟ですが、パフォーマンスの消費は低くありません。要素の実際のレンダリング サイズを 1 つずつ取得する必要があります。ウィンドウのサイズ変更をサポートしたい場合は、 、消耗がひどいです。

コードの詳細を確認する必要がある学生のために、Github および

WeChat コード スニペット

に実際のデモを置きました。試す。

上記のモデルに基づいて、実際に可視領域内の要素のみをレンダリングするように最適化することができ、これによりウォーターフォール フローのパフォーマンスが大幅に向上します。時間のある学生が改善できることを願っています。気に入ってください~o ( ̄▽ ̄)dプログラミング関連の知識については、プログラミング ビデオをご覧ください。 !

以上が小さなプログラムで切り詰められたウォーターフォール フロー コンポーネントを実装する方法について話しましょうの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。