• 小程序跨页面数据传递与事件响应


    在实际工作中有很多场景需要在第二个页面中将用户操作之后的将数据回传到上一页面。接下来将我的方案分享给小伙伴。 本次示例采用 uni-app 框架和 weui 样式库 实现思路 创建一个 Emitter,用于事件处理 创建一个 ...

     
     
     

    在实际工作中有很多场景需要在第二个页面中将用户操作之后的将数据回传到上一页面。接下来将我的方案分享给小伙伴。

    本次示例采用 uni-app 框架和 weui 样式库

    实现思路

    1. 创建一个 Emitter,用于事件处理
    2. 创建一个全局的 Storage
    3. 在第一个页面创建一个 emitter 对象,并添加事件监听,将 emitter 存储到 Storage 中
    4. 在第二个页面从 Storage 中取出 emitter 对象, 并触发事件,将数据传递到第一个页面中做处理

    创建 Emitter

    function isFunc(fn) {
      return typeof fn === 'function';
    }
    
    export default class Emitter {
      constructor() {
        this._store = {};
      }
    
      /**
       * 事件监听
       * @param {String} event 事件名
       * @param {Function} listener 事件回调函数
       */
      on(event, listener) {
        const listeners = this._store[event] || (this._store[event] = []);
    
        listeners.push(listener);
      }
    
      /**
       * 取消事件监听
       * @param {String} event 事件名
       * @param {Function} listener 事件回调函数
       */
      off(event, listener) {
        const listeners = this._store[event] || (this._store[event] = []);
    
        listeners.splice(listeners.findIndex(item => item === listener), 1);
      }
    
      /**
       * 事件监听 仅监听一次
       * @param {String} event 事件名
       * @param {Function} listener 事件回调函数
       */
      once(event, listener) {
        const proxyListener = (data) => {
          isFunc(listener) && listener.call(null, data);
    
          this.off(event, proxyListener);
        }
    
        this.on(event, proxyListener);
      }
    
      /**
       * 触发事件
       * @param {String} 事件名
       * @param {Object} 传给事件回调函数的参数
       */
      emit(event, data) {
        const listeners = this._store[event] || (this._store[event] = []);
    
        for (const listener of listeners) {
          isFunc(listener) && listener.call(null, data);
        }
      }
    }
    
    复制代码

    创建 Storage

    export class Storage {
      constructor() {
        this._store = {};
      }
    
      add(key, val) {
        this._store[key] = val;
      }
      
      get(key) {
        return this._store[key];
      }
      
      remove(key) {
        delete this._store[key];
      }
      
      clear() {
        this._store = {};
      }
    }
    
    export default new Storage();
    
    复制代码

    第一个页面中的处理

    <template>
      <div class="page">
        <div class="weui-cells__title">选择城市</div>
        <div class="weui-cells weui-cells_after-title">
          <navigator :url="`../select/select?id=${cityId}`" class="weui-cell weui-cell_access" hover-class="weui-cell_active">
            <div class="weui-cell__hd weui-label">所在城市</div>
            <div class="weui-cell__bd" :style="{color: cityName || '#999'}">{{ cityName || '请选择' }}</div>
            <div class="weui-cell__ft weui-cell__ft_in-access"></div>
          </navigator>
        </div>
      </div>
    </template>
    
    <script>
    import Emitter from '../../utils/emitter';
    import storage from '../../utils/storage';
    
    export default {
      data() {
        return {
          cityId: '',
          cityName: '',
        }
      },
      onLoad() {
        const emitter = new Emitter();
    
        // 将emitter存到storage中
        storage.add('indexEmitter', emitter);
    
        // 添加事件监听
        emitter.on('onSelect', this.handleSelect);
      },
      methods: {
        // 事件处理
        handleSelect(data) {
          this.cityId = data.id;
          this.cityName = data.text;
        }
      }
    }
    </script>
    
    复制代码

    第二个页面中的处理

    <template>
      <div class="page">
        <div class="weui-cells__title">城市列表</div>
        <div class="weui-cells weui-cells_after-title">
          <radio-group @change="handleChange">
            <label class="weui-cell weui-check__label" v-for="item in list" :key="item.id">
              <radio class="weui-check" :value="item.id" :checked="`${item.id}` === selectedId" />
              <div class="weui-cell__bd">{{ item.text }}</div>
              <div v-if="`${item.id}` === selectedId" class="weui-cell__ft weui-cell__ft_in-radio">
                <icon class="weui-icon-radio" type="success_no_circle" size="16" />
              </div>
            </label>
          </radio-group>
        </div>
      </div>
    </template>
    
    <script>
    import storage from '../../utils/storage';
    
    export default {
      data() {
        return {
          list: [
            { id: 0, text: '北京' },
            { id: 1, text: '上海' },
            { id: 2, text: '广州' },
            { id: 3, text: '深圳' },
            { id: 4, text: '杭州' },
          ],
          selectedId: ''
        }
      },
      onLoad({ id }) {
        this.selectedId = id;
        
        // 取出 emitter
        this.emitter = storage.get('indexEmitter');
      },
      methods: {
        handleChange(e) {
          this.selectedId = e.detail.value;
    
          const item = this.list.find(({ id }) => `${id}` === e.detail.value);
    
          // 触发事件并传递数据
          this.emitter.emit('onSelect', { ...item });
        }
      }
    }
    </script>
    
    复制代码

    效果展示

    传送门

    github

    总结

    之所以将Storage定义成全局的,是为了保证第一个页面放到Storage中和第二个页面从 Storage 中取出的emitter是同一个实例,如此第一个页面才能正确监听到第二个页面触发的事件。也可以使用 vuex,将 emitter 放到 state 中。


     转自:http://www.wxapp-union.com/article-5740-1.html
  • 相关阅读:
    js异步编程
    gitreset
    js数据类型
    vuex报错
    个人管理系统综述
    ffmpeg第7篇:数据流选择神器map指令
    eltable多选框根据条件隐藏显示
    [域渗透内网渗透] 从 web 到域控,你未曾设想的攻击链
    宽字节第二期线下培训开始招生啦!!!
    cve20212394 weblogic反序列化漏洞分析
  • 原文地址:https://www.cnblogs.com/zmdComeOn/p/12053740.html
Copyright © 2020-2023  润新知