欧美三级国产三级日韩三级_亚洲熟妇丰满大屁股熟妇_欧美亚洲成人一区二区三区_国产精品久久久久久模特

小程序-頁(yè)面與頁(yè)面間如何進(jìn)行傳遞數(shù)據(jù)(通信) - 新聞資訊 - 云南小程序開(kāi)發(fā)|云南軟件開(kāi)發(fā)|云南網(wǎng)站建設(shè)-昆明葵宇信息科技有限公司

159-8711-8523

云南網(wǎng)建設(shè)/小程序開(kāi)發(fā)/軟件開(kāi)發(fā)

知識(shí)

不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價(jià)值,我們?cè)谧非笃湟曈X(jué)表現(xiàn)的同時(shí),更側(cè)重于功能的便捷,營(yíng)銷的便利,運(yùn)營(yíng)的高效,讓網(wǎng)站成為營(yíng)銷工具,讓軟件能切實(shí)提升企業(yè)內(nèi)部管理水平和效率。優(yōu)秀的程序?yàn)楹笃谏?jí)提供便捷的支持!

您當(dāng)前位置>首頁(yè) » 新聞資訊 » 小程序相關(guān) >

小程序-頁(yè)面與頁(yè)面間如何進(jìn)行傳遞數(shù)據(jù)(通信)

發(fā)表時(shí)間:2021-1-5

發(fā)布人:葵宇科技

瀏覽次數(shù):47

在小程序中組件與組件之間的通信是通過(guò)在引用組件處,在自定義組件上添加自定義屬性實(shí)現(xiàn)的,子組件內(nèi)部通過(guò)properties進(jìn)行接收

更多關(guān)于組件與組件之間的通信可參考小程序?qū)崿F(xiàn)自定義組件以及自定義組件間的通信這篇文章

那頁(yè)面與頁(yè)面之間又如何傳遞數(shù)據(jù)?

您將閱讀完本文后,將收獲到:

  1. 頁(yè)面間跳轉(zhuǎn)攜帶參數(shù)(通過(guò)url的方式)傳遞數(shù)據(jù)
  2. 如何返回上一級(jí)頁(yè)面,并刷新頁(yè)面呢
  3. 使用全局app頁(yè)面定義的變量實(shí)現(xiàn)數(shù)據(jù)的傳遞
  4. 使用本地緩存數(shù)據(jù)
  5. 使用 eventChannel 向被打開(kāi)頁(yè)面?zhèn)魉蛿?shù)據(jù)(wx.navigateTo高級(jí)用法)


頁(yè)面間通過(guò) url 方式傳遞數(shù)據(jù)

在小程序中當(dāng)中,在父頁(yè)面,通過(guò)url方式傳遞參數(shù)到子頁(yè)面,是一種比較常見(jiàn)的做法

如下示例所示:應(yīng)用場(chǎng)景

  1. 點(diǎn)擊列表頁(yè)面,進(jìn)入詳情頁(yè)
  2. 動(dòng)態(tài)改變?cè)斍轫?yè)面的navBar中的title

父頁(yè)面實(shí)例代碼

<view>
  <view class="list-wrap">
    <block wx:for="{{listDatas}}" wx:key="index">
      <view bindtap="onListTap" data-list="{{item}}">
        <text>{{ item.list_text}}text>
      view>
    block>
  view>
view>

css代碼

.list-wrap {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  padding: 15px 15px;
}

.list-wrap view {
  width: 30%;
  height: 300rpx;
  border: 1px solid #ccc;
  margin-bottom: 15px;
  text-align: center;
  line-height: 300rpx;
  font-size: 28rpx;
}

js代碼

Page({
  /**
   * 頁(yè)面的初始數(shù)據(jù)
   */
  data: {
    listDatas: [
      {
        listId: '1',
        list_text: '建鋼構(gòu)混泥房',
        link_phone: '137-0113-4148',
        linker: '王經(jīng)理',
      },

      {
        listId: '2',
        list_text: '建辦公樓房',
        link_phone: '137-0113-4148',
        linker: '陳經(jīng)理',
      },

      {
        listId: '3',
        list_text: '建冰場(chǎng)鋼結(jié)構(gòu)',
        link_phone: '137-0113-4148',
        linker: '張經(jīng)理',
      },
    ],
  },

  /**
   * 生命周期函數(shù)--監(jiān)聽(tīng)頁(yè)面加載
   */
  onLoad: function(options) {},

  onListTap(event) {
    const {
      listId,
      list_text,
      link_phone,
      linker,
    } = event.currentTarget.dataset.list;
    // 1. 傳遞參數(shù)-通過(guò)url的方式傳遞當(dāng)前頁(yè)面數(shù)據(jù)到子頁(yè)面當(dāng)中去,在子頁(yè)面的onload的options中可以拿到
    wx.navigateTo({
      url: `/pages/listDetail/listDetail?id=${listId}&navtitle=${list_text}&phone=${link_phone}&link=${linker}`,
    });
  },
});

切換tab選項(xiàng)就可以查看對(duì)應(yīng)的代碼,在上面示例中,從一個(gè)頁(yè)面跳轉(zhuǎn)到另一個(gè)頁(yè)面是使用wx.navigateTo()這個(gè)方法,如果想要將該頁(yè)面的數(shù)據(jù)傳遞到子頁(yè)面中,可以通過(guò)url拼接參數(shù)的方式進(jìn)行傳遞,多個(gè)參數(shù)之間使用&符號(hào)相連

路徑后可以帶參數(shù),參數(shù)與路徑之間使用 ? 分隔,參數(shù)鍵與參數(shù)值用 = 相連,不同參數(shù)用 & 分隔;如path?key=value&key2=value2

上面示例代碼中使用了es6的模板字符串,參數(shù)之間,也可以使用+拼接,個(gè)人覺(jué)得使用+真的很難受,不舒服,容易出錯(cuò)

如下是es6模板字符串方式拼接參數(shù)

wx.navigateTo({
  url: `/pages/listDetail/listDetail?id=${listId}&navtitle=${list_text}&phone=${link_phone}&link=${linker}`,
});

如下是加號(hào)拼接方式

 wx.navigateTo({
      url: "/pages/listDetail/listDetail?id="+listId+"&navtitle="+list_text+"&phone="+link_phone+"&link="+link_phone+"&link="+linker,
    })
  }

兩者比較

通過(guò)es6中的模板字符串,使用反引號(hào),結(jié)合模板字符串${變量}的方式,要比使用+加號(hào)拼接參數(shù)要好理解得多

在單個(gè)參數(shù)情況下,或許使用模板字符串與加號(hào)沒(méi)有影響,區(qū)別,但是當(dāng)多個(gè)參數(shù)時(shí),使用加號(hào)做拼接就會(huì)令人奔潰,很容易出錯(cuò)

甚至有可能在接收參數(shù)時(shí),出現(xiàn)丟失的情況,這或許就是不小心使用加號(hào)前后空格或解析參數(shù)時(shí),加號(hào)被轉(zhuǎn)義導(dǎo)致的,很容易出現(xiàn) bug

子頁(yè)面實(shí)例代碼

<view>
  <view class="container">
    <view>項(xiàng)目:<text>{{id}}-{{text}}text>view>
    <view>聯(lián)系人: {{link}}view>
    <view>聯(lián)系電話: {{phoneNumber}}view>
  view>
view>

css代碼

.container {
  padding: 20px 0 10px 30px;
}

.container view {
  line-height: 30px;
}

js邏輯代碼

Page({
  /**
   * 頁(yè)面的初始數(shù)據(jù)
   */
  data: {
    // 頁(yè)面中要渲染的數(shù)據(jù),數(shù)據(jù)初始化
    id: null,
    text: '',
    phoneNumber: '',
    linker: '',
  },

  /**
   * 生命周期函數(shù)--監(jiān)聽(tīng)頁(yè)面加載
   */
  onLoad: function(options) {
    console.log(options);
    const { id, navtitle, phone, link } = options;
    this._setNavTitle(navtitle);
    this._getList(id, navtitle, phone, link);
  },

  // 設(shè)置navTitle
  _setNavTitle(navtitle) {
    wx.setNavigationBarTitle({
      title: navtitle,
    });
  },

  _getList(id, navtitle, phone, link) {
    // 改變頁(yè)面中的數(shù)據(jù),setData
    this.setData({
      text: navtitle,
      id,
      phoneNumber: phone,
      link,
    });
  },
});

當(dāng)父頁(yè)面通過(guò)url的方式傳遞數(shù)據(jù)給子頁(yè)面時(shí),在子頁(yè)面中的生命周期onLoad函數(shù)中的options中可以拿到
想要更改什么數(shù)據(jù),直接重新setData就可以了的

注意

  1. url的方式適合頁(yè)面間跳轉(zhuǎn)攜帶參數(shù),多個(gè)參數(shù)之間使用&符號(hào)拼接
  2. 此方法有一定的局限性,不適宜傳入復(fù)雜的數(shù)據(jù),例如:數(shù)組,對(duì)象
  3. 適合參數(shù)比較少的情況

url 中有多個(gè)參數(shù)時(shí)傳遞

在小程序中,向跳轉(zhuǎn)的目標(biāo)url頁(yè)面?zhèn)鬟f的參數(shù)有時(shí)候遠(yuǎn)不止一個(gè),使用wx.navigator進(jìn)行跳轉(zhuǎn),支持/pages/xxx/xxx?param1=${param1}?m2=${param2}?m3=${param3}的方式,并不支持類似obj={key1:value1,key2: value2}對(duì)象或者數(shù)組list: [arr1, arr2, arr3 ..]

url參數(shù)是數(shù)組情況

wx.navigateTo({
  url: `/pages/listDetail/listDetail?list=${[
    listId,
    list_text,
    link_phone,
    linker,
  ]}`,
});

子頁(yè)面(跳轉(zhuǎn)目標(biāo)頁(yè))

onLoad: function (options) {
    console.log(options);
    const list = options.list.split(','); // 通過(guò)split分割成數(shù)組
    console.log(list);
  },

分析

當(dāng)被跳轉(zhuǎn)的 url 中的參數(shù)是數(shù)組時(shí),那么在跳轉(zhuǎn)的目標(biāo)頁(yè)面中的onLoad生命周期函數(shù)的option,將得到父頁(yè)面中的字符串參數(shù)

通過(guò)split方法將字符串分割為數(shù)組,然后通過(guò)數(shù)組下標(biāo)的方式拿到對(duì)應(yīng)的參數(shù)

父頁(yè)面中

const name = 'itclanCoder';
const sex = 'boy';
wx.navigateTo({
  url: `/pages/listDetail/listDetail?data=http://www.wxapp-union.com/${[name, sex]}`,
});

子頁(yè)面中

onLoad: function (options) {
    console.log(options);
    const data = http://www.wxapp-union.com/options.data.split(','); // 通過(guò)split分割成數(shù)組
    console.log(data); // ["itclanCoder", "boy"]
  },

url參數(shù)是對(duì)象情況

url參數(shù)是對(duì)象時(shí),并不會(huì)像數(shù)組一樣,在目標(biāo)頁(yè)面中onLoadoptions對(duì)象中是一個(gè)字符串,而卻是一個(gè)對(duì)象

如下所示

{
  obj: [object, object];
}

我們需要借助JSON.stringify()對(duì)傳入的參數(shù)對(duì)象進(jìn)行序列化

父頁(yè)面(對(duì)象參數(shù)序列化)

wx.navigateTo({
  url: `/pages/listDetail/listDetail?obj=${JSON.stringify({
    id: listId,
    text: list_text,
    phone: link_phone,
    link: linker,
  })}`,
});

通常,我們把參數(shù)對(duì)象,定義成一個(gè)對(duì)象的,簡(jiǎn)化我們的代碼,用一個(gè)變量對(duì)象臨時(shí)存儲(chǔ)的

const params = {
  // 參數(shù)放到外面,讓代碼更加清晰,可讀,可維護(hù)性更高
  id: listId,
  text: list_text,
  phone: link_phone,
  link: linker,
};
wx.navigateTo({
  url: `/pages/listDetail/listDetail?obj=${JSON.stringify(params)}`,
});

那么在子頁(yè)面中,需要通過(guò)JSON.parse()對(duì)父頁(yè)面中傳遞過(guò)來(lái)的參數(shù)進(jìn)行反序列化,否則拿到的將是字符串對(duì)象,是無(wú)法通過(guò)對(duì)象.的方式訪問(wèn)屬性

子頁(yè)面(對(duì)象參數(shù)反序列化)

onLoad: function (options) {
    console.log(options);
    const obj = JSON.parse(options.obj); // 將字符串對(duì)象轉(zhuǎn)化為真正的對(duì)象
    console.log(obj); // {id: "1", text: "建鋼構(gòu)混泥房", phone: "137-0113-4148", link: "王經(jīng)理"}
  },

分析
在父頁(yè)面中若跳轉(zhuǎn)目標(biāo)的 url 參數(shù)是對(duì)象的情況下,需要先將參數(shù)通過(guò)JSON.stringify()序列化才可以

const params = {
  // 參數(shù)放到外面,讓代碼更加清晰,可讀,可維護(hù)性更高
  id: 22,
  name: '川川',
  sex: 'boy',
};
wx.navigateTo({
  url: `/pages/listDetail/listDetail?obj=${JSON.stringify(params)}`,
});

那么在子頁(yè)面(目標(biāo)頁(yè)面中)的onLoadoptions

onLoad: function (options) {
    console.log(options);
    const obj = JSON.parse(options.obj); // 將字符串對(duì)象轉(zhuǎn)化為真正的對(duì)象
    console.log(obj); // {id: 22, name: "川川",sex: "boy"}
},

可能會(huì)遇到的問(wèn)題

當(dāng)傳遞的對(duì)象數(shù)據(jù)中含有特殊字符串時(shí),在下個(gè)頁(yè)面使用JSON.parse()還原為對(duì)象時(shí)會(huì)報(bào)錯(cuò)
也就是當(dāng)url傳參 參數(shù)值過(guò)長(zhǎng),在子頁(yè)面接收時(shí),會(huì)出現(xiàn)問(wèn)題,存在丟失情況

具體解決辦法

在上個(gè)頁(yè)面(被跳轉(zhuǎn)頁(yè)面)將對(duì)象轉(zhuǎn)化為字符串后(JSON.stringify()),然后使用encodeURIComponent進(jìn)行編碼,然后在下個(gè)頁(yè)面先用decodeURIComponent進(jìn)行解碼,最終在還原為對(duì)象

父(上個(gè))頁(yè)面編碼

const params = {
  // 參數(shù)放到外面,讓代碼更加清晰,可讀,可維護(hù)性更高
  id: 22,
  name: '川川',
  sex: 'boy',
};
const param = encodeURIComponent(JSON.stringify(params)); // 通過(guò)encodeURIComponent編碼
wx.navigateTo({
  url: `/pages/listDetail/listDetail?obj=${param}`,
});

子頁(yè)面解碼

onLoad: function (options) {
    console.log(options);
    const tempObj = decodeURIComponent(options.obj)
    const obj = JSON.parse(tempObj); // 將字符串對(duì)象轉(zhuǎn)化為真正的對(duì)象
    console.log(obj); // {id: 22, name: "川川",sex: "boy"}
},

