


Une brève analyse des méthodes de personnalisation des composants dans les mini-programmes WeChat
Comment personnaliser les composants du mini-programme WeChat ? L'article suivant vous présentera comment personnaliser les composants des mini-programmes WeChat. J'espère qu'il vous sera utile !
Pendant le processus de développement de l'applet WeChat, certains modules de page pouvant être utilisés sur plusieurs pages peuvent être encapsulés dans un composant pour améliorer l'efficacité du développement. Bien que nous puissions introduire l'intégralité de la bibliothèque de composants tels que weui, vant, etc., compte tenu parfois de la limite de taille du paquet de l'applet WeChat, il est généralement plus contrôlable de l'encapsuler en tant que composant personnalisé.
Et pour certains modules métiers, nous pouvons les encapsuler dans des composants pour les réutiliser. Cet article parle principalement des deux aspects suivants :
- Déclaration et utilisation des composants
- Communication des composants
Déclaration et utilisation des composants
La couche inférieure du système de composants de l'applet WeChat est implémentée via le Cadre de composants Exparser, intégré dans la bibliothèque de base du mini-programme, tous les composants du mini-programme, y compris les composants intégrés et les composants personnalisés, sont organisés et gérés par Exparser.
Les composants personnalisés incluent les fichiers suivants, tout comme l'écriture de pages :
- index.json
- index.wxml
- index.wxss
- index.js
- index.wxs
pour écrire un onglet à titre d'exemple :
Lors de l'écriture d'un composant personnalisé, vous devez définir le champ <code>component
sur true
dans le fichier json
: tab
组件为例:
编写自定义组件时需要在 json
文件中讲 component
字段设为 true
:
{ "component": true }
在 js
文件中,基础库提供有 Page 和 Component 两个构造器,Page 对应的页面为页面根组件,Component 则对应:
Component({ options: { // 组件配置 addGlobalClass: true, // 指定所有 _ 开头的数据字段为纯数据字段 // 纯数据字段是一些不用于界面渲染的 data 字段,可以用于提升页面更新性能 pureDataPattern: /^_/, multipleSlots: true // 在组件定义时的选项中启用多slot支持 }, properties: { vtabs: {type: Array, value: []}, }, data: { currentView: 0, }, observers: { // 监测 activeTab: function(activeTab) { this.scrollTabBar(activeTab); } }, relations: { // 关联的子/父组件 '../vtabs-content/index': { type: 'child', // 关联的目标节点应为子节点 linked: function(target) { this.calcVtabsCotentHeight(target); }, unlinked: function(target) { delete this.data._contentHeight[target.data.tabIndex]; } } }, lifetimes: { // 组件声明周期 created: function() { // 组件实例刚刚被创建好时 }, attached: function() { // 在组件实例进入页面节点树时执行 }, detached: function() { // 在组件实例被从页面节点树移除时执行 }, }, methods: { // 组件方法 calcVtabsCotentHeight(target) {} } });
如果有了解过 Vue2 的小伙伴,会发现这个声明很熟悉。
在小程序启动时,构造器会将开发者设置的properties、data、methods等定义段,
写入Exparser的组件注册表中。这个组件在被其它组件引用时,就可以根据这些注册信息来创建自定义组件的实例。
模版文件 wxml:
<view class='vtabs'> <slot /> </view>
样式文件:
.vtabs {}
外部页面组件使用,只需要在页面的 json
文件中引入
{ "navigationBarTitleText": "商品分类", "usingComponents": { "vtabs": "../../../components/vtabs", } }
在初始化页面时,Exparser 会创建出页面根组件的一个实例,用到的其他组件也会响应创建组件实例(这是一个递归的过程):
组件创建的过程大致有以下几个要点:
根据组件注册信息,从组件原型上创建出组件节点的
JS
对象,即组件的this
;将组件注册信息中的
data
复制一份,作为组件数据,即this.data
;将这份数据结合组件
WXML
,据此创建出Shadow Tree
(组件的节点树),由于Shadow Tree
中可能引用有其他组件,因而这会递归触发其他组件创建过程;将
ShadowTree
拼接到Composed Tree
(最终拼接成的页面节点树)上,并生成一些缓存数据用于优化组件更新性能;触发组件的
created
生命周期函数;如果不是页面根组件,需要根据组件节点上的属性定义,来设置组件的属性值;
当组件实例被展示在页面上时,触发组件的
attached
生命周期函数,如果Shadow Tree
中有其他组件,也逐个触发它们的生命周期函数。
组件通信
由于业务的负责度,我们常常需要把一个大型页面拆分为多个组件,多个组件之间需要进行数据通信。
对于跨代组件通信可以考虑全局状态管理,这里只讨论常见的父子组件通信:
方法一 WXML 数据绑定
用于父组件向子组件的指定属性设置数据。
子声明 properties 属性
Component({ properties: { vtabs: {type: Array, value: []}, // 数据项格式为 `{title}` } })
父组件调用:
<vtabs vtabs="{{ vtabs }}"</vtabs>
方法二 事件
用于子组件向父组件传递数据,可以传递任意数据。
子组件派发事件,先在 wxml 结构绑定子组件的点击事件:
<view bindtap="handleTabClick">
再在 js 文件中进行派发事件,事件名可以自定义填写, 第二个参数可以传递数据对象,第三个参数为事件选项。
handleClick(e) { this.triggerEvent( 'tabclick', { index }, { bubbles: false, // 事件是否冒泡 // 事件是否可以穿越组件边界,为 false 时,事件只在引用组件的节点树上触发, // 不进入其他任何组件的内部 composed: false, capturePhase: false // 事件是否拥有捕获阶段 } ); }, handleChange(e) { this.triggerEvent('tabchange', { index }); },
最后,在父组件中监听使用:
<vtabs vtabs="{{ vtabs }}" bindtabclick="handleTabClick" bindtabchange="handleTabChange" >
方法三 selectComponent 获取组件实例对象
通过 selectComponent
<view> <vtabs-content="goods-content{{ index }}"></vtabs-content> </view>
js< /code> Dans le fichier, la bibliothèque de base fournit deux constructeurs, Page et Component. La page correspondant à Page est le composant racine de la page, et le Component correspond à : <p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>Page({
reCalcContentHeight(index) {
const goodsContent = this.selectComponent(`#goods-content${index}`);
},
})</pre><div class="contentsignin">Copier après la connexion</div></div></p> Si vous avez des connaissances sur Vue2, vous trouverez cette instruction. très familier. <p></p>Lorsque le mini-programme est démarré, le constructeur écrira les propriétés, données, méthodes et autres sections de définition définies par le développeur dans le registre des composants d'Exparser. Lorsque ce composant est référencé par d'autres composants, il peut créer des instances de composants personnalisés en fonction de ces informations d'enregistrement. <p></p>Fichier modèle wxml : 🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>export function jumpTo(url, options) {
const baseUrl = url.split(&#39;?&#39;)[0];
// 如果 url 带了参数,需要把参数也挂载到 options 上
if (url.indexof(&#39;?&#39;) !== -1) {
const { queries } = resolveUrl(url);
Object.assign(options, queries, options); // options 的优先级最高
}
cosnt queryString = objectEntries(options)
.filter(item => item[1] || item[0] === 0) // 除了数字 0 外,其他非值都过滤
.map(
([key, value]) => {
if (typeof value === &#39;object&#39;) {
// 对象转字符串
value = JSON.stringify(value);
}
if (typeof value === &#39;string&#39;) {
// 字符串 encode
value = encodeURIComponent(value);
}
return `${key}=${value}`;
}
).join(&#39;&&#39;);
if (queryString) { // 需要组装参数
url = `${baseUrl}?${queryString}`;
}
const pageCount = wx.getCurrentPages().length;
if (jumpType === &#39;navigateTo&#39; && pageCount < 5) {
wx.navigateTo({
url,
fail: () => {
wx.switch({ url: baseUrl });
}
});
} else {
wx.navigateTo({
url,
fail: () => {
wx.switch({ url: baseUrl });
}
});
}
}</pre><div class="contentsignin">Copier après la connexion</div></div><div class="contentsignin">Copier après la connexion</div></div>🎜Fichier de style : 🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>export const resolveSearch = search => {
const queries = {};
cosnt paramList = search.split(&#39;&&#39;);
paramList.forEach(param => {
const [key, value = &#39;&#39;] = param.split(&#39;=&#39;);
queries[key] = value;
});
return queries;
};
export const resolveUrl = (url) => {
if (url.indexOf(&#39;?&#39;) === -1) {
// 不带参数的 url
return {
queries: {},
page: url
}
}
const [page, search] = url.split(&#39;?&#39;);
const queries = resolveSearch(search);
return {
page,
queries
};
};</pre><div class="contentsignin">Copier après la connexion</div></div><div class="contentsignin">Copier après la connexion</div></div>🎜Pour utiliser des composants de page externes, il vous suffit d'introduire 🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>jumpTo({
url: &#39;pages/consignment/index&#39;,
{
sender: { name: &#39;naluduo233&#39; }
}
});</pre><div class="contentsignin">Copier après la connexion</div></div><div class="contentsignin">Copier après la connexion</div></div>🎜dans le fichier <code>json
de la page Lors de l'initialisation de la page, Exparser. créera la racine de la page. Une instance d'un composant, et les autres composants utilisés répondront également pour créer des instances de composant (il s'agit d'un processus récursif) : 🎜🎜Le processus de création d'un composant comporte grosso modo les points suivants : 🎜- 🎜🎜Selon les informations d'enregistrement du composant, créez l'objet
- class选择器(可以连续指定多个):
.a-class.another-class
- 子元素选择器:
.the-parent > .the-child
- 后代选择器:
.the-ancestor .the-descendant
- 跨自定义组件的后代选择器:
.the-ancestor >>> .the-descendant
- 多选择器的并集:
#a-node
,.some-other-nodes
JS
du nœud du composant à partir du prototype du composant, c'est-à-dire le this</code du composant >; 🎜🎜🎜🎜Créez les informations d'enregistrement du composant Copiez une copie de <code>data
en tant que données de composant, c'est-à-dire this.data
🎜🎜🎜🎜 Combinez ces données avec le composant WXML
, selon Cela crée un Shadow Tree
(l'arborescence des nœuds du composant puisque d'autres composants peuvent être référencés dans le Shadow Tree
). , cela déclenchera de manière récursive le processus de création d'autres composants ; 🎜🎜🎜🎜 Splice ShadowTree
à Composed Tree
(l'arbre de nœuds de page épissé final) et générera du cache. données pour optimiser les performances de mise à jour des composants ; 🎜🎜🎜🎜déclencher la fonction de cycle de vie du composant créé
🎜🎜🎜🎜S'il ne s'agit pas du composant racine de la page, vous devez définir la valeur d'attribut du composant en fonction ; à la définition de l'attribut sur le nœud du composant ; 🎜🎜🎜🎜Lorsque l'instance du composant est affichée sur la page Lorsque la fonction de cycle de vie attaché
du composant est déclenchée, s'il y a d'autres composants dans l'Shadow Tree
, leurs fonctions de cycle de vie sont également déclenchées une par une. 🎜🎜🎜🎜Communication entre composants🎜🎜🎜En raison de la responsabilité commerciale, nous devons souvent diviser une grande page en plusieurs composants, et une communication de données est requise entre plusieurs composants . 🎜🎜Pour la communication de composants entre générations, la gestion globale de l'état peut être envisagée. Ici, nous discutons uniquement de la communication de composants parent-enfant commune : 🎜🎜🎜Méthode 1 de liaison de données WXML🎜🎜 🎜Utilisé par le composant parent pour définir les données sur les propriétés spécifiées du composant enfant. 🎜🎜L'enfant déclare l'attribut propriétés🎜const sender = JSON.parse(getParam('sender') || '{}');
Copier après la connexionCopier après la connexion🎜Le composant parent appelle : 🎜// 返回当前页面
export function getCurrentPage() {
const pageStack = wx.getCurrentPages();
const lastIndex = pageStack.length - 1;
const currentPage = pageStack[lastIndex];
return currentPage;
}
// 获取页面 url 参数
export function getParams() {
const currentPage = getCurrentPage() || {};
const allParams = {};
const { route, options } = currentPage;
if (options) {
const entries = objectEntries(options);
entries.forEach(
([key, value]) => {
allParams[key] = decodeURIComponent(value);
}
);
}
return allParams;
}
// 按字段返回值
export function getParam(name) {
const params = getParams() || {};
return params[name];
}
Copier après la connexionCopier après la connexion🎜🎜Événement méthode 2🎜🎜🎜 est utilisé pour que le composant enfant transférer des données vers le composant parent, des données arbitraires peuvent être transmises. 🎜🎜Pour distribuer des événements à partir d'un sous-composant, liez d'abord l'événement click du sous-composant dans la structure wxml : 🎜// global-data.js
// 由于 switchTab 不支持携带参数,所以需要考虑使用全局数据存储
// 这里不管是不是 switchTab,先把数据挂载上去
const queryMap = {
page: '',
queries: {}
};
Copier après la connexionCopier après la connexion🎜 Ensuite, répartissez l'événement dans le fichier js. Le nom de l'événement peut être personnalisé.
Le deuxième paramètre peut transmettre l'objet de données et le troisième paramètre est l'option d'événement. 🎜export function jumpTo(url, options) {
// ...
Object.assign(queryMap, {
page: baseUrl,
queries: options
});
// ...
if (jumpType === 'switchTab') {
wx.switchTab({ url: baseUrl });
} else if (jumpType === 'navigateTo' && pageCount < 5) {
wx.navigateTo({
url,
fail: () => {
wx.switch({ url: baseUrl });
}
});
} else {
wx.navigateTo({
url,
fail: () => {
wx.switch({ url: baseUrl });
}
});
}
}
Copier après la connexionCopier après la connexion🎜Enfin, écoutez le composant parent en utilisant : 🎜// 获取页面 url 参数
export function getParams() {
const currentPage = getCurrentPage() || {};
const allParams = {};
const { route, options } = currentPage;
if (options) {
const entries = objectEntries(options);
entries.forEach(
([key, value]) => {
allParams[key] = decodeURIComponent(value);
}
);
+ if (isTabBar(route)) {
+ // 是 tab-bar 页面,使用挂载到全局的参数
+ const { page, queries } = queryMap;
+ if (page === `${route}`) {
+ Object.assign(allParams, queries);
+ }
+ }
}
return allParams;
}
Copier après la connexionCopier après la connexion🎜🎜Méthode 3 selectComponent pour obtenir l'objet instance du composant🎜🎜🎜via selectComponent </ Le code> permet d'obtenir l'instance du sous-composant et ainsi d'appeler la méthode du sous-composant. Le sélecteur js🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>// 判断当前路径是否是 tabBar
const { tabBar} = appConfig;
export isTabBar = (route) => tabBar.list.some(({ pagePath })) => pagePath === route);</pre><div class="contentsignin">Copier après la connexion</div></div><div class="contentsignin">Copier après la connexion</div></div>🎜du composant Parent est similaire au sélecteur CSS, mais ne prend en charge que la syntaxe suivante. 🎜<ul><li>ID选择器:<code>#the-id
(笔者只测试了这个,其他读者可自行测试)
const sender = JSON.parse(getParam('sender') || '{}');
// 返回当前页面 export function getCurrentPage() { const pageStack = wx.getCurrentPages(); const lastIndex = pageStack.length - 1; const currentPage = pageStack[lastIndex]; return currentPage; } // 获取页面 url 参数 export function getParams() { const currentPage = getCurrentPage() || {}; const allParams = {}; const { route, options } = currentPage; if (options) { const entries = objectEntries(options); entries.forEach( ([key, value]) => { allParams[key] = decodeURIComponent(value); } ); } return allParams; } // 按字段返回值 export function getParam(name) { const params = getParams() || {}; return params[name]; }
// global-data.js // 由于 switchTab 不支持携带参数,所以需要考虑使用全局数据存储 // 这里不管是不是 switchTab,先把数据挂载上去 const queryMap = { page: '', queries: {} };
export function jumpTo(url, options) { // ... Object.assign(queryMap, { page: baseUrl, queries: options }); // ... if (jumpType === 'switchTab') { wx.switchTab({ url: baseUrl }); } else if (jumpType === 'navigateTo' && pageCount < 5) { wx.navigateTo({ url, fail: () => { wx.switch({ url: baseUrl }); } }); } else { wx.navigateTo({ url, fail: () => { wx.switch({ url: baseUrl }); } }); } }
// 获取页面 url 参数 export function getParams() { const currentPage = getCurrentPage() || {}; const allParams = {}; const { route, options } = currentPage; if (options) { const entries = objectEntries(options); entries.forEach( ([key, value]) => { allParams[key] = decodeURIComponent(value); } ); + if (isTabBar(route)) { + // 是 tab-bar 页面,使用挂载到全局的参数 + const { page, queries } = queryMap; + if (page === `${route}`) { + Object.assign(allParams, queries); + } + } } return allParams; }
方法四 url 参数通信
在电商/物流等微信小程序中,会存在这样的用户故事,有一个「下单页面A」和「货物信息页面B」
- 在「下单页面 A」填写基本信息,需要下钻到「详细页面B」填写详细信息的情况。比如一个寄快递下单页面,需要下钻到货物信息页面填写更详细的信息,然后返回上一个页面。
- 在「下单页面 A」下钻到「货物页面B」,需要回显「货物页面B」的数据。
微信小程序由一个 App()
实例和多个 Page()
组成。小程序框架以栈的方式维护页面(最多10个) 提供了以下 API 进行页面跳转,页面路由如下
wx.navigateTo(只能跳转位于栈内的页面)
wx.redirectTo(可跳转位于栈外的新页面,并替代当前页面)
wx.navigateBack(返回上一层页面,不能携带参数)
wx.switchTab(切换 Tab 页面,不支持 url 参数)
wx.reLaunch(小程序重启)
可以简单封装一个 jumpTo 跳转函数,并传递参数:
export function jumpTo(url, options) { const baseUrl = url.split('?')[0]; // 如果 url 带了参数,需要把参数也挂载到 options 上 if (url.indexof('?') !== -1) { const { queries } = resolveUrl(url); Object.assign(options, queries, options); // options 的优先级最高 } cosnt queryString = objectEntries(options) .filter(item => item[1] || item[0] === 0) // 除了数字 0 外,其他非值都过滤 .map( ([key, value]) => { if (typeof value === 'object') { // 对象转字符串 value = JSON.stringify(value); } if (typeof value === 'string') { // 字符串 encode value = encodeURIComponent(value); } return `${key}=${value}`; } ).join('&'); if (queryString) { // 需要组装参数 url = `${baseUrl}?${queryString}`; } const pageCount = wx.getCurrentPages().length; if (jumpType === 'navigateTo' && pageCount < 5) { wx.navigateTo({ url, fail: () => { wx.switch({ url: baseUrl }); } }); } else { wx.navigateTo({ url, fail: () => { wx.switch({ url: baseUrl }); } }); } }
jumpTo 辅助函数:
export const resolveSearch = search => { const queries = {}; cosnt paramList = search.split('&'); paramList.forEach(param => { const [key, value = ''] = param.split('='); queries[key] = value; }); return queries; }; export const resolveUrl = (url) => { if (url.indexOf('?') === -1) { // 不带参数的 url return { queries: {}, page: url } } const [page, search] = url.split('?'); const queries = resolveSearch(search); return { page, queries }; };
在「下单页面A」传递数据:
jumpTo({ url: 'pages/consignment/index', { sender: { name: 'naluduo233' } } });
在「货物信息页面B」获得 URL 参数:
const sender = JSON.parse(getParam('sender') || '{}');
url 参数获取辅助函数
// 返回当前页面 export function getCurrentPage() { const pageStack = wx.getCurrentPages(); const lastIndex = pageStack.length - 1; const currentPage = pageStack[lastIndex]; return currentPage; } // 获取页面 url 参数 export function getParams() { const currentPage = getCurrentPage() || {}; const allParams = {}; const { route, options } = currentPage; if (options) { const entries = objectEntries(options); entries.forEach( ([key, value]) => { allParams[key] = decodeURIComponent(value); } ); } return allParams; } // 按字段返回值 export function getParam(name) { const params = getParams() || {}; return params[name]; }
参数过长怎么办?路由 api 不支持携带参数呢?
虽然微信小程序官方文档没有说明可以页面携带的参数有多长,但还是可能会有参数过长被截断的风险。
我们可以使用全局数据记录参数值,同时解决 url 参数过长和路由 api 不支持携带参数的问题。
// global-data.js // 由于 switchTab 不支持携带参数,所以需要考虑使用全局数据存储 // 这里不管是不是 switchTab,先把数据挂载上去 const queryMap = { page: '', queries: {} };
更新跳转函数
export function jumpTo(url, options) { // ... Object.assign(queryMap, { page: baseUrl, queries: options }); // ... if (jumpType === 'switchTab') { wx.switchTab({ url: baseUrl }); } else if (jumpType === 'navigateTo' && pageCount < 5) { wx.navigateTo({ url, fail: () => { wx.switch({ url: baseUrl }); } }); } else { wx.navigateTo({ url, fail: () => { wx.switch({ url: baseUrl }); } }); } }
url 参数获取辅助函数
// 获取页面 url 参数 export function getParams() { const currentPage = getCurrentPage() || {}; const allParams = {}; const { route, options } = currentPage; if (options) { const entries = objectEntries(options); entries.forEach( ([key, value]) => { allParams[key] = decodeURIComponent(value); } ); + if (isTabBar(route)) { + // 是 tab-bar 页面,使用挂载到全局的参数 + const { page, queries } = queryMap; + if (page === `${route}`) { + Object.assign(allParams, queries); + } + } } return allParams; }
辅助函数
// 判断当前路径是否是 tabBar const { tabBar} = appConfig; export isTabBar = (route) => tabBar.list.some(({ pagePath })) => pagePath === route);
按照这样的逻辑的话,是不是都不用区分是否是 isTabBar
页面了,全部页面都从 queryMap 中获取?这个问题目前后续探究再下结论,因为我目前还没试过从页面实例的 options
中拿到的值是缺少的。所以可以先保留读取 getCurrentPages
的值。
方法五 EventChannel 事件派发通信
前面我谈到从「当前页面A」传递数据到被打开的「页面B」可以通过 url 参数。那么想获取被打开页面传送到当前页面的数据要如何做呢?是否也可以通过 url 参数呢?
答案是可以的,前提是不需要保存「页面A」的状态。如果要保留「页面 A」的状态,就需要使用 navigateBack
返回上一页,而这个 api 是不支持携带 url 参数的。
这样时候可以使用 页面间事件通信通道 EventChannel。
pageA 页面
// wx.navigateTo({ url: 'pageB?id=1', events: { // 为指定事件添加一个监听器,获取被打开页面传送到当前页面的数据 acceptDataFromOpenedPage: function(data) { console.log(data) }, }, success: function(res) { // 通过eventChannel向被打开页面传送数据 res.eventChannel.emit('acceptDataFromOpenerPage', { data: 'test' }) } });
pageB 页面
Page({ onLoad: function(option){ const eventChannel = this.getOpenerEventChannel() eventChannel.emit('acceptDataFromOpenedPage', {data: 'test'}); // 监听acceptDataFromOpenerPage事件,获取上一页面通过eventChannel传送到当前页面的数据 eventChannel.on('acceptDataFromOpenerPage', function(data) { console.log(data) }) } })
会出现数据无法监听的情况吗?
小程序的栈不超过 10 层,如果当前「页面A」不是第 10 层,那么可以使用 navigateTo
跳转保留当前页面,跳转到「页面B」,这个时候「页面B」填写完毕后传递数据给「页面A」时,「页面A」是可以监听到数据的。
如果当前「页面A」已经是第10个页面,只能使用 redirectTo
跳转「PageB」页面。结果是当前「页面A」出栈,新「页面B」入栈。这个时候将「页面B」传递数据给「页面A」,调用 navigateBack
是无法回到目标「页面A」的,因此数据是无法正常被监听到。
不过我分析做过的小程序中,栈中很少有10层的情况,5 层的也很少。因为调用 wx.navigateBack
、wx.redirectTo
会关闭当前页面,调用 wx.switchTab
会关闭其他所有非 tabBar 页面。
所以很少会出现这样无法回到上一页面以监听到数据的情况,如果真出现这种情况,首先要考虑的不是数据的监听问题了,而是要保证如何能够返回上一页面。
比如在「PageA」页面中先调用 getCurrentPages
获取页面的数量,再把其他的页面删除,之后在跳转「PageB」页面,这样就避免「PageA」调用 wx.redirectTo
导致关闭「PageA」。但是官方是不推荐开发者手动更改页面栈的,需要慎重。
如果有读者遇到这种情况,并知道如何解决这种的话,麻烦告知下,感谢。
使用自定义的事件中心 EventBus
除了使用官方提供的 EventChannel 外,我们也可以自定义一个全局的 EventBus 事件中心。
因为这样更加灵活,不需要在调用 wx.navigateTo
等APi里传入参数,多平台的迁移性更强。
export default class EventBus { private defineEvent = {}; // 注册事件 public register(event: string, cb): void { if(!this.defineEvent[event]) { (this.defineEvent[event] = [cb]); } else { this.defineEvent[event].push(cb); } } // 派遣事件 public dispatch(event: string, arg?: any): void { if(this.defineEvent[event]) {{ for(let i=0, len = this.defineEvent[event].length; i<len; ++i) { this.defineEvent[event][i] && this.defineEvent[event][i](arg); } }} } // on 监听 public on(event: string, cb): void { return this.register(event, cb); } // off 方法 public off(event: string, cb?): void { if(this.defineEvent[event]) { if(typeof(cb) == "undefined") { delete this.defineEvent[event]; // 表示全部删除 } else { // 遍历查找 for(let i=0, len=this.defineEvent[event].length; i<len; ++i) { if(cb == this.defineEvent[event][i]) { this.defineEvent[event][i] = null; // 标记为空 - 防止dispath 长度变化 // 延时删除对应事件 setTimeout(() => this.defineEvent[event].splice(i, 1), 0); break; } } } } } // once 方法,监听一次 public once(event: string, cb): void { let onceCb = arg => { cb && cb(arg); this.off(event, onceCb); } this.register(event, onceCb); } // 清空所有事件 public clean(): void { this.defineEvent = {}; } } export connst eventBus = new EventBus();
在 PageA 页面监听:
eventBus.on('update', (data) => console.log(data));
在 PageB 页面派发
eventBus.dispatch('someEvent', { name: 'naluduo233'});
小结
本文主要讨论了微信小程序如何自定义组件,涉及两个方面:
- 组件的声明与使用
- 组件的通信
如果你使用的是 taro 的话,直接按照 react 的语法自定义组件就好。而其中的组件通信的话,因为 taro 最终也是会编译为微信小程序,所以 url 和 eventbus 的页面组件通信方式是适用的。后续会分析 vant-ui weapp 的一些组件源码,看看有赞是如何实践的。
感谢阅读,如有错误的地方请指出
【相关学习推荐:小程序开发教程】
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!

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

AI Hentai Generator
Générez AI Hentai gratuitement.

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Le mini programme WeChat officiel de Xianyu a été lancé discrètement. Dans le mini programme, vous pouvez publier des messages privés pour communiquer avec les acheteurs/vendeurs, afficher les informations personnelles et les commandes, rechercher des articles, etc. Si vous êtes curieux, qu'est-ce que le mini Xianyu WeChat. programme appelé ? Jetons un coup d'oeil. Quel est le nom de l'applet Xianyu WeChat ? Réponse : Xianyu, transactions inutilisées, ventes d'occasion, valorisations et recyclage. 1. Dans le mini programme, vous pouvez publier des messages inactifs, communiquer avec des acheteurs/vendeurs via des messages privés, afficher des informations personnelles et des commandes, rechercher des articles spécifiés, etc. 2. Sur la page du mini programme, il y a une page d'accueil, à proximité, publier des messages inactifs et les miens 5 fonctions ; 3. Si vous souhaitez l'utiliser, vous devez activer le paiement WeChat avant d'acheter ;

L'applet WeChat implémente la fonction de téléchargement d'images Avec le développement de l'Internet mobile, l'applet WeChat est devenue un élément indispensable dans la vie des gens. Les mini-programmes WeChat fournissent non seulement une multitude de scénarios d'application, mais prennent également en charge les fonctions définies par les développeurs, notamment les fonctions de téléchargement d'images. Cet article présentera comment implémenter la fonction de téléchargement d'images dans l'applet WeChat et fournira des exemples de code spécifiques. 1. Travaux préparatoires Avant de commencer à écrire du code, nous devons télécharger et installer les outils de développement WeChat et nous inscrire en tant que développeur WeChat. En même temps, vous devez également comprendre WeChat

Pour implémenter l'effet de menu déroulant dans les mini-programmes WeChat, des exemples de code spécifiques sont nécessaires. Avec la popularité de l'Internet mobile, les mini-programmes WeChat sont devenus une partie importante du développement d'Internet, et de plus en plus de gens ont commencé à y prêter attention et à y prêter attention. utilisez les mini-programmes WeChat. Le développement de mini-programmes WeChat est plus simple et plus rapide que le développement d'applications traditionnelles, mais il nécessite également la maîtrise de certaines compétences en développement. Dans le développement des mini-programmes WeChat, les menus déroulants sont un composant courant de l'interface utilisateur, permettant une meilleure expérience utilisateur. Cet article présentera en détail comment implémenter l'effet de menu déroulant dans l'applet WeChat et fournira des informations pratiques.

Implémentation d'effets de filtre d'image dans les mini-programmes WeChat Avec la popularité des applications de médias sociaux, les gens aiment de plus en plus appliquer des effets de filtre aux photos pour améliorer l'effet artistique et l'attractivité des photos. Les effets de filtre d'image peuvent également être implémentés dans les mini-programmes WeChat, offrant aux utilisateurs des fonctions de retouche photo plus intéressantes et créatives. Cet article expliquera comment implémenter des effets de filtre d'image dans les mini-programmes WeChat et fournira des exemples de code spécifiques. Tout d’abord, nous devons utiliser le composant canevas dans l’applet WeChat pour charger et modifier des images. Le composant canevas peut être utilisé sur la page

Utilisez l'applet WeChat pour obtenir un effet de commutation de carrousel. L'applet WeChat est une application légère avec des caractéristiques de développement et d'utilisation simples et efficaces. Dans les mini-programmes WeChat, il est courant d'obtenir des effets de commutation de carrousel. Cet article explique comment utiliser l'applet WeChat pour obtenir l'effet de changement de carrousel et donne des exemples de code spécifiques. Tout d’abord, ajoutez un composant carrousel au fichier d’échange de l’applet WeChat. Par exemple, vous pouvez utiliser la balise <swiper> pour obtenir l'effet de commutation du carrousel. Dans ce composant, vous pouvez passer b

Le mini-programme officiel WeChat de Xianyu a été lancé discrètement. Il offre aux utilisateurs une plate-forme pratique qui vous permet de publier et d'échanger facilement des objets inutilisés. Dans le mini programme, vous pouvez communiquer avec des acheteurs ou des vendeurs via des messages privés, afficher des informations personnelles et des commandes et rechercher les articles que vous souhaitez. Alors, comment s'appelle exactement Xianyu dans le mini-programme WeChat ? Ce guide didacticiel vous le présentera en détail. Les utilisateurs qui souhaitent savoir, veuillez suivre cet article et continuer à lire ! Quel est le nom de l'applet Xianyu WeChat ? Réponse : Xianyu, transactions inutilisées, ventes d'occasion, valorisations et recyclage. 1. Dans le mini programme, vous pouvez publier des messages inactifs, communiquer avec des acheteurs/vendeurs via des messages privés, afficher des informations personnelles et des commandes, rechercher des articles spécifiés, etc. 2. Sur la page du mini programme, il y a une page d'accueil, à proximité, publier des messages inactifs et les miens 5 fonctions ;

Pour implémenter l'effet de rotation d'image dans WeChat Mini Program, des exemples de code spécifiques sont nécessaires. WeChat Mini Program est une application légère qui offre aux utilisateurs des fonctions riches et une bonne expérience utilisateur. Dans les mini-programmes, les développeurs peuvent utiliser divers composants et API pour obtenir divers effets. Parmi eux, l'effet de rotation d'image est un effet d'animation courant qui peut ajouter de l'intérêt et des effets visuels au mini-programme. Pour obtenir des effets de rotation d'image dans les mini-programmes WeChat, vous devez utiliser l'API d'animation fournie par le mini-programme. Ce qui suit est un exemple de code spécifique qui montre comment

La mise en œuvre de la fonction de suppression coulissante dans les mini-programmes WeChat nécessite des exemples de code spécifiques. Avec la popularité des mini-programmes WeChat, les développeurs rencontrent souvent des problèmes de mise en œuvre de certaines fonctions courantes au cours du processus de développement. Parmi eux, la fonction de suppression coulissante est une exigence fonctionnelle courante et couramment utilisée. Cet article présentera en détail comment implémenter la fonction de suppression coulissante dans l'applet WeChat et donnera des exemples de code spécifiques. 1. Analyse des besoins Dans le mini programme WeChat, la mise en œuvre de la fonction de suppression coulissante implique les points suivants : Affichage de la liste : pour afficher une liste qui peut être glissée et supprimée, chaque élément de la liste doit inclure
