


Une brève analyse des méthodes de personnalisation des composants dans les mini-programmes WeChat
Mar 25, 2022 am 11:33 AMComment 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
組件為例:
編寫自定義組件時(shí)需要在 json
文件中講 component
字段設(shè)為 true
:
{ "component": true }
在 js
文件中,基礎(chǔ)庫(kù)提供有 Page 和 Component 兩個(gè)構(gòu)造器,Page 對(duì)應(yīng)的頁(yè)面為頁(yè)面根組件,Component 則對(duì)應(yīng):
Component({ options: { // 組件配置 addGlobalClass: true, // 指定所有 _ 開頭的數(shù)據(jù)字段為純數(shù)據(jù)字段 // 純數(shù)據(jù)字段是一些不用于界面渲染的 data 字段,可以用于提升頁(yè)面更新性能 pureDataPattern: /^_/, multipleSlots: true // 在組件定義時(shí)的選項(xiàng)中啟用多slot支持 }, properties: { vtabs: {type: Array, value: []}, }, data: { currentView: 0, }, observers: { // 監(jiān)測(cè) activeTab: function(activeTab) { this.scrollTabBar(activeTab); } }, relations: { // 關(guān)聯(lián)的子/父組件 '../vtabs-content/index': { type: 'child', // 關(guān)聯(lián)的目標(biāo)節(jié)點(diǎn)應(yīng)為子節(jié)點(diǎn) linked: function(target) { this.calcVtabsCotentHeight(target); }, unlinked: function(target) { delete this.data._contentHeight[target.data.tabIndex]; } } }, lifetimes: { // 組件聲明周期 created: function() { // 組件實(shí)例剛剛被創(chuàng)建好時(shí) }, attached: function() { // 在組件實(shí)例進(jìn)入頁(yè)面節(jié)點(diǎn)樹時(shí)執(zhí)行 }, detached: function() { // 在組件實(shí)例被從頁(yè)面節(jié)點(diǎn)樹移除時(shí)執(zhí)行 }, }, methods: { // 組件方法 calcVtabsCotentHeight(target) {} } });
如果有了解過(guò) Vue2 的小伙伴,會(huì)發(fā)現(xiàn)這個(gè)聲明很熟悉。
在小程序啟動(dòng)時(shí),構(gòu)造器會(huì)將開發(fā)者設(shè)置的properties、data、methods等定義段,
寫入Exparser的組件注冊(cè)表中。這個(gè)組件在被其它組件引用時(shí),就可以根據(jù)這些注冊(cè)信息來(lái)創(chuàng)建自定義組件的實(shí)例。
模版文件 wxml:
<view class='vtabs'> <slot /> </view>
樣式文件:
.vtabs {}
外部頁(yè)面組件使用,只需要在頁(yè)面的 json
文件中引入
{ "navigationBarTitleText": "商品分類", "usingComponents": { "vtabs": "../../../components/vtabs", } }
在初始化頁(yè)面時(shí),Exparser 會(huì)創(chuàng)建出頁(yè)面根組件的一個(gè)實(shí)例,用到的其他組件也會(huì)響應(yīng)創(chuàng)建組件實(shí)例(這是一個(gè)遞歸的過(guò)程):
組件創(chuàng)建的過(guò)程大致有以下幾個(gè)要點(diǎn):
根據(jù)組件注冊(cè)信息,從組件原型上創(chuàng)建出組件節(jié)點(diǎn)的
JS
對(duì)象,即組件的this
;將組件注冊(cè)信息中的
data
復(fù)制一份,作為組件數(shù)據(jù),即this.data
;將這份數(shù)據(jù)結(jié)合組件
WXML
,據(jù)此創(chuàng)建出Shadow Tree
(組件的節(jié)點(diǎn)樹),由于Shadow Tree
中可能引用有其他組件,因而這會(huì)遞歸觸發(fā)其他組件創(chuàng)建過(guò)程;將
ShadowTree
拼接到Composed Tree
(最終拼接成的頁(yè)面節(jié)點(diǎn)樹)上,并生成一些緩存數(shù)據(jù)用于優(yōu)化組件更新性能;觸發(fā)組件的
created
生命周期函數(shù);如果不是頁(yè)面根組件,需要根據(jù)組件節(jié)點(diǎn)上的屬性定義,來(lái)設(shè)置組件的屬性值;
當(dāng)組件實(shí)例被展示在頁(yè)面上時(shí),觸發(fā)組件的
attached
生命周期函數(shù),如果Shadow Tree
中有其他組件,也逐個(gè)觸發(fā)它們的生命周期函數(shù)。
組件通信
由于業(yè)務(wù)的負(fù)責(zé)度,我們常常需要把一個(gè)大型頁(yè)面拆分為多個(gè)組件,多個(gè)組件之間需要進(jìn)行數(shù)據(jù)通信。
對(duì)于跨代組件通信可以考慮全局狀態(tài)管理,這里只討論常見(jiàn)的父子組件通信:
方法一 WXML 數(shù)據(jù)綁定
用于父組件向子組件的指定屬性設(shè)置數(shù)據(jù)。
子聲明 properties 屬性
Component({ properties: { vtabs: {type: Array, value: []}, // 數(shù)據(jù)項(xiàng)格式為 `{title}` } })
父組件調(diào)用:
<vtabs vtabs="{{ vtabs }}"</vtabs>
方法二 事件
用于子組件向父組件傳遞數(shù)據(jù),可以傳遞任意數(shù)據(jù)。
子組件派發(fā)事件,先在 wxml 結(jié)構(gòu)綁定子組件的點(diǎn)擊事件:
<view bindtap="handleTabClick">
再在 js 文件中進(jìn)行派發(fā)事件,事件名可以自定義填寫, 第二個(gè)參數(shù)可以傳遞數(shù)據(jù)對(duì)象,第三個(gè)參數(shù)為事件選項(xiàng)。
handleClick(e) { this.triggerEvent( 'tabclick', { index }, { bubbles: false, // 事件是否冒泡 // 事件是否可以穿越組件邊界,為 false 時(shí),事件只在引用組件的節(jié)點(diǎn)樹上觸發(fā), // 不進(jìn)入其他任何組件的內(nèi)部 composed: false, capturePhase: false // 事件是否擁有捕獲階段 } ); }, handleChange(e) { this.triggerEvent('tabchange', { index }); },
最后,在父組件中監(jiān)聽使用:
<vtabs vtabs="{{ vtabs }}" bindtabclick="handleTabClick" bindtabchange="handleTabChange" >
方法三 selectComponent 獲取組件實(shí)例對(duì)象
通過(guò) selectComponent
<view> <vtabs-content="goods-content{{ index }}"></vtabs-content> </view>In
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><pre class='brush:php;toolbar:false;'>Page({
reCalcContentHeight(index) {
const goodsContent = this.selectComponent(`#goods-content${index}`);
},
})</pre></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 : ??<pre class='brush:php;toolbar:false;'>export function jumpTo(url, options) {
const baseUrl = url.split(&#39;?&#39;)[0];
// 如果 url 帶了參數(shù),需要把參數(shù)也掛載到 options 上
if (url.indexof(&#39;?&#39;) !== -1) {
const { queries } = resolveUrl(url);
Object.assign(options, queries, options); // options 的優(yōu)先級(jí)最高
}
cosnt queryString = objectEntries(options)
.filter(item => item[1] || item[0] === 0) // 除了數(shù)字 0 外,其他非值都過(guò)濾
.map(
([key, value]) => {
if (typeof value === &#39;object&#39;) {
// 對(duì)象轉(zhuǎn)字符串
value = JSON.stringify(value);
}
if (typeof value === &#39;string&#39;) {
// 字符串 encode
value = encodeURIComponent(value);
}
return `${key}=${value}`;
}
).join(&#39;&&#39;);
if (queryString) { // 需要組裝參數(shù)
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>??Fichier de style : ??<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) {
// 不帶參數(shù)的 url
return {
queries: {},
page: url
}
}
const [page, search] = url.split(&#39;?&#39;);
const queries = resolveSearch(search);
return {
page,
queries
};
};</pre>??Pour utiliser des composants de page externes, il vous suffit d'introduire ??<pre class='brush:php;toolbar:false;'>jumpTo({
url: &#39;pages/consignment/index&#39;,
{
sender: { name: &#39;naluduo233&#39; }
}
});</pre>??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選擇器(可以連續(xù)指定多個(gè)):
.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') || '{}');
??Le composant parent appelle?: ??// 返回當(dāng)前頁(yè)面
export function getCurrentPage() {
const pageStack = wx.getCurrentPages();
const lastIndex = pageStack.length - 1;
const currentPage = pageStack[lastIndex];
return currentPage;
}
// 獲取頁(yè)面 url 參數(shù)
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];
}
????é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 不支持?jǐn)y帶參數(shù),所以需要考慮使用全局?jǐn)?shù)據(jù)存儲(chǔ)
// 這里不管是不是 switchTab,先把數(shù)據(jù)掛載上去
const queryMap = {
page: '',
queries: {}
};
?? 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 });
}
});
}
}
??Enfin, écoutez le composant parent en utilisant?: ??// 獲取頁(yè)面 url 參數(shù)
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 頁(yè)面,使用掛載到全局的參數(shù)
+ const { page, queries } = queryMap;
+ if (page === `${route}`) {
+ Object.assign(allParams, queries);
+ }
+ }
}
return allParams;
}
????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??<pre class='brush:php;toolbar:false;'>// 判斷當(dāng)前路徑是否是 tabBar
const { tabBar} = appConfig;
export isTabBar = (route) => tabBar.list.some(({ pagePath })) => pagePath === route);</pre>??du composant Parent est similaire au sélecteur CSS, mais ne prend en charge que la syntaxe suivante. ??<ul><li>ID選擇器:<code>#the-id
(筆者只測(cè)試了這個(gè),其他讀者可自行測(cè)試)
方法四 url 參數(shù)通信
在電商/物流等微信小程序中,會(huì)存在這樣的用戶故事,有一個(gè)「下單頁(yè)面A」和「貨物信息頁(yè)面B」
- 在「下單頁(yè)面 A」填寫基本信息,需要下鉆到「詳細(xì)頁(yè)面B」填寫詳細(xì)信息的情況。比如一個(gè)寄快遞下單頁(yè)面,需要下鉆到貨物信息頁(yè)面填寫更詳細(xì)的信息,然后返回上一個(gè)頁(yè)面。
- 在「下單頁(yè)面 A」下鉆到「貨物頁(yè)面B」,需要回顯「貨物頁(yè)面B」的數(shù)據(jù)。
微信小程序由一個(gè) App()
實(shí)例和多個(gè) Page()
組成。小程序框架以棧的方式維護(hù)頁(yè)面(最多10個(gè)) 提供了以下 API 進(jìn)行頁(yè)面跳轉(zhuǎn),頁(yè)面路由如下
wx.navigateTo(只能跳轉(zhuǎn)位于棧內(nèi)的頁(yè)面)
wx.redirectTo(可跳轉(zhuǎn)位于棧外的新頁(yè)面,并替代當(dāng)前頁(yè)面)
wx.navigateBack(返回上一層頁(yè)面,不能攜帶參數(shù))
wx.switchTab(切換 Tab 頁(yè)面,不支持 url 參數(shù))
wx.reLaunch(小程序重啟)
可以簡(jiǎn)單封裝一個(gè) jumpTo 跳轉(zhuǎn)函數(shù),并傳遞參數(shù):
export function jumpTo(url, options) { const baseUrl = url.split('?')[0]; // 如果 url 帶了參數(shù),需要把參數(shù)也掛載到 options 上 if (url.indexof('?') !== -1) { const { queries } = resolveUrl(url); Object.assign(options, queries, options); // options 的優(yōu)先級(jí)最高 } cosnt queryString = objectEntries(options) .filter(item => item[1] || item[0] === 0) // 除了數(shù)字 0 外,其他非值都過(guò)濾 .map( ([key, value]) => { if (typeof value === 'object') { // 對(duì)象轉(zhuǎn)字符串 value = JSON.stringify(value); } if (typeof value === 'string') { // 字符串 encode value = encodeURIComponent(value); } return `${key}=${value}`; } ).join('&'); if (queryString) { // 需要組裝參數(shù) 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 輔助函數(shù):
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) { // 不帶參數(shù)的 url return { queries: {}, page: url } } const [page, search] = url.split('?'); const queries = resolveSearch(search); return { page, queries }; };
在「下單頁(yè)面A」傳遞數(shù)據(jù):
jumpTo({ url: 'pages/consignment/index', { sender: { name: 'naluduo233' } } });
在「貨物信息頁(yè)面B」獲得 URL 參數(shù):
const sender = JSON.parse(getParam('sender') || '{}');
url 參數(shù)獲取輔助函數(shù)
// 返回當(dāng)前頁(yè)面 export function getCurrentPage() { const pageStack = wx.getCurrentPages(); const lastIndex = pageStack.length - 1; const currentPage = pageStack[lastIndex]; return currentPage; } // 獲取頁(yè)面 url 參數(shù) 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]; }
參數(shù)過(guò)長(zhǎng)怎么辦?路由 api 不支持?jǐn)y帶參數(shù)呢?
雖然微信小程序官方文檔沒(méi)有說(shuō)明可以頁(yè)面攜帶的參數(shù)有多長(zhǎng),但還是可能會(huì)有參數(shù)過(guò)長(zhǎng)被截?cái)嗟娘L(fēng)險(xiǎn)。
我們可以使用全局?jǐn)?shù)據(jù)記錄參數(shù)值,同時(shí)解決 url 參數(shù)過(guò)長(zhǎng)和路由 api 不支持?jǐn)y帶參數(shù)的問(wèn)題。
// global-data.js // 由于 switchTab 不支持?jǐn)y帶參數(shù),所以需要考慮使用全局?jǐn)?shù)據(jù)存儲(chǔ) // 這里不管是不是 switchTab,先把數(shù)據(jù)掛載上去 const queryMap = { page: '', queries: {} };
更新跳轉(zhuǎn)函數(shù)
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 參數(shù)獲取輔助函數(shù)
// 獲取頁(yè)面 url 參數(shù) 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 頁(yè)面,使用掛載到全局的參數(shù) + const { page, queries } = queryMap; + if (page === `${route}`) { + Object.assign(allParams, queries); + } + } } return allParams; }
輔助函數(shù)
// 判斷當(dāng)前路徑是否是 tabBar const { tabBar} = appConfig; export isTabBar = (route) => tabBar.list.some(({ pagePath })) => pagePath === route);
按照這樣的邏輯的話,是不是都不用區(qū)分是否是 isTabBar
頁(yè)面了,全部頁(yè)面都從 queryMap 中獲???這個(gè)問(wèn)題目前后續(xù)探究再下結(jié)論,因?yàn)槲夷壳斑€沒(méi)試過(guò)從頁(yè)面實(shí)例的 options
中拿到的值是缺少的。所以可以先保留讀取 getCurrentPages
的值。
方法五 EventChannel 事件派發(fā)通信
前面我談到從「當(dāng)前頁(yè)面A」傳遞數(shù)據(jù)到被打開的「頁(yè)面B」可以通過(guò) url 參數(shù)。那么想獲取被打開頁(yè)面?zhèn)魉偷疆?dāng)前頁(yè)面的數(shù)據(jù)要如何做呢?是否也可以通過(guò) url 參數(shù)呢?
答案是可以的,前提是不需要保存「頁(yè)面A」的狀態(tài)。如果要保留「頁(yè)面 A」的狀態(tài),就需要使用 navigateBack
返回上一頁(yè),而這個(gè) api 是不支持?jǐn)y帶 url 參數(shù)的。
這樣時(shí)候可以使用 頁(yè)面間事件通信通道 EventChannel。
pageA 頁(yè)面
// wx.navigateTo({ url: 'pageB?id=1', events: { // 為指定事件添加一個(gè)監(jiān)聽器,獲取被打開頁(yè)面?zhèn)魉偷疆?dāng)前頁(yè)面的數(shù)據(jù) acceptDataFromOpenedPage: function(data) { console.log(data) }, }, success: function(res) { // 通過(guò)eventChannel向被打開頁(yè)面?zhèn)魉蛿?shù)據(jù) res.eventChannel.emit('acceptDataFromOpenerPage', { data: 'test' }) } });
pageB 頁(yè)面
Page({ onLoad: function(option){ const eventChannel = this.getOpenerEventChannel() eventChannel.emit('acceptDataFromOpenedPage', {data: 'test'}); // 監(jiān)聽acceptDataFromOpenerPage事件,獲取上一頁(yè)面通過(guò)eventChannel傳送到當(dāng)前頁(yè)面的數(shù)據(jù) eventChannel.on('acceptDataFromOpenerPage', function(data) { console.log(data) }) } })
會(huì)出現(xiàn)數(shù)據(jù)無(wú)法監(jiān)聽的情況嗎?
小程序的棧不超過(guò) 10 層,如果當(dāng)前「頁(yè)面A」不是第 10 層,那么可以使用 navigateTo
跳轉(zhuǎn)保留當(dāng)前頁(yè)面,跳轉(zhuǎn)到「頁(yè)面B」,這個(gè)時(shí)候「頁(yè)面B」填寫完畢后傳遞數(shù)據(jù)給「頁(yè)面A」時(shí),「頁(yè)面A」是可以監(jiān)聽到數(shù)據(jù)的。
如果當(dāng)前「頁(yè)面A」已經(jīng)是第10個(gè)頁(yè)面,只能使用 redirectTo
跳轉(zhuǎn)「PageB」頁(yè)面。結(jié)果是當(dāng)前「頁(yè)面A」出棧,新「頁(yè)面B」入棧。這個(gè)時(shí)候?qū)ⅰ疙?yè)面B」傳遞數(shù)據(jù)給「頁(yè)面A」,調(diào)用 navigateBack
是無(wú)法回到目標(biāo)「頁(yè)面A」的,因此數(shù)據(jù)是無(wú)法正常被監(jiān)聽到。
不過(guò)我分析做過(guò)的小程序中,棧中很少有10層的情況,5 層的也很少。因?yàn)檎{(diào)用 wx.navigateBack
、wx.redirectTo
會(huì)關(guān)閉當(dāng)前頁(yè)面,調(diào)用 wx.switchTab
會(huì)關(guān)閉其他所有非 tabBar 頁(yè)面。
所以很少會(huì)出現(xiàn)這樣無(wú)法回到上一頁(yè)面以監(jiān)聽到數(shù)據(jù)的情況,如果真出現(xiàn)這種情況,首先要考慮的不是數(shù)據(jù)的監(jiān)聽問(wèn)題了,而是要保證如何能夠返回上一頁(yè)面。
比如在「PageA」頁(yè)面中先調(diào)用 getCurrentPages
獲取頁(yè)面的數(shù)量,再把其他的頁(yè)面刪除,之后在跳轉(zhuǎn)「PageB」頁(yè)面,這樣就避免「PageA」調(diào)用 wx.redirectTo
導(dǎo)致關(guān)閉「PageA」。但是官方是不推薦開發(fā)者手動(dòng)更改頁(yè)面棧的,需要慎重。
如果有讀者遇到這種情況,并知道如何解決這種的話,麻煩告知下,感謝。
使用自定義的事件中心 EventBus
除了使用官方提供的 EventChannel 外,我們也可以自定義一個(gè)全局的 EventBus 事件中心。
因?yàn)檫@樣更加靈活,不需要在調(diào)用 wx.navigateTo
等APi里傳入?yún)?shù),多平臺(tái)的遷移性更強(qiáng)。
export default class EventBus { private defineEvent = {}; // 注冊(cè)事件 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 監(jiān)聽 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; // 標(biāo)記為空 - 防止dispath 長(zhǎng)度變化 // 延時(shí)刪除對(duì)應(yīng)事件 setTimeout(() => this.defineEvent[event].splice(i, 1), 0); break; } } } } } // once 方法,監(jiān)聽一次 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 頁(yè)面監(jiān)聽:
eventBus.on('update', (data) => console.log(data));
在 PageB 頁(yè)面派發(fā)
eventBus.dispatch('someEvent', { name: 'naluduo233'});
小結(jié)
本文主要討論了微信小程序如何自定義組件,涉及兩個(gè)方面:
- 組件的聲明與使用
- 組件的通信
如果你使用的是 taro 的話,直接按照 react 的語(yǔ)法自定義組件就好。而其中的組件通信的話,因?yàn)?taro 最終也是會(huì)編譯為微信小程序,所以 url 和 eventbus 的頁(yè)面組件通信方式是適用的。后續(xù)會(huì)分析 vant-ui weapp 的一些組件源碼,看看有贊是如何實(shí)踐的。
感謝閱讀,如有錯(cuò)誤的地方請(qǐng)指出
【相關(guān)學(xué)習(xí)推薦:小程序開發(fā)教程】
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

Undress AI Tool
Images de déshabillage gratuites

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.

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
échangez les visages dans n'importe quelle vidéo sans effort grace à notre outil d'échange de visage AI entièrement gratuit?!

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?;

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

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.

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?;

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 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

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

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