注意

  1. 當(dāng)父頁(yè)面?zhèn)鬟f的url參數(shù)為對(duì)象時(shí),在子頁(yè)面是無(wú)法直接獲取的,在父頁(yè)面中,必須先使用JSON.stringify()轉(zhuǎn)換為字符串
    然后在下個(gè)頁(yè)面使用JSON.parse()還原為對(duì)象,這樣在子頁(yè)面中便可以通過(guò)對(duì)象的方式拿到
  2. 當(dāng)父頁(yè)面?zhèn)鬟f的url對(duì)象數(shù)據(jù)中含有特殊字符串時(shí),在子頁(yè)面使用 JSON.parse()還原為對(duì)象時(shí)會(huì)報(bào)錯(cuò)。需要在上個(gè)(父)頁(yè)面將對(duì)象轉(zhuǎn)化為字符串后(JSON.stringify()),在使用 encodeURIComponent 進(jìn)行編碼,然后在下個(gè)(子)頁(yè)面先用 decodeURIComponent 進(jìn)行解碼在還原(JSON.parse())為對(duì)象。

如何返回上一級(jí)頁(yè)面-并刷新頁(yè)面

在使用wx.navigateTo()API 進(jìn)行跳轉(zhuǎn)時(shí),在子頁(yè)面中可以通過(guò)wx.navigateBack()返回上一級(jí)頁(yè)面的

這個(gè)場(chǎng)景在日常開(kāi)發(fā)中,就有不少的

例如:寫(xiě)完微博,發(fā)完微博成功后,自動(dòng)要返回到首頁(yè),申請(qǐng)退款時(shí),跳轉(zhuǎn)到申清退款頁(yè)面等等的

const pages = getCurrentPages(); // 可以獲取當(dāng)前頁(yè)面棧,上一個(gè)頁(yè)面以及當(dāng)前頁(yè)面棧信息
console.log(pages); // 是一個(gè)數(shù)組,記錄了上一個(gè)頁(yè)面與當(dāng)前頁(yè)面信息
// 取到上一個(gè)頁(yè)面
const prevPage = pages[pages.length - 2]; // 獲取第0個(gè)頁(yè)面,也就是上個(gè)頁(yè)面
console.log(prevPage);
prevPage.onLoad(); // 可以調(diào)用上一頁(yè)面的方法
prevPage.setData({
  name: 'itclanCoder',
});

這個(gè)方法非常厲害,而且很有用,當(dāng)你通過(guò)wx.navigateTo(),一層一層跳轉(zhuǎn)到子頁(yè)面時(shí),使用getCurrentPages方法就可以找到上級(jí),上上級(jí)的頁(yè)面棧信息

它是通過(guò)獲取到其他頁(yè)面的原型對(duì)象,然后通過(guò)小程序原型下的setData方法,對(duì)當(dāng)前對(duì)象管理的數(shù)據(jù)data進(jìn)行修改

這個(gè)方法getCurrentPage方法可以操作頁(yè)面堆棧頁(yè)面的數(shù)據(jù)和方法,可以做到對(duì)子(后一)頁(yè)面對(duì)父(上一)頁(yè)面的數(shù)據(jù)管理

提示

getCurrentPages()用于獲取當(dāng)前頁(yè)面棧,數(shù)組中第一個(gè)元素為首頁(yè),最后一個(gè)元素為當(dāng)前頁(yè)面

  1. 不要嘗試修改頁(yè)面棧,會(huì)導(dǎo)致路由以及頁(yè)面狀態(tài)錯(cuò)誤(不要依賴這個(gè)方法)
  2. 不要在 App.onLaunch 的時(shí)候調(diào)用 getCurrentPages(),此時(shí) page 還沒(méi)有生成

使用全局app頁(yè)面定義的變量實(shí)現(xiàn)數(shù)據(jù)的傳遞

在小程序當(dāng)中,當(dāng)有多個(gè)頁(yè)面用到一些公共變量對(duì)象參數(shù)時(shí),例如:小程序的openId,一些公用的狀態(tài),可以放到全局app

全局頁(yè)面 app.js

//app.js
App({
  onLaunch: function() {
    // 定義的全局變量,如token,某些狀態(tài)等,放在globalData下
    this.globalData = http://www.wxapp-union.com/{
      token: 'token',
      url: 'http://coder.itclan.cn/',
      userInfo: 'itclanCoder',
    };
  },
});

使用頁(yè)面

const app = getApp(); // 在另一頁(yè)面想要使用全局變量處,調(diào)用getApp()
Page({
  // 頁(yè)面初始化的數(shù)據(jù)
  data: {
    token: '',
    url: '',
    userInfo: '',
  },
  // 生命周期函數(shù)
  onLoad: function(options) {},

  onGetGlobal() {
    // 獲取全局變量
    const { token, url, userInfo } = app.globalData;
    console.log(token, url, userInfo);
    this.setData({
      token,
      url,
      userInfo,
    });
  },
});

wxml

<view>
  <view class="globalData">
    <view class="getGloablBtn btn" bindtap="onGetGlobal">獲取全局變量view>
    <view class="changeGloablBtn btn" bindtap="onChangeGlobal"
      >修改全局變量view
    >
  view>
  <view>{{token}}view>
  <view>{{url}}view>
  <view>{{userInfo}}view>
