Parlons de la façon d'implémenter un composant de flux de cascade tronqué dans un petit programme

青灯夜游
Libérer: 2022-02-07 10:12:07
avant
2597 Les gens l'ont consulté

Comment implémenter un composant de flux en cascade tronqué dans un mini-programme ? L'article suivant vous présentera comment implémenter une applet WeChat capable de tronquer le composant de flux en cascade. J'espère que cela vous sera utile !

Parlons de la façon d'implémenter un composant de flux de cascade tronqué dans un petit programme

Le flux en cascade est une méthode de mise en page courante. Il existe de nombreuses façons de le mettre en œuvre, par exemple en le divisant directement en deux colonnes, puis en contrôlant l'ajout d'éléments dans les colonnes de gauche et de droite. côtés grâce à un positionnement absolu. [Recommandations d'apprentissage associées : Tutoriel de développement de mini-programmes]

Le flux en cascade qui sera présenté dans cet article est différent du flux conventionnel, car le flux en cascade peut être tronqué au milieu :

Parlons de la façon dimplémenter un composant de flux de cascade tronqué dans un petit programme

Pour la mise en page ci-dessus , s'il est forcé d'être divisé en deux colonnes, cela ne convient pas à la mise en page, j'ai donc utilisé le positionnement absolu pour la mise en page. Puisque la hauteur des éléments dans le flux de la cascade n'est pas fixe, je dois trouver un moyen d'obtenir la hauteur. de chaque élément, puis déterminez la hauteur de l'élément. Placez une ligne entière, soit à gauche, soit à droite.

Tout d'abord, jetons un coup d'œil à l'implémentation de la partie modèle :

<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>
Copier après la connexion

Le modèle est relativement simple, un conteneur container, puis parcourt le tableau et restitue un tas de emballer les conteneurs à plat. container 容器,然后循环数组,平级渲染出一堆 wrapper 容器。

wrapper 容器是一个绝对定位的包裹元素,wrapper 容器里面需要放置需要实际渲染的组件,为了灵活性更高一点,我把这个渲染组件设置成了虚拟节点,在使用组件的时候可以指定实际渲染的自定义组件。

因为 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,
		});
	},
}
Copier après la connexion

在使用该组件的时候我们就不能直接通过赋值数组的方式来渲染元素了,而是得通过组件实例方法add(item)

wrapper Le conteneur est un élément d'emballage positionné de manière absolue. Les composants qui doivent être réellement rendus doivent être placés dans le conteneur wrapper Afin d'être plus flexibles. J'ai défini ce composant de rendu. Il est devenu un nœud virtuel et vous pouvez spécifier le composant personnalisé qui est réellement rendu lors de l'utilisation du composant.

Étant donné que l'élément wrapper est positionné de manière absolue, nous devons maintenir manuellement la hauteur de l'ensemble du conteneur container.

Une question ici est la suivante : comment obtenir la hauteur de l'élément à l'intérieur ? La zone calculée dans le modèle vise à résoudre ce problème. Avant de placer les éléments dans le tableau, nous rendons d'abord les éléments dans la zone calculée, puis utilisons l'API WXML pour obtenir. la taille de rendu réelle de l'élément, afin que nous puissions connaître la largeur et la hauteur réelles de rendu de cet élément. Après avoir obtenu les informations sur la taille de rendu de chaque élément, nous devons confirmer si l'élément occupe toute la ligne ou la moitié de celle-ci :

  • Si le element La largeur de rendu est la même que celle du conteneur, vous pouvez alors juger que cet élément remplit une ligne entière, et vous devez définir le conteneur d'emballage wrapper sur la largeur d'une ligne entière

     ; li>

  • Sinon Si la condition 1 est remplie, alors vous devez placer le wrapper à gauche ou à droite en fonction de la hauteur totale des éléments gauche et droit.

Après analyse, ce qu'il faut écrire un peu c'est calculer le décalage du wrapper et décider s'il faut le mettre à gauche ou à droite, ou s'il devrait occuper toute la ligne. Le code principal est implémenté comme suit : rrreeeLors de l'utilisation de ce composant, nous ne pouvons pas restituer directement les éléments en attribuant des tableaux, mais devons utiliser la méthode d'instance du composant add(item). Parce que j'ai implémenté une file d'attente, je peux simplement ajouter directement une boucle. Si vous vous souciez du statut, déterminez simplement si l'opération d'ajout du dernier élément est terminée. 🎜🎜La flexibilité du flux de cascade obtenue de cette manière est relativement élevée, mais la consommation de performances n'est pas faible. Vous devez obtenir la taille réelle du rendu des éléments un par un. Si vous souhaitez prendre en charge le redimensionnement de la fenêtre, la consommation est terrible. 🎜🎜Pour les étudiants qui ont besoin de voir les détails du code, j'ai mis la démo réelle sur 🎜Github🎜 et 🎜Extraits de code WeChat🎜 Les étudiants dans le besoin peuvent l'essayer. 🎜🎜Sur la base du modèle ci-dessus, il peut en fait être optimisé pour restituer uniquement les éléments dans la zone visible, ce qui peut grandement améliorer les performances du flux en cascade. J'espère que les étudiants qui ont le temps pourront l'améliorer et l'aimer. o( ̄▽ ̄ )d🎜🎜Pour plus de connaissances sur la programmation, veuillez visiter : 🎜Vidéo de programmation🎜 ! ! 🎜

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:juejin.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal