목차
컴포넌트 선언 및 사용
미니 프로그램이 시작되면 생성자는 개발자가 설정한 속성, 데이터, 메서드 및 기타 정의 섹션을 Exparser의 구성 요소 레지스트리에 기록합니다. 이 구성 요소가 다른 구성 요소에서 참조되면 이러한 등록 정보를 기반으로 사용자 정의 구성 요소의 인스턴스를 만들 수 있습니다.
小结
위챗 애플릿 미니 프로그램 개발 WeChat 미니 프로그램의 구성 요소를 사용자 정의하는 방법에 대한 간략한 분석

WeChat 미니 프로그램의 구성 요소를 사용자 정의하는 방법에 대한 간략한 분석

Mar 25, 2022 am 11:33 AM
위챗 애플릿

WeChat 미니 프로그램의 구성요소를 어떻게 맞춤설정하나요? 다음 기사에서는 WeChat 미니 프로그램의 구성 요소를 사용자 정의하는 방법을 소개하겠습니다. 도움이 되길 바랍니다!

WeChat 미니 프로그램의 구성 요소를 사용자 정의하는 방법에 대한 간략한 분석

WeChat 미니 프로그램 개발 과정에서 여러 페이지에서 사용할 수 있는 일부 페이지 모듈을 구성 요소로 캡슐화하여 개발 효율성을 높일 수 있습니다. weui, vant 등과 같은 전체 구성 요소 라이브러리를 도입할 수 있지만 때때로 WeChat 애플릿의 패키지 크기 제한을 고려하면 이를 사용자 정의 구성 요소로 캡슐화하는 것이 일반적으로 더 제어하기 쉽습니다.

일부 비즈니스 모듈의 경우 재사용을 위해 구성 요소로 캡슐화할 수 있습니다. 이 기사에서는 주로 다음 두 가지 측면에 대해 설명합니다.

  • 컴포넌트 선언 및 사용
  • 컴포넌트 통신

컴포넌트 선언 및 사용

WeChat 애플릿 컴포넌트 시스템의 최하위 계층은 Exparser를 통해 구현됩니다. 내장된 컴포넌트 프레임워크 미니 프로그램의 기본 라이브러리에는 내장 컴포넌트, 커스텀 컴포넌트 등 미니 프로그램 내의 모든 컴포넌트가 Exparser에 의해 구성되고 관리됩니다.

사용자 정의 구성 요소에는 페이지 작성과 마찬가지로 다음 파일이 포함됩니다.

  • index.json
  • index.wxml
  • index.wxss
  • index.js
  • index.wxs