view>

wxss

.globalData {
  display: flex;
  justify-content: start;
  margin: 15px 0 0 0;
}

.getGloablBtn {
  background: rgb(89, 196, 119);
  margin-right: 15px;
}

.changeGloablBtn {
  background: rgb(160, 10, 7);
}

.btn {
  width: 120px;
  height: 30px;
  line-height: 30px;
  color: #fff;
  text-align: center;
}

分析

全局定義的變量,一些狀態(tài),可以掛載在全局頁(yè)面 app.jsglobalData中,在使用全局變量頁(yè)面處

  1. 需要調(diào)用getApp()函數(shù)
  2. 通過(guò)getApp().globalData.a可以拿到全局對(duì)象下定義的變量對(duì)象
  3. 若要修改全局變量對(duì)象直接賦值即可getApp().globalData.a = "bb";

全局定義變量注意事項(xiàng)

  1. App()必須在app.js中注冊(cè),且不能注冊(cè)多個(gè)
  2. 不要在定義App()內(nèi)的函數(shù)調(diào)用getApp(),使用this就可以拿到App下的實(shí)例
  3. 不要在 App.onLaunch 的時(shí)候調(diào)用 getCurrentPages(),此時(shí) page 還沒(méi)有生成
  4. 通過(guò)getApp()獲取到全局頁(yè)面的實(shí)例后,就不要私自調(diào)用生命周期函數(shù)了的

使用本地緩存

在微信小程序都可以有自己的本地緩存

  • wx.setStorageSync:同步設(shè)置本地存儲(chǔ)某個(gè)指定的key數(shù)據(jù)
  • wx.setStorage: 異步設(shè)置本地所有存儲(chǔ)某個(gè)key數(shù)據(jù)
  • wx.getStorage: 異步獲取本地所有存儲(chǔ)數(shù)據(jù)
  • wx.getStorageSync:同步獲取本地存儲(chǔ)某個(gè)指定key的數(shù)據(jù)
  • wx.clearStorage:一次性清除所有本地存儲(chǔ)(緩存)數(shù)據(jù),不需要參數(shù)
  • wx.clearStorageSync:一次性清除同步所有本地存儲(chǔ),不需要參數(shù)
  • wx.removeStorage:從本地緩存中異步移除指定 key,需要指定某個(gè)key
  • wx.removeStorageSync:從本地存儲(chǔ)中同步移除指定的key,需要指定某個(gè)key

上面的方法可以對(duì)本地緩存進(jìn)行讀寫(xiě)和清理的操作,讀與寫(xiě)都是一一對(duì)應(yīng)的

使用本地緩存,可以作為頁(yè)面間數(shù)據(jù)傳遞,但是仍然需要注意一些實(shí)用情況,如下所示

隔離策略

同一個(gè)微信用戶,同一個(gè)小程序 storage上限為 10MB,一般可以作為緩存臨時(shí)一些小的數(shù)據(jù),比如用戶登錄信息之類的

storage 以用戶維度隔離,同一臺(tái)設(shè)備上,A 用戶無(wú)法讀取到 B 用戶的數(shù)據(jù);不同小程序之間也無(wú)法互相讀寫(xiě)數(shù)據(jù)

存儲(chǔ)大小限制

除非用戶主動(dòng)刪除或因存儲(chǔ)空間原因被系統(tǒng)清理,否則數(shù)據(jù)都一直可用。單個(gè) key 允許存儲(chǔ)的最大數(shù)據(jù)長(zhǎng)度為 1MB,所有數(shù)據(jù)存儲(chǔ)上限為 10MB

插件隔離限制

  1. 同一小程序使用不同插件:不同插件之間,插件與小程序之間 storage 不互通。
  2. 不同小程序使用同一插件:同一插件storage不互通
  3. storage只是針對(duì)當(dāng)前用戶,不同用戶,使用不同的插件,他們之間storage是無(wú)法實(shí)現(xiàn)數(shù)據(jù)共用的
    :::

清理策略

本地緩存的清理時(shí)機(jī)跟代碼包一樣,只有在代碼包被清理的時(shí)候本地緩存才會(huì)被清理

注意事項(xiàng)

將數(shù)據(jù)存儲(chǔ)在本地緩存中指定的 key 中。會(huì)覆蓋掉原來(lái)該 key 對(duì)應(yīng)的內(nèi)容

也就是說(shuō),如果是相同的key,后面的會(huì)覆蓋掉原來(lái)該 key 對(duì)應(yīng)的內(nèi)容

設(shè)置/獲取/刪除存儲(chǔ)

使用的是wx.setStorageSync(),wx.getStorageSync方法

如何設(shè)置本地存儲(chǔ)數(shù)據(jù)

wx.setStorage({
  key: 'key',
  data: 'value',
});

或如下簡(jiǎn)寫(xiě)方式

wx.setStorageSync('key', 'value');

如何獲取本地存儲(chǔ)數(shù)據(jù)

wx.getStorageSync({
  key: 'key',
  success(res) {
    console.log(res.data);
  },
});

或如下簡(jiǎn)寫(xiě)

var value = http://www.wxapp-union.com/wx.getStorageSync('key');

如何刪除本地存儲(chǔ)數(shù)據(jù)

