欢迎您光临深圳塔灯网络科技有限公司!
电话图标 余先生:13699882642

网站百科

为您解码网站建设的点点滴滴

关于原生小程序页面间数据传送的研究

发表日期:2019-11 文章编辑:小灯 浏览次数:3607

第一次在公司里负责做小程序,因为第一次做怕遇到大坑,所以用的原生开发。页面数据共享比较常用,所以来研究研究。
  1. A页面直接url传参 B页面onload里接收。这种简单粗暴但B如果还想给A传参感觉不太方便。而且传一个很大的对象过去,必须要stringfy。但是地址长度有限所以会有bug
  2. 直接wx.setStorage 简单粗暴,直接存微信本地。有时候我并不想存太久,只是临时的数据也给我存本地了感觉怪怪的。
  3. getCurrentPages() 这个可以拿当前的页面栈,通过他来那上一个页面,上上个页面的信息。有时候一个页面说不定有很多种进入途径,也不知道上个页面是啥,用起来也有点怕怕的。
  4. app.globalData 里存一个临时数据比如payload:null,当要A页面要传参时改变payload值,然后B页面获取到后置为null。我一般就这么搞感觉还行。
  5. 有米有什么更好的方法呢,我发现现在的小程序框架都是有状态管理的,要不我也整个。我就研究了下,抄个乞丐版的redux放在小程序里用用。以下为代码。

一、上来建个文件夹把redux相关的代码丢上去。

//createStore.js

export default function createStore(reducer, preloadedState, enhancer) {
  //放中间件用 其实就是在enhancer里调用createStore 并修改dispatch
  if (enhancer && typeof enhancer === 'function') {
    return enhancer(createStore)(reducer, preloadedState)
  }
  
  //初始state赋值
  let state = preloadedState;
  let listeners = [];

  const getState = () => state;
   //触发动作
  const dispatch = (action) => {
    state = reducer(state, action);
    listeners.forEach(listener => listener());
  };
  //添加监听器,无非加些有setData的方法进去
  const subscribe = (listener) => {
    listeners.push(listener);
    return () => {
      listeners = listeners.filter(l => l !== listener);
    }
  };

   //初始化
  dispatch({});

  return { getState, dispatch, subscribe };
}

具体代码可以看代码地址
对于redux不太理解的同学可以看看其它文章。有很多高手写,我这个菜鸟就不写了:)

二、把store 存到app.js里

import store from './store/index.js'
import bindActionCreator from '/store/hcyRedux/bindActionCreator.js'
App({
  globalData: {
    store,
    bindActionCreator //方便dispatch
  }
})

三、建action

// /action/page2
import * as types from '../action-types'
//创建 action的函数
export default {
  change(obj) {
    return { type: 'page2/' + types.INPUT, payload: obj }
  },
  promiseChange(obj) {
    return {
      type: 'page2/' + types.INPUT,
      payload: new Promise(function (resolve, reject) {
        setTimeout(function () {
          resolve(obj)
        }, 1000)
      })
    }
  }
}

// /action/page1
import * as types from '../action-types'
//创建 action的函数
export default {
  change(obj) {
    return { type: 'page1/' + types.INPUT, payload: obj}
  }
}

四、建reducer

import * as types from '../action-types'
const head = 'page2/'
const defaultValue = {
  input1: 4,
  input2: 5,
  input3: 6
}
export default function (state = defaultValue, action) {
  switch (action.type) {
    case head + types.INPUT:
      return { ...state, ...action.payload };
    default:
      return state
  }
}

这是page2的page1也差不多

这样子不管什么页面可以通过app.globalData.store.getState()想怎么取值都可以了。
当然每个页面的onload 和 onUnLoad 都必须添加和删除监听(就是setData)这样dispatch 之后页面才会渲染。

这样基本就完成了。但我不想每个页面都添加删除监听。可以这么干。

// 自己封装了一个mini-redux.js
const app = getApp();
const store = app.globalData.store;

//得到一个{page1:{。。。},page2{。。。}}这样一个对象
function getData (obj) {
  let res = {}
  obj.pages.forEach(x => {
    res[x] = store.getState()[x]
  })
  return res
}

export default function (obj) {
  let listener = null;
  let res = {};
  this.action = obj.action.map(x => app.globalData.bindActionCreator(x, store.dispatch));
  this.store = store
  return {
    ...obj,
    data: getData(obj),
    onLoad: function () {
      listener = store.subscribe(() => {
        this.setData(getData(obj))
      })
      store.dispatch({})
      obj.onLoad && obj.onLoad();
    },
    onUnload() {
      listener();
      obj.onUnload && obj.onUnload();
    }
  }
}

page2页面

<view class="page-section">
  <view class="weui-cells__title">{{page2.input1}}</view>
  <view class="weui-cells weui-cells_after-title">
    <view class="weui-cell weui-cell_input">
      <input class="weui-input" placeholder="test" value="{{page2.input1}}" bindinput="bindKeyInput" data-key="input1" />
    </view>
  </view>
</view>
<view class="page-section">
  <view class="weui-cells__title">{{page2.input2}}</view>
  <view class="weui-cells weui-cells_after-title">
    <view class="weui-cell weui-cell_input">
      <input class="weui-input" placeholder="test" value="{{page2.input2}}" bindinput="bindKeyInput" data-key="input2" />
    </view>
  </view>
</view>
<view class="page-section">
  <view class="weui-cells__title">{{page2.input3}}</view>
  <view class="weui-cells weui-cells_after-title">
    <view class="weui-cell weui-cell_input">
      <input class="weui-input" placeholder="test" value="{{page2.input3}}" bindinput="bindKeyInput" data-key="input3" />
    </view>
  </view>
</view>
<text>{{page1.input1}}</text>
<navigator url="/pages/page2/page2">
  <button type="primary"> 2 </button>
</navigator>

page2.js

import actions1 from '../../store/actions/page1.js'
import actions2 from '../../store/actions/page2.js'
import V from '../../utils/mini-redux.js'
const page = {}

Page(V.call(page,{
  action: [actions1, actions2], //定义好用那些action
  pages:['page1', 'page2'], //定义好需要用那些store 是在reducer/index.js 定义的
  bindKeyInput(e) {
    //action[0] 就是actions1
    page.action[0].change({
      [e.target.dataset.key]: e.detail.value
    });
    page.action[1].promiseChange({
      [e.target.dataset.key]: e.detail.value
    });
  },
  onShow() {
    console.log('show2')
  },
  onLoad () {
    console.log('load2')
  }
}))

具体代码可以看代码地址

还是有些问题 每次dispatch 会触发页面栈的所有页面的监听,页面可以直接setData store 等等。这些地方应该还可以优化。


本页内容由塔灯网络科技有限公司通过网络收集编辑所得,所有资料仅供用户学习参考,本站不拥有所有权,如您认为本网页中由涉嫌抄袭的内容,请及时与我们联系,并提供相关证据,工作人员会在5工作日内联系您,一经查实,本站立刻删除侵权内容。本文链接:https://dengtar.com/25242.html
相关小程序
 八年  行业经验

多一份参考,总有益处

联系深圳网站公司塔灯网络,免费获得网站建设方案及报价

咨询相关问题或预约面谈,可以通过以下方式与我们联系

业务热线:余经理:13699882642

Copyright ? 2013-2018 Tadeng NetWork Technology Co., LTD. All Rights Reserved.