예를 들어 tab 구성 요소를 작성하려면: 사용자 정의 구성 요소를 작성할 때 json 파일에서 comment 필드를 true로 설정해야 합니다: 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=&#39;vtabs&#39;>
    <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

    Component({
        properties: {
            vtabs: {type: Array, value: []}, // 数据项格式为 `{title}`
        }
    })
    로그인 후 복사

    In js< /code> 파일에서 기본 라이브러리는 Page와 Component라는 두 개의 생성자를 제공합니다. Page에 해당하는 페이지는 페이지 루트 구성 요소이고 구성 요소는 다음과 같습니다. </li><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'> &lt;vtabs vtabs=&quot;{{ vtabs }}&quot;&lt;/vtabs&gt;</pre><div class="contentsignin">로그인 후 복사</div></div></ul> Vue2에 대한 지식이 있으면 다음 명령문을 찾을 수 있습니다. 매우 친숙합니다. <h2 id="strong-미니-프로그램이-시작되면-생성자는-개발자가-설정한-속성-데이터-메서드-및-기타-정의-섹션을-Exparser의-구성-요소-레지스트리에-기록합니다-이-구성-요소가-다른-구성-요소에서-참조되면-이러한-등록-정보를-기반으로-사용자-정의-구성-요소의-인스턴스를-만들-수-있습니다-strong"><strong>미니 프로그램이 시작되면 생성자는 개발자가 설정한 속성, 데이터, 메서드 및 기타 정의 섹션을 Exparser의 구성 요소 레지스트리에 기록합니다. 이 구성 요소가 다른 구성 요소에서 참조되면 이러한 등록 정보를 기반으로 사용자 정의 구성 요소의 인스턴스를 만들 수 있습니다. </strong></h2>템플릿 파일 wxml: <p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'> &lt;view bindtap=&quot;handleTabClick&quot;&gt;</pre><div class="contentsignin">로그인 후 복사</div></div></p>스타일 파일: <p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'> handleClick(e) { this.triggerEvent( &amp;#39;tabclick&amp;#39;, { index }, { bubbles: false, // 事件是否冒泡 // 事件是否可以穿越组件边界,为 false 时,事件只在引用组件的节点树上触发, // 不进入其他任何组件的内部 composed: false, capturePhase: false // 事件是否拥有捕获阶段 } ); }, handleChange(e) { this.triggerEvent(&amp;#39;tabchange&amp;#39;, { index }); },</pre><div class="contentsignin">로그인 후 복사</div></div></p>외부 페이지 구성요소를 사용하려면 페이지 초기화 시 페이지의 <code>json 파일에

    <vtabs 
        vtabs="{{ vtabs }}"
        bindtabclick="handleTabClick" 
        bindtabchange="handleTabChange" 
    >
    로그인 후 복사
    만 추가하면 됩니다. 페이지 루트를 생성합니다. 구성 요소의 인스턴스와 사용된 다른 구성 요소도 구성 요소 인스턴스 생성에 응답합니다(이는 재귀 프로세스입니다). 구성 요소 생성 프로세스에는 대략 다음과 같은 핵심 사항이 있습니다.

      컴포넌트 등록 정보에 따라 컴포넌트 프로토타입에서 컴포넌트 노드의 JS 객체, 즉 컴포넌트의 this 객체를 생성합니다. code>;

      구성요소 등록 정보 만들기 data의 복사본을 구성요소 데이터로 복사합니다. 즉, this.data

      이 데이터를 다음과 결합합니다. WXML 구성요소는 섀도우 트리(구성요소의 노드 트리)를 생성합니다. 섀도우 트리</code에서 다른 구성요소를 참조할 수 있기 때문입니다. >, 이는 다른 구성 요소의 생성 프로세스를 재귀적으로 트리거합니다. </span></strong></p><p> <code>ShadowTreeComposed Tree(마지막으로 연결된 ​​페이지 노드 트리)에 연결하고 일부를 생성합니다. 구성 요소 업데이트 성능을 최적화하기 위해 데이터를 캐시합니다.

      구성 요소 생성 수명 주기 기능을 트리거합니다.

      페이지 루트 구성 요소가 아닌 경우 구성 요소의 속성 값을 설정해야 합니다. 구성 요소 노드의 속성 정의에 따라 구성 요소 인스턴스가 페이지에 표시될 때 구성 요소의 attached 수명 주기 기능이 트리거될 때 Shadow에 다른 구성 요소가 있는 경우 트리, 해당 수명 주기 기능도 하나씩 트리거됩니다.

      selectComponent

      컴포넌트 통신

      비즈니스 책임으로 인해 큰 페이지를 여러 구성 요소로 분할해야 하는 경우가 많으며, 여러 구성 요소 간에 데이터 통신이 필요합니다.

      세대 간 구성 요소 통신을 위해 전역 상태 관리를 고려할 수 있습니다. 여기서는 일반적인 상위-하위 구성 요소 통신만 논의합니다. 🎜🎜🎜🎜방법 1 WXML 데이터 바인딩 🎜🎜🎜🎜은 상위 구성 요소가 데이터를 지정된 속성으로 설정하는 데 사용됩니다. 하위 구성 요소. 🎜🎜하위 항목은 속성 속성을 선언합니다.🎜
      <view>
          <vtabs-content="goods-content{{ index }}"></vtabs-content>
      </view>
      로그인 후 복사
      🎜상위 구성 요소 호출: 🎜
      Page({
          reCalcContentHeight(index) {
              const goodsContent = this.selectComponent(`#goods-content${index}`);
          },
      })
      로그인 후 복사
      🎜🎜🎜방법 2 이벤트🎜🎜🎜🎜는 하위 구성 요소가 상위 구성 요소에 데이터를 전달하는 데 사용되며 모든 데이터가 전달될 수 있습니다. 🎜🎜하위 구성 요소에서 이벤트를 전달하려면 먼저 wxml 구조에서 하위 구성 요소의 클릭 이벤트를 바인딩하세요. 🎜
      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 });
                  }
              });
          } 
      }
      로그인 후 복사
      로그인 후 복사
      🎜 그런 다음 js 파일에서 이벤트를 전달하세요. 이벤트 이름을 사용자 정의할 수 있습니다. 2번째 파라미터는 데이터 객체를 전달할 수 있으며, 3번째 파라미터는 이벤트 옵션입니다. 🎜
      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
          };
      };
      로그인 후 복사
      로그인 후 복사
      🎜마지막으로 다음을 사용하여 상위 구성 요소에서 수신합니다. 🎜
      jumpTo({ 
          url: &#39;pages/consignment/index&#39;, 
          { 
              sender: { name: &#39;naluduo233&#39; }
          }
      });
      로그인 후 복사
      로그인 후 복사
      🎜🎜🎜메서드 3 selectComponent를 사용하여 구성 요소 인스턴스 객체 가져오기 🎜🎜🎜🎜 🎜 메소드를 통해 하위 구성 요소의 인스턴스를 가져올 수 있으므로 하위 구성 요소의 메서드를 호출할 수 있습니다. . 🎜🎜Parent 컴포넌트의 wxml🎜
      const sender = JSON.parse(getParam(&#39;sender&#39;) || &#39;{}&#39;);
      로그인 후 복사
      로그인 후 복사
      🎜Parent 컴포넌트의 js🎜
      // 返回当前页面
      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];
      }
      로그인 후 복사
      로그인 후 복사
      🎜selector는 CSS selector와 유사하지만 다음 구문만 지원합니다. 🎜
      • ID选择器:#the-id(笔者只测试了这个,其他读者可自行测试)
      • class选择器(可以连续指定多个):.a-class.another-class
      • 子元素选择器:.the-parent > .the-child
      • 后代选择器:.the-ancestor .the-descendant
      • 跨自定义组件的后代选择器:.the-ancestor >>> .the-descendant
      • 多选择器的并集:#a-node, .some-other-nodes

      方法四 url 参数通信

      WeChat 미니 프로그램의 구성 요소를 사용자 정의하는 방법에 대한 간략한 분석

      在电商/物流等微信小程序中,会存在这样的用户故事,有一个「下单页面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(&#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 });
                  }
              });
          } 
      }
      로그인 후 복사
      로그인 후 복사

      jumpTo 辅助函数:

      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
          };
      };
      로그인 후 복사
      로그인 후 복사

      在「下单页面A」传递数据:

      jumpTo({ 
          url: &#39;pages/consignment/index&#39;, 
          { 
              sender: { name: &#39;naluduo233&#39; }
          }
      });
      로그인 후 복사
      로그인 후 복사

      在「货物信息页面B」获得 URL 参数:

      const sender = JSON.parse(getParam(&#39;sender&#39;) || &#39;{}&#39;);
      로그인 후 복사
      로그인 후 복사

      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: &#39;&#39;,
          queries: {}
      };
      로그인 후 복사

      更新跳转函数

      export function jumpTo(url, options) {
          // ...
          Object.assign(queryMap, {
              page: baseUrl,
              queries: options
          });
          // ...
          if (jumpType === &#39;switchTab&#39;) {
              wx.switchTab({ url: baseUrl });
          } else if (jumpType === &#39;navigateTo&#39; && 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: &#39;pageB?id=1&#39;,
          events: {
              // 为指定事件添加一个监听器,获取被打开页面传送到当前页面的数据
              acceptDataFromOpenedPage: function(data) {
                console.log(data) 
              },
          },
          success: function(res) {
              // 通过eventChannel向被打开页面传送数据
              res.eventChannel.emit(&#39;acceptDataFromOpenerPage&#39;, { data: &#39;test&#39; })
          }
      });
      로그인 후 복사

      pageB 页面

      Page({
          onLoad: function(option){
              const eventChannel = this.getOpenerEventChannel()
              eventChannel.emit(&#39;acceptDataFromOpenedPage&#39;, {data: &#39;test&#39;});
         
              // 监听acceptDataFromOpenerPage事件,获取上一页面通过eventChannel传送到当前页面的数据
              eventChannel.on(&#39;acceptDataFromOpenerPage&#39;, 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.navigateBackwx.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(&#39;update&#39;, (data) => console.log(data));
      로그인 후 복사

      在 PageB 页面派发

      eventBus.dispatch(&#39;someEvent&#39;, { name: &#39;naluduo233&#39;});
      로그인 후 복사

      小结

      本文主要讨论了微信小程序如何自定义组件,涉及两个方面:

      • 组件的声明与使用
      • 组件的通信

      如果你使用的是 taro 的话,直接按照 react 的语法自定义组件就好。而其中的组件通信的话,因为 taro 最终也是会编译为微信小程序,所以 url 和 eventbus 的页面组件通信方式是适用的。后续会分析 vant-ui weapp 的一些组件源码,看看有赞是如何实践的。

      感谢阅读,如有错误的地方请指出

      【相关学习推荐:小程序开发教程

      위 내용은 WeChat 미니 프로그램의 구성 요소를 사용자 정의하는 방법에 대한 간략한 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
1 몇 달 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

Xianyu WeChat 미니 프로그램 공식 출시 Xianyu WeChat 미니 프로그램 공식 출시 Feb 10, 2024 pm 10:39 PM

Xianyu의 공식 WeChat 미니 프로그램이 조용히 출시되었습니다. 미니 프로그램에서는 비공개 메시지를 게시하여 구매자/판매자와 소통하고, 개인 정보 및 주문 보기, 상품 검색 등을 할 수 있습니다. 궁금하시다면 Xianyu WeChat mini가 무엇인가요? 프로그램을 살펴볼까요? Xianyu WeChat 애플릿의 이름은 무엇입니까? 답변: Xianyu, 유휴 거래, 중고 판매, ​​평가 및 재활용. 1. 미니 프로그램에서는 대기 메시지 게시, 비공개 메시지를 통한 구매자/판매자와의 커뮤니케이션, 개인 정보 및 주문 보기, 특정 항목 검색 등을 할 수 있습니다. 2. 미니 프로그램 페이지에는 근처에 홈페이지가 있습니다. 유휴 게시, 메시지, 내 5가지 기능 3. 사용하려면 구매하기 전에 WeChat 결제를 활성화해야 합니다.

WeChat 애플릿은 사진 업로드 기능을 구현합니다. WeChat 애플릿은 사진 업로드 기능을 구현합니다. Nov 21, 2023 am 09:08 AM

WeChat 애플릿은 사진 업로드 기능을 구현합니다. 모바일 인터넷의 발전으로 WeChat 애플릿은 사람들의 삶에 없어서는 안될 부분이 되었습니다. WeChat 미니 프로그램은 다양한 애플리케이션 시나리오를 제공할 뿐만 아니라 이미지 업로드 기능을 포함한 개발자 정의 기능도 지원합니다. 이 기사에서는 WeChat 애플릿에서 이미지 업로드 기능을 구현하는 방법을 소개하고 구체적인 코드 예제를 제공합니다. 1. 준비 작업 코드 작성을 시작하기 전에 WeChat 개발자 도구를 다운로드하여 설치하고 WeChat 개발자로 등록해야 합니다. 동시에 WeChat도 이해해야 합니다.

WeChat 애플릿에서 드롭다운 메뉴 효과 구현 WeChat 애플릿에서 드롭다운 메뉴 효과 구현 Nov 21, 2023 pm 03:03 PM

WeChat 미니 프로그램에서 드롭다운 메뉴 효과를 구현하려면 구체적인 코드 예제가 필요합니다. 모바일 인터넷의 인기로 인해 WeChat 미니 프로그램은 인터넷 개발의 중요한 부분이 되었으며 점점 더 많은 사람들이 관심을 갖고 주목하기 시작했습니다. WeChat 미니 프로그램을 사용하세요. WeChat 미니 프로그램 개발은 기존 APP 개발보다 간단하고 빠르지만 특정 개발 기술을 숙달해야 합니다. WeChat 미니 프로그램 개발에서 드롭다운 메뉴는 일반적인 UI 구성 요소로, 더 나은 사용자 경험을 제공합니다. 이 기사에서는 WeChat 애플릿에서 드롭다운 메뉴 효과를 구현하는 방법을 자세히 소개하고 실용적인 정보를 제공합니다.

WeChat 미니 프로그램에 이미지 필터 효과 구현 WeChat 미니 프로그램에 이미지 필터 효과 구현 Nov 21, 2023 pm 06:22 PM

WeChat 미니 프로그램에서 사진 필터 효과 구현 소셜 미디어 애플리케이션의 인기로 인해 사람들은 사진의 예술적 효과와 매력을 높이기 위해 사진에 필터 효과를 적용하는 것을 점점 더 좋아하고 있습니다. WeChat 미니 프로그램에서도 사진 필터 효과를 구현할 수 있어 사용자에게 더욱 흥미롭고 창의적인 사진 편집 기능을 제공합니다. 이 기사에서는 WeChat 미니 프로그램에서 이미지 필터 효과를 구현하는 방법을 소개하고 구체적인 코드 예제를 제공합니다. 먼저 WeChat 애플릿의 캔버스 구성 요소를 사용하여 이미지를 로드하고 편집해야 합니다. 페이지에서 캔버스 구성요소를 사용할 수 있습니다.

WeChat 애플릿을 사용하여 캐러셀 전환 효과 달성 WeChat 애플릿을 사용하여 캐러셀 전환 효과 달성 Nov 21, 2023 pm 05:59 PM

WeChat 애플릿을 사용하여 캐러셀 전환 효과를 얻으세요. WeChat 애플릿은 개발 및 사용이 간단하고 효율적인 경량 애플리케이션입니다. WeChat 미니 프로그램에서는 캐러셀 전환 효과를 달성하는 것이 일반적인 요구 사항입니다. 이 기사에서는 WeChat 애플릿을 사용하여 캐러셀 전환 효과를 얻는 방법을 소개하고 구체적인 코드 예제를 제공합니다. 먼저 WeChat 애플릿의 페이지 파일에 캐러셀 구성 요소를 추가합니다. 예를 들어 &lt;swiper&gt; 태그를 사용하여 캐러셀의 전환 효과를 얻을 수 있습니다. 이 구성 요소에서는 b를 전달할 수 있습니다.

Xianyu WeChat 애플릿의 이름은 무엇입니까? Xianyu WeChat 애플릿의 이름은 무엇입니까? Feb 27, 2024 pm 01:11 PM

Xianyu의 공식 WeChat 미니 프로그램이 사용자에게 유휴 항목을 쉽게 게시하고 거래할 수 있는 편리한 플랫폼을 제공하기 위해 조용히 출시되었습니다. 미니 프로그램에서는 비공개 메시지를 통해 구매자 또는 판매자와 소통할 수 있으며, 개인정보 및 주문 조회, 원하는 상품을 검색할 수 있습니다. 그렇다면 WeChat 미니 프로그램에서 Xianyu는 정확히 무엇이라고 불리나요? 이 튜토리얼 가이드에서는 이에 대해 자세히 소개합니다. 알고 싶은 사용자는 이 기사를 따라 계속 읽어보세요! Xianyu WeChat 애플릿의 이름은 무엇입니까? 답변: Xianyu, 유휴 거래, 중고 판매, ​​평가 및 재활용. 1. 미니 프로그램에서는 대기 메시지 게시, 비공개 메시지를 통한 구매자/판매자와의 커뮤니케이션, 개인 정보 및 주문 보기, 특정 항목 검색 등을 할 수 있습니다. 2. 미니 프로그램 페이지에는 근처에 홈페이지가 있습니다. 유휴 게시, 메시지 및 5가지 기능.

WeChat 애플릿에서 이미지 회전 효과 구현 WeChat 애플릿에서 이미지 회전 효과 구현 Nov 21, 2023 am 08:26 AM

WeChat 미니 프로그램에서 이미지 회전 효과를 구현하려면 구체적인 코드 예제가 필요합니다. WeChat 미니 프로그램은 사용자에게 풍부한 기능과 좋은 사용자 경험을 제공하는 경량 애플리케이션입니다. 미니 프로그램에서 개발자는 다양한 구성 요소와 API를 사용하여 다양한 효과를 얻을 수 있습니다. 그 중 그림 회전 효과는 미니프로그램에 흥미와 시각 효과를 더할 수 있는 일반적인 애니메이션 효과이다. WeChat 미니 프로그램에서 이미지 회전 효과를 얻으려면 미니 프로그램에서 제공하는 애니메이션 API를 사용해야 합니다. 다음은 방법을 보여주는 특정 코드 예제입니다.

WeChat 미니 프로그램에서 슬라이딩 삭제 기능 구현 WeChat 미니 프로그램에서 슬라이딩 삭제 기능 구현 Nov 21, 2023 pm 06:22 PM

WeChat 미니 프로그램에서 슬라이딩 삭제 기능을 구현하려면 특정 코드 예제가 필요합니다. WeChat 미니 프로그램의 인기로 인해 개발자는 개발 과정에서 일부 공통 기능의 구현 문제에 직면하는 경우가 많습니다. 그중 슬라이딩 삭제 기능은 일반적으로 사용되는 기능 요구 사항입니다. 이 기사에서는 WeChat 애플릿에서 슬라이딩 삭제 기능을 구현하는 방법을 자세히 소개하고 구체적인 코드 예제를 제공합니다. 1. 요구 사항 분석 WeChat 미니 프로그램에서 슬라이딩 삭제 기능의 구현에는 다음 사항이 포함됩니다. 목록 표시: 슬라이드 및 삭제할 수 있는 목록을 표시하려면 각 목록 항목에 다음이 포함되어야 합니다.

See all articles