清除小程序當(dāng)中的本地存儲(chǔ)分為一次性全部刪除所有存儲(chǔ),與刪除存儲(chǔ)中某指定的存儲(chǔ)key

wx.clearStorage(); // 一次性刪除小程序中的所有存儲(chǔ)數(shù)據(jù)

刪除存儲(chǔ)中某指定的存儲(chǔ)key,一定要注意這兩者的區(qū)別,有的小伙伴只知道wx.clearStorage()

wx.removeStorageSync('key'); // 刪除小程序中指定的key的存儲(chǔ)

同樣等價(jià)于

wx.removeStorageSync({
  key: 'key',
  success(res) {
    console.log(res);
  },
});

注意:wx.removeStorageSync方法,不同于wx.clearStorageSync()方法,它同樣也是刪除小程序中所有同步存儲(chǔ)的數(shù)據(jù),
前者需要指定刪除存儲(chǔ)對(duì)應(yīng)的key值,而后者不需要指定key,它是一次性刪除所有同步存儲(chǔ)的代碼

wx.clearStorageSync(); // 一次性刪除小程序中所有同步存儲(chǔ)的數(shù)據(jù)

關(guān)于小程序中本地存儲(chǔ)的方法確實(shí)容易讓人暈,搞混淆,理解它們的區(qū)別,還是要在開(kāi)發(fā)者工具中,自行調(diào)試,才知道每個(gè)方法之間區(qū)別差異的

光看文字,不動(dòng)手寫(xiě)代碼測(cè)試,是無(wú)法理解他們之間的差異的,很容易搞混,在使用時(shí)容易亂套

提示

凡是帶sync結(jié)尾的都是同步的,而凡是帶clear開(kāi)頭的都是一次性清除同步/異步的存儲(chǔ),而帶·remove開(kāi)頭的都是需要指定刪除某個(gè)存儲(chǔ)的key

解決相同 key 覆蓋問(wèn)題

在小程序中,當(dāng)出現(xiàn)同名key,后者key覆蓋前者是一個(gè)讓人頭疼的問(wèn)題

具體解決

可以將需要存儲(chǔ)數(shù)據(jù)存到一個(gè)數(shù)組當(dāng)中,當(dāng)需要使用時(shí),取最后一個(gè)即可

至于若有增刪操作,每次刪除完某一數(shù)據(jù)后,重新在設(shè)置一次本地存儲(chǔ)即可

let lists = wx.getStorageSync('lists'); // 先獲取lists本地存儲(chǔ)的數(shù)據(jù)
if (!lists) {
  // 第一次判斷緩存中有沒(méi)有l(wèi)ists數(shù)據(jù)
  lists = []; // 若沒(méi)有,則存儲(chǔ)設(shè)置一個(gè)空數(shù)組
}
lists.push(data); // 這里的data是要存儲(chǔ)到本地中的數(shù)據(jù)
wx.setStorageSync('lists', lists); // 設(shè)置本地存儲(chǔ)key:val

通過(guò)上面的操作,就解決了存儲(chǔ) key 值覆蓋的問(wèn)題,那么如何取最新的呢

const storageList = wx.getStorageSync('lists');
const listData = http://www.wxapp-union.com/storageList[storageList.length - 1]; // 獲取到最后一個(gè)
this.setData({
  // 重新setData數(shù)據(jù)即可
  lists: listData,
});

是使用同步存儲(chǔ)還是異步存儲(chǔ)

帶有Sync,這個(gè)表示的同步的操作,與之相對(duì)的不帶后綴就是異步”。

同步與異步是指的消息通訊機(jī)制。就是信息傳來(lái)傳去的時(shí)候是同步還異步。重點(diǎn)強(qiáng)調(diào)的是通訊這個(gè)動(dòng)作。

很容易混淆,在計(jì)算機(jī)里,他們兩是對(duì)立,相反的,同步代碼是順序執(zhí)行,會(huì)形成阻塞,而異步代碼不會(huì)阻塞,它是等待主線程執(zhí)行完后,可以在回過(guò)頭來(lái)執(zhí)行

比如要請(qǐng)求用戶信息的時(shí)候,需要從緩存中獲取username這個(gè)變量,那只有先獲取到這個(gè)變量才能進(jìn)行下一步。那就應(yīng)該使用同步,使用wx.getStorageSync。這樣能確保一定能獲取到這個(gè)變量,所有在第一次獲取緩存中的數(shù)據(jù)時(shí)

我們往往先要判斷一下緩存中是否有我們想要的那一數(shù)據(jù)的,否則若沒(méi)有,在代碼中使用了,就會(huì)報(bào)錯(cuò)

打電話就是一個(gè)同步的例子,必須先打完上一個(gè),然后才能在打下一個(gè),而發(fā)短信就是一個(gè)異步的例子,你可以跟 A 同學(xué)發(fā),發(fā)完后不用等待,也可以更 B 同學(xué)發(fā)

在相同的時(shí)間內(nèi),使用同步只能干一件事情,必須得一件,一件的干完,而異步則在同一段時(shí)間內(nèi),可以同時(shí)干多件事情

JavaScript 是單線程的,但是瀏覽器是多線程的.它的異步是借助事件實(shí)現(xiàn)的.具體可自行查看多線程與單線程相關(guān)知識(shí)的

使用eventChannel向被打開(kāi)頁(yè)面?zhèn)魉蛿?shù)據(jù)(wx.navigateTo高級(jí)用法)

對(duì)于頁(yè)面與頁(yè)面之間的數(shù)據(jù)通信,一種方式是,可以通過(guò)url攜帶參數(shù)的方式跳轉(zhuǎn)到指定的頁(yè)面,在跳轉(zhuǎn)的指定頁(yè)面中的onLoad生命周期函數(shù)中的options中可以拿到數(shù)據(jù)

但是這種傳遞數(shù)據(jù)的方式是有限的,不適合數(shù)據(jù)多的情況下

另一種方式是可以傳遞數(shù)據(jù)沒(méi)有限制,wx.navigateTo提供了一種更加高級(jí)的用法,通過(guò)eventChannel向被打開(kāi)頁(yè)面?zhèn)魉蛿?shù)據(jù)

父(當(dāng)前)頁(yè)面向子(目標(biāo))頁(yè)面?zhèn)鬟f數(shù)據(jù)

被打開(kāi)(上/父級(jí))頁(yè)面

Page({
  data: {
    parentPageData: {
      name: '川川',
      url: 'http://coder.itclan.cn',
      vx: 'itclanCoder',
    },
  },

  onEventChannel() {
    const parentPageData = http://www.wxapp-union.com/this.data.parentPageData; // 當(dāng)前頁(yè)面的數(shù)據(jù)
    wx.navigateTo({
      url: `/pages/listDetail/listDetail`, // 打開(kāi)的目標(biāo)頁(yè)面
      success: (res) => {
        // 通過(guò)eventChannel向被打開(kāi)頁(yè)面?zhèn)魉蛿?shù)據(jù),目標(biāo)頁(yè)面是listDetail,這個(gè)data名字是你自己取的任意,在目標(biāo)頁(yè)面中有個(gè)參數(shù)接收就可以
        res.eventChannel.emit('parentPageEmit', { data: parentPageData });
      },
    });
  },
});

被打開(kāi)(上/父級(jí))頁(yè)面的wxml,綁定事件

<view bindtap="onEventChannel">打開(kāi)跳轉(zhuǎn)到目標(biāo)頁(yè)面view>

打開(kāi)(目標(biāo))頁(yè)面

在目標(biāo)打開(kāi)頁(yè)面中通過(guò)getOpenerEventChange方法,用on進(jìn)行監(jiān)聽(tīng)被跳轉(zhuǎn)頁(yè)面的方法,就可以拿到被跳轉(zhuǎn)頁(yè)面中通過(guò)emit方法傳遞過(guò)來(lái)的數(shù)據(jù),其中使用on監(jiān)聽(tīng)的方法名與被跳轉(zhuǎn)頁(yè)面的名字保持一致就可以,這樣實(shí)現(xiàn)了兩個(gè)不同頁(yè)面之間的數(shù)據(jù)通信傳遞

Page({
  data: {
    acceptParentData: {},
  },

  onLoad: function(options) {
    // 通過(guò)getOpenerEventChannel對(duì)象,對(duì)`parentPageEmit`進(jìn)行監(jiān)聽(tīng)
    const eventChannel = this.getOpenerEventChannel();
    eventChannel.on('parentPageEmit', (data) => {
      console.log(data);
      this.setData({
        acceptParentData: data,
      });
    });
  },
});

說(shuō)明

將某整個(gè)父頁(yè)面的數(shù)據(jù)傳遞給跳轉(zhuǎn)到的子頁(yè)面,是一個(gè)比較常見(jiàn)的需求操作

比如在商品詳情頁(yè)面中,跳到到下單頁(yè)面,需要將詳情頁(yè)面的一些數(shù)據(jù)

傳遞給跳轉(zhuǎn)的子頁(yè)面,那么這個(gè)時(shí)候,用url的方式傳遞數(shù)據(jù)就不時(shí)很合適,選用eventChannel的方式就比價(jià)適合

wx.navigateTo的成功success回調(diào)中,通過(guò)emit進(jìn)行觸發(fā),emit接收兩個(gè)參數(shù),第一個(gè)是監(jiān)聽(tīng)事件的名稱,第二個(gè)參數(shù)是需要向目標(biāo)頁(yè)面?zhèn)鬟f的數(shù)據(jù)

res.eventChannel.emit(`監(jiān)聽(tīng)的事件名稱parentPageEmit`, { data: '數(shù)據(jù)' });

在跳轉(zhuǎn)的目標(biāo)頁(yè)面中,通過(guò)調(diào)用getOpenerEventChannel方法,然后進(jìn)行on的綁定

const eventChannel = this.getOpenerEventChannel();
eventChannel.on('監(jiān)聽(tīng)的事件名稱parentPageEmit', (data) => {
  console.log(data);
  this.setData({
    acceptParentData: data,
  });
});

當(dāng)前頁(yè)面-->目標(biāo)頁(yè)面是利用wx.navigateTo 中的 success 回調(diào)中使用 emit 觸發(fā),目標(biāo)跳轉(zhuǎn)頁(yè)面用 on 監(jiān)聽(tīng)

實(shí)現(xiàn)將當(dāng)前頁(yè)面的數(shù)據(jù)傳遞給目標(biāo)頁(yè)面中

那當(dāng)前頁(yè)面又如何獲取目標(biāo)頁(yè)面的數(shù)據(jù)呢


父(當(dāng)前)頁(yè)面如何獲取跳轉(zhuǎn)(子/目標(biāo))頁(yè)面中的數(shù)據(jù)

知道了當(dāng)前頁(yè)面向目標(biāo)跳轉(zhuǎn)頁(yè)面?zhèn)鬟f數(shù)據(jù),那么反過(guò)來(lái),當(dāng)前頁(yè)面又如何接收跳轉(zhuǎn)頁(yè)面?zhèn)鬟f過(guò)來(lái)的數(shù)據(jù)?

當(dāng)前頁(yè)面

Page({
  data: {
    parentPageData: {
      name: '川川',
      url: 'http://coder.itclan.cn',
      vx: 'itclanCoder',
    },
    subdetailData: {},
  },

  onEventChannel() {
    const parentPageData = http://www.wxapp-union.com/this.data.parentPageData; // 當(dāng)前頁(yè)面的數(shù)據(jù)
    wx.navigateTo({
      url: `/pages/listDetail/listDetail`, // 打開(kāi)的目標(biāo)頁(yè)面
      events: {
        // 頁(yè)面間通信接口,用于監(jiān)聽(tīng)被打開(kāi)頁(yè)面發(fā)送到當(dāng)前頁(yè)面的數(shù)據(jù)
        // 為指定事件添加一個(gè)監(jiān)聽(tīng)器,獲取被打開(kāi)頁(yè)面?zhèn)魉偷疆?dāng)前頁(yè)面的數(shù)據(jù)
        subPageEmit: (data) => {
          console.log(data);
          this.setData({
            subdetailData: data,
          });
        },
      },
    });
  },
});

wxml

<view class="subdetail-box">
  <block wx:for="{{subdetailData}}" wx:key="index">
    <view>姓名:{{item.name}}view>
    <view>站點(diǎn):{{item.url}}view>
    <view>微信:{{item.vx}}view>
  block>
view>

子頁(yè)面目標(biāo)頁(yè)面

Page({
  data: {
    subdetailData: {
      name: '輕記賬小程序-我是子頁(yè)面?zhèn)鬟f過(guò)來(lái)的數(shù)據(jù)',
      url: 'http://itclan.cn/',
      vx: 'itclanCoder',
    },
  },

  onLoad: function(options) {
    this.returnSubPagePrev();
  },

  returnSubPagePrev() {
    const subdetailData = http://www.wxapp-union.com/this.data.subdetailData;
    const eventChannel = this.getOpenerEventChannel();
    // 通過(guò)emit的方式進(jìn)行觸發(fā),將子頁(yè)面/目標(biāo)頁(yè)面中的數(shù)據(jù)傳遞給當(dāng)前頁(yè)面
    eventChannel.emit('subPageEmit', { data: subdetailData });
  },
});

說(shuō)明

在當(dāng)前頁(yè)面中獲取子頁(yè)面的數(shù)據(jù),是借助wx.navigateTo中提供的event這個(gè)參數(shù)接口,它可以用于監(jiān)聽(tīng)被打開(kāi)頁(yè)面發(fā)送到當(dāng)前頁(yè)面的數(shù)據(jù)

換言之,也就是當(dāng)前頁(yè)面可以獲取監(jiān)聽(tīng)到子頁(yè)面?zhèn)鬟f過(guò)來(lái)的數(shù)據(jù),在子頁(yè)面中通過(guò)emit的方式進(jìn)行觸發(fā),同樣,emit方法接收兩個(gè)參數(shù)

第一個(gè)是監(jiān)聽(tīng)的事件名稱,第二個(gè)參數(shù)對(duì)象是具體要傳遞的數(shù)據(jù)

結(jié)語(yǔ)

本文主要介紹 4 種在小程序當(dāng)中頁(yè)面與頁(yè)面之間的傳遞數(shù)據(jù)常見(jiàn)方法,其中如何返回上一級(jí)頁(yè)面,這些都是實(shí)際開(kāi)發(fā)中經(jīng)常會(huì)遇到的問(wèn)題

每一種方法都有與之對(duì)應(yīng)的應(yīng)用場(chǎng)景,url 方式比較適合跳轉(zhuǎn),攜帶少量的數(shù)據(jù),當(dāng)多個(gè)頁(yè)面需要共享同一個(gè)數(shù)據(jù)對(duì)象時(shí),可以使用全局globalData對(duì)象,也可以使用本地緩存數(shù)據(jù)

以及最后一種使用 eventChannel 向被打開(kāi)頁(yè)面?zhèn)魉蛿?shù)據(jù)(wx.navigateTo高級(jí)用法)

它適合一種傳遞復(fù)雜的數(shù)據(jù).

關(guān)于頁(yè)面之間數(shù)據(jù)傳遞就介紹這么多,如果您有問(wèn)題,歡迎補(bǔ)充,給我留言,一起學(xué)習(xí)成長(zhǎng)

相關(guān)案例查看更多