乾貨分享:小程序項目實踐和經驗總結

最近接觸小程序開發,我特將本次開發過程當中所使用到的相關知識點進行了總結,以做爲經驗的積累。但願給本身之後的開發,提供一些幫忙,同時提升解決問題的能力。若有錯誤,請你們指正。css

github地址項目地址html

weui:使用微信原生視覺體驗樣式庫

認識: WeUI 是一套同微信原生視覺體驗一致的基礎樣式庫,由微信官方設計團隊爲微信內網頁和微信小程序量身設計,令用戶的使用感知更加統一。前端

官網: weui.io/vue

github地址: github.com/weui/weui-w…node

微信推出了一套官方樣式庫,方便你們開發,對於一些相似的UI界面咱們須要引入便可,無需重複造輪子。咱們只需導入weui.wxss等便可減小大量的css佈局工做.ios

關於本地圖片資源路徑(background)

小程序只有image標籤支持本地圖片資源路徑,wxss裏的background-image不支持。 若是想在css中使用背景圖,解決方法:git

一、將本地圖片用線上地址轉化成base64路徑。線上轉化base64的地址:imgbase64.duoshitong.com/github

二、url裏面的圖片來源必須填寫外鏈。以下:web

area{
   background: url('https://mirror-gold-cdn.xitu.io/168e088859e325b9d85?imageView2/1/w/100/h/100/q/85/format/webp/interlace/1' ) no-repeat center;
}
複製代碼

websocket問題

體驗版支持ws協議,須要打開調試模式 若是websocket是鏈接的域名非IP地址,則不能經過鏈接代理更改電腦的host來指定socket域名的解析地址 若是有測試環境,建議:數據庫

  1. 建一個專有的測試環境websocket域名
  2. 直接使用測試環境的IP地址訪問websocket

關於時間格式在ios中處理方法

背景: 因爲ios只識別格式yyy/mm/dd格式,如"2018-10-31 20:30:00"格式沒法識別; 默認狀況下數據庫拿到的日期格式爲「2018-08-30 12:00:00」,若是不替換「-」的話,在IOS下是不能經過getDate(datestring)獲取到日期對象的。Android下兩種格式均表現正常。

解決方法: 經過正則替換掉全部的"-",以下:

var dateStr = "2018-09-08 12:30:30"; // 後臺返回的時間字符串
dateStr = dateStr.replace(/-/g, '/');
console.log(dateStr); 
結果爲:2018/09/08 12:30:30
複製代碼

小程序DOM上附屬參數,函數中獲取參數方法

view.wxml:

// DOM上附屬參數
<view 
  data-id='{{fangyuanItem.id}}' 
  data-houseitemid='{{fangyuanItem.houseItemId}}' 
  catchtap='viewMendianDetail'>
</view>
複製代碼

view.js:

// 函數中獲取參數
  page({
      data:{},
      viewMendianDetail: function (e) {
        var roomtypeid = e.currentTarget.dataset.id;
        var houseItemId = e.currentTarget.dataset.houseitemid;
      }
  })
複製代碼

注意: 附屬參數時,data-key,key格式爲小寫;

小程序 navigator 沒法跳轉 tabBar上的頁面

方法一:navigator 的 open-type 設置爲 switchTab

代碼以下:

<navigator url="../cart/index" open-type="switchTab">
   <text>首頁</text>
</navigator>
複製代碼

方法二:wx.switchTab({})

代碼以下:

index.wxml:

<text catchtap="toIndex">首頁</text>
複製代碼

index.js:

page({
    toIndex(){
        wx.switchTab({  
          url: '../cart/index'
        }) 
    }
 })
複製代碼

wx.navigateTo和wx.switchTab導航傳參

wx.navigateTo導航傳參

1.wx.navigateTo,url經過參數拼接傳參;

// 訪問房型詳情
viewMendianDetail: function (e) {
  var roomtypeid = e.currentTarget.dataset.id;
  var houseItemId = e.currentTarget.dataset.houseitemid;
  wx.navigateTo({
    url: '/pages/index/index?houseItemId=' + houseItemId + '&roomtypeid=' + roomtypeid,
  })
}
複製代碼

2.定位到的組件中經過生命週期函數onLoad接收參數對象,並設置本組件中的數據

pages/index/index:

onLoad: function (options) {
    //console.log(options)
    var houseItemId = options.houseItemId
    var roomtypeid = options.roomtypeid
    this.setData({
        houseItemId: houseItemId,
        roomTypeId: roomtypeid
    })
}
複製代碼

wx.switchTab導航傳參

1.前提:app.js中有定義全局變量searchInfo,以下:

App({
    globalData: {
        searchInfo:{
          searchInput:"",
          laiyuan:0
        }
  }
});
複製代碼

2.經過app.globalData定義全局參數,以下:

a.wxml:

const app = getApp()
page({
    data:{},
    toZhaofang:function(e){
        app.globalData.searchInfo = {
          "searchInput": searchInput,
          "laiyuan": 1
        }
        wx.switchTab({
          url: '/pages/tabbar/zhaofang/index',
        })
   }
})
複製代碼

3.經過app.globalData來接收全局參數,以下: zhaofang/index.wxml:

const app = getApp()
 page({
    onLoad(){ 
       let searchInfo = app.globalData.searchInfo
       let searchInput = searchInfo.searchInput;
    }
 })
複製代碼

數據緩存:wx.setStorage,wx.setStorageSync等介紹和區別

wx.setStorage,wx.setStorageSync區別:

1.wx.setStorageSync爲同步請求方法,會阻塞後續方法的執行;wx.setStorage爲異步請求方法,不會阻塞當前任務,有sucess,fail,complete回調函數,適用於須要拿到緩存數據以後的後續操做。

2.適應場景不一樣:wx.setStorageSync爲同步操做,如:拿到用戶token以後,去獲取用戶信息;wx.setStorage異步操做,如:頁面剛加載進來,就去拿到用戶緩存數據,在其餘事件中去使用緩存數據。

代碼以下:

wx.setStorageSync(同步):

page({
   data:{},
   // 頁面初始化渲染過程當中,拿到用戶token並立馬根據token獲取用戶信息;
   onLoad: function () {
       try {
          var token = wx.getStorageSync("token");
          if (token) {
            this.getUserInfoByToken(token);
          }
        } catch (e) {
          // Do something when catch error
        }
   },
   getUserInfoByToken(token){}
})
複製代碼

wx.setStorage(異步):

page({
   data:{
      userInfo:"",
   },
   // 頁面初始化渲染過程當中,拿到用戶信息
   onLoad: function () {
       var that = this;
       wx.setStorage({
             key: "userInfo",
            success: function (res) {
              that.data.userInfo = res.data;
            },
            fail:function(res){ 
               console.log(res);
            },
            complete:function(res){
              console.log(res);
            }
        })
   },
   // 其餘函數中,能夠拿到用戶信息進行使用
   getUserInfoByUserId(){
       var data = {
           userId:that.data.userInfo.userId
       }
   }
})
複製代碼

wx.getStorage()和wx.getStorageSync()介紹:

  1. wx.getStorage(Object object):從本地緩存中異步獲取指定 key 的內容

示例代碼:

wx.getStorage({
  key: 'key',
  success (res) {
    console.log(res.data)
  }
})
複製代碼
  1. wx.getStorageSync(string key):wx.getStorage 的同步版本

示例代碼:

try {
  var value = wx.getStorageSync('key')
  if (value) {
    // Do something with return value
  }
} catch (e) {
  // Do something when catch error
}
複製代碼

wx.getStorageInfo()和wx.getStorageInfoSync()介紹:

  1. wx.getStorageInfo(Object object):異步獲取當前storage的相關信息

示例代碼:

wx.getStorageInfo({
  success (res) {
    console.log(res.keys)
    console.log(res.currentSize)
    console.log(res.limitSize)
  }
})
複製代碼
  1. wx.getStorageInfoSync():wx.getStorageInfo 的同步版本

示例代碼:

try {
  const res = wx.getStorageInfoSync()
  console.log(res.keys)
  console.log(res.currentSize)
  console.log(res.limitSize)
} catch (e) {
  // Do something when catch error
}
複製代碼

wx.clearStorage()和wx.clearStorageSync()介紹:

  1. wx.clearStorage(Object object):清理本地數據緩存

示例代碼:

wx.clearStorage()
複製代碼
  1. wx.clearStorageSync():wx.clearStorage 的同步版本

示例代碼:

try {
  wx.clearStorageSync()
} catch(e) {
  // Do something when catch error
}
複製代碼

wx.removeStorage()和wx.removeStorageSync()介紹:

  1. wx.removeStorage(Object object):從本地緩存中移除指定 key

代碼以下:

wx.removeStorage({
  key: 'key',
  success (res) {
    console.log(res)
  }
})
複製代碼
  1. wx.removeStorageSync(string key):wx.removeStorage 的同步版本

代碼以下:

try {
  wx.removeStorageSync('key')
} catch (e) {
  // Do something when catch error
}
複製代碼

自定義小程序轉發功能

默認狀況下,咱們須要點擊小程序右上角的...才能看到轉發,這樣並不能對用戶起到引導做用,一般的作法是使用一個button,而且設置open-type爲share,這樣就能夠經過按鈕啓動分享。 可是原生按鈕很難看,咱們能夠設置一個圖片,而且調整按鈕的樣式;

效果如圖:

share.wxml:

<button open-type="share"><image src="/images/icon-share.png"></image></button>
複製代碼

share.wxss:

button {
    padding:0;
    width:70rpx;
    height:70rpx;
    display:block;
    border:0;
    background: transparent;
}
button::after {
    border:0; 
}
複製代碼

注意: 尤爲是對 button::after 要進行設置,不然按鈕的邊框是沒法去掉的。

經過 wx.getSystemInfo()來獲取手機信息(包括寬,高)

小程序提供的getSystemInfo()方法,該方法能夠獲取到設備的經常使用信息,如手機型號.設備像素比.屏幕寬高等等.最經常使用的就是屏幕寬高了. 爲了保證獲取信息的準確性,wx.getSystemInfoSync是在頁面初始化的時候就計算了。因此最好的方法是使用異步接口,而且在onReady函數中調用。

info.js:

Page({
  onReady: function (options) {
    this.getSystemInfo();
  },
  getSystemInfo:function(){
    wx.getSystemInfo({
      success: function (res) {
         console.log("手機屏幕的寬度爲:" + res.screenWidth);
         console.log("手機屏幕的高度爲:" + res.screenHeight);
        console.log("可視網頁的寬度爲:" + res.windowWidth);
        console.log("可視網頁的高度爲:" + res.windowHeight);
        console.log("手機的系統爲:" + res.system);
        console.log("微信版本號爲:" + res.version);
      }
    })
  }
})
複製代碼

結果如圖:

模板(template)定義與傳參

定義: WXML提供模板(template),能夠在模板中定義代碼片斷,而後在不一樣的地方調用。 使用 name 屬性,做爲模板的名字。如:

1.定義模板文件 baseTemplate.wxml:

<template name="msgItem">
  <view>
    <text> {{index}}: {{msg}} </text>
    <text> Time: {{time}} </text>
  </view>
</template>
複製代碼

2.使用模板並經過data傳遞參數 使用 is 屬性,聲明須要的使用的模板,而後將模板所須要的 data 傳入。以下: user.wxml:

<import src="../template/baseTemplate.wxml" />
 <block wx:for="{{goodlist}}" wx:key="idx">
    <template is="msgItem" data="{{...item}}"></template>
</block>
複製代碼

注意:

1.經過data="{{...item}}"的方式傳遞參數時,被調用的模板中,不須要再寫item;

2.若是要傳多個數據到模板,用逗號分開,item 是對象,index是單個數據,要用鍵值對.

<view class="tab-list" wx:for="{{list}}" wx:key="index">
   <template is="day-tab" data="{{item,index:index,target:target}}" wx:key="index"></template>
</view>
複製代碼

user.js,數據定義格式以下:

page({
   data:{
       goodlist:[
           { index: 0,msg: 'this is a template',time: '2016-06-18'},
           { index: 1,msg: 'this is a template1',time: '2017-06-18'},
           { index: 2,msg: 'this is a template2',time: '2018-06-18'}
       ]
   }
})
複製代碼

城市選擇組件picker使用

效果如圖:

組件介紹

picker:從底部彈起的滾動選擇器。

代碼以下:

picker.wxml:

<picker  
    mode='selector' 
    range="{{region}}" 
    range-key="{{'cityName'}}" 
    value='{{indexCity}}'
    bindchange="chooseCity" 
    >
    <view class="picker">  
        {{region[indexCity].cityName}}
    </view>  
</picker>
複製代碼

picker.js:

page({
   data:{
       region:[
           {"cityName":"北京市","cityId":"12345"},
           {"cityName":"上海市","cityId":"67890"},
           {"cityName":"武漢市","cityId":"54321"},
       ]
   },
   chooseCity(e){
     var value = e.detail.value;  // index下標
   }
})
複製代碼

屬性介紹

mode(string):選擇器類型;mode 的合法值:

  • selector:普通選擇器;
  • multiSelector:多列選擇器;
  • time:時間選擇器;
  • date:日期選擇器;
  • region:省市區選擇器

滑動組件scroll-view

介紹: scroll-view:可滾動視圖區域。使用豎向滾動時,須要給scroll-view一個固定高度,經過 WXSS 設置 height。組件屬性的長度單位默認爲px,2.4.0起支持傳入單位(rpx/px)。

詳細文檔請參考

效果如圖:

使用方法以下:

<scroll-view scroll-x="true"></scroll-view>
複製代碼

注意:

1.scroll-view的scroll-x失效的解決辦法

給scroll-view加上white-space: nowrap; 給scroll-view的子元素box加上display:inline-block便可。

代碼以下:

.scroll-box {
   white-space: nowrap;
}
.scroll-box .box{
   display:inline-block
}
複製代碼

2.文本數據默認顯示2行,超出部分用"..."代替:

樣式代碼以下:

line-height: 40rpx;
white-space:pre-line;
display:-webkit-box;
-webkit-box-orient:vertical;
-webkit-line-clamp:2;
overflow:hidden;
複製代碼

視圖容器cover-image和cover-view

使用背景:

在微信小程序常常會用到一些原生組件,好比map、video、canvas、camera,這些原生組件想讓其餘元素覆蓋在其上,必須使用cover-view或者cover-image組件。

cover-view

介紹: 覆蓋在原生組件之上的文本視圖。可覆蓋的原生組件包括 map、video、canvas、camera、live-player、live-pusher。只支持嵌套 cover-view、cover-image,可在 cover-view 中使用 button。組件屬性的長度單位默認爲px,2.4.0起支持傳入單位(rpx/px)。

注意: 只支持基本的定位、佈局、文本樣式。不支持設置單邊的border、background-image、shadow、overflow: visible等。

一、支持background-color,不支持background-image,若是你發現你的素材在真機出不來,並且你又設置了背景圖片的話,那你能夠把這些元素所有替換成cover-image。

二、不支持overflow: visible也是有點坑,這樣的話,你想超出依然顯示,就須要設置一個同級元素並提高層級才能達到效果了。

效果如圖:

示例代碼以下:

video.wxml:

<video id="myVideo" src="http://wxsnsdy.tc.qq.com/105/20210/snsdyvideodownload?filekey=30280201010421301f0201690402534804102ca905ce620b1241b726bc41dcff44e00204012882540400&bizid=1023&hy=SH&fileparam=302c020101042530230204136ffd93020457e3c4ff02024ef202031e8d7f02030f42400204045a320a0201000400" controls="{{false}}" event-model="bubble">
  <cover-view class="controls">
    <cover-view class="play" bindtap="play">
      <cover-image class="img" src="/path/to/icon_play" />
    </cover-view>
    <cover-view class="pause" bindtap="pause">
      <cover-image class="img" src="/path/to/icon_pause" />
    </cover-view>
    <cover-view class="time">00:00</cover-view>
  </cover-view>
</video>
複製代碼

video.wxss:

.controls {
  position: relative;
  top: 50%;
  height: 50px;
  margin-top: -25px;
  display: flex;
}
.play,.pause,.time {
  flex: 1;
  height: 100%;
}
.time {
  text-align: center;
  background-color: rgba(0, 0, 0, .5);
  color: white;
  line-height: 50px;
}
.img {
  width: 40px;
  height: 40px;
  margin: 5px auto;
}
複製代碼

video.js

Page({
  onReady() {
    this.videoCtx = wx.createVideoContext('myVideo')
  },
  play() {
    this.videoCtx.play()
  },
  pause() {
    this.videoCtx.pause()
  }
})
複製代碼

cover-image

介紹: 覆蓋在原生組件之上的圖片視圖,可覆蓋的原生組件同cover-view,只支持嵌套在cover-view裏。

cover-image發現了兩個問題:

一、雖然說和image組件基本同樣,可是設置mode屬性也就是圖片裁剪、縮放的模式無效

二、寬度固定,高度auto,時,按照正常效果應該是圖片按比例伸縮展現,可是發現該組件高度一直爲0,只能根據應用場景尋找其餘替代方案了。

視圖容器swiper

介紹: 滑塊視圖容器。其中只可放置swiper-item組件,不然會致使未定義的行爲。

效果如圖:

代碼以下:

swiper.wxml:

<view class="area">
   <view class="fuTitle">swiper</view>
   <view class="intro"> 
      <text class="one-title">介紹:</text>
      <text>滑塊視圖容器。其中只可放置swiper-item組件,不然會致使未定義的行爲。</text>
   </view>
   <view class="item">
      <swiper 
        indicator-dots="{{indicatorDots}}"
        indicator-color="{{indicatorColor}}"
        indicator-active-color="{{indicatorActiveColor}}"
        previous-margin="{{previousMargin}}"
        next-margin="{{nextMargin}}"
        display-multiple-items="{{itemsNum}}"
        autoplay="{{autoplay}}" 
        interval="{{interval}}" 
        duration="{{duration}}"
        bindchange="bindchange"
        easing-function="{{easing}}"
        >
        <block wx:for="{{imgUrls}}" wx:key="{{index}}">
          <swiper-item item-id="{{index}}">
            <image src="{{item}}" class="slide-image" width="355" height="150"/>
          </swiper-item>
        </block>
      </swiper>
   </view>
</view>
複製代碼

swiper.js

Page({
    data: {
         imgUrls:[
           "../../images/bo1.jpg",
           "../../images/bo2.jpg",
           "../../images/bo3.jpg",
           "../../images/bo4.jpg"
         ],
         indicatorDots: true,    // 是否顯示滾動圓點圖標
        indicatorColor: "#07c160", // 指示點顏色
        indicatorActiveColor: "#28d3ee", // 當前選中的指示點顏色
        previousMargin: "10rpx", // 前邊距,可用於露出前一項的一小部分,接受 px 和 rpx 值
        nextMargin: "10rpx",     // 後邊距,可用於露出後一項的一小部分,接受 px 和 rpx 值
        itemsNum:1,              // 同時顯示的滑塊數量
        easing: "default",       // 指定 swiper 切換緩動動畫類型
        autoplay: true,         // 是否自動播放
        interval: 5000,         // 自動切換時間間隔
        duration: 1000          // 滑動的動畫時長
    }
})
複製代碼

rich-text實現富文本解析

介紹: 富文本。主要用來解析服務端傳遞過來的富文本html格式的數據,進行展現在頁面上。相似於vue的v-html指令;

效果如圖:

代碼以下:

richText.wxml:

<view class="rich-area">
      <rich-text nodes="{{article_content}}" bindtap="tapRichText"></rich-text>
</view>
複製代碼

richText.js:

Page({
   data: {
     article_content: '<p>自我介紹1</p><p><img src="https://mirror-gold-cdn.xitu.io/168e088859e325b9d85?imageView2/1/w/100/h/100/q/85/format/webp/interlace/1" width="100" height="100"/></p><p>自我介紹2</p><p><img src="https://mirror-gold-cdn.xitu.io/168e088859e325b9d85?imageView2/1/w/100/h/100/q/85/format/webp/interlace/1" width="100" height="100"/></p><p>自我介紹3</p><p><img src="https://mirror-gold-cdn.xitu.io/168e088859e325b9d85?imageView2/1/w/100/h/100/q/85/format/webp/interlace/1" width="100" height="100"/></p>',
   }
});
複製代碼

小程序中運用高德地圖繪製靜態圖

功能背景

在小程序的頁面中,須要顯示某個位置的具體地理座標並作好標記;若是直接使用map組件,沒法知足功能需求,同時會存在頁面層級重疊的問題;全部就選擇了高德地圖微信小程序sdk,繪製靜態圖來呈現。

效果如圖:

開發步驟

1.獲取高德Key

點我獲取Key>> 點我查看申請高德Key的方法>>

2.繪製靜態圖

簡介: 因爲微信內沒法運行第三方地圖,高德對廣大開發者提供了靜態地圖功能,可快速生成一張地圖圖片,能夠指定顯示的地圖區域、圖片大小、以及在地圖上添加覆蓋物,如標籤、標註、折線、多邊形。 可用於快速生成一張個性化塗鴉的靜態地圖用於查看和分享。

靜態圖上繪製點

一、在頁面的 js 文件中,實例化 AMapWX 對象,請求顯示靜態地圖。

首先,引入 amap-wx.js 文件(amap-wx.js 從相關下載頁面下載的 zip 文件解壓後獲得)。

xinxi.js:

var amapFile = require('path/to/amap-wx.js');//如:..­/..­/libs/amap-wx.js
複製代碼

而後,構造 AMapWX 對象,並調用 getStaticmap 方法。 其中,注意: 把百度地圖座標轉換成高德,騰訊地圖座標

var zuobiaoArr = network.bMapTransQQMap(lng,lat)
複製代碼
Page({
  data: {
    pointObj:{
      lng:'您的座標經度值',
      lat:'您的座標緯度值'
    },
    src: ''
  },
  onLoad: function() {
    var that = this;
    var myAmapFun = new amapFile.AMapWX({key:"您的Key"});
    wx.getSystemInfo({
      success: function(data){
        var height = data.windowHeight;
        var width = data.windowWidth;
        var size = width + "*" + height;
        myAmapFun.getStaticmap({
          zoom: 8,
          size: size,
          scale: 2,
          markers: "mid,0xFF0000,A:"+pointObj.lng+","+pointObj.lat", success: function(data){ that.setData({ src: data.url }) }, fail: function(info){ wx.showModal({title:info.errMsg}) } }) } }) } }) 複製代碼

注意: data.windowHeight,data.windowWidth獲取的是整個窗口的高度和寬度,這裏能夠根據需求本身設定地圖要顯示的寬高。 markers: "mid,0xFF0000,A:"+pointObj.lng+";"+pointObj.lat",用於設置地圖上要顯示的標記座標;若是要顯示多個標記,格式爲:

markers: "mid,0xFF0000,A:116.37359,39.92437;116.47359,39.92437"; // 多個座標點以";"分割;
複製代碼

二、編寫頁面的 wxml 文件,搭建頁面結構。

xinxi.wxml:

<view class="img_box">
  <img src="{{src}}">
</view>
複製代碼

三、編寫頁面的 wxss 文件,設置頁面樣式。

xinxi.wxss:

.img_box{
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}
.img_box image{
  width: 100%;
  height: 100%;
}
……
複製代碼

4.注意細節:

若是你提供的 pointObj:{lng:'您的座標經度值',lat:'您的座標緯度值'}數據對象爲百度地圖的座標值,咱們須要將其轉換爲高德地圖座標值(它們的座標計算方式不一樣);

轉換方法以下:

//百度地圖座標轉爲高德,騰訊地圖座標
function bMapTransQQMap(lng, lat) {
    let x_pi = 3.14159265358979324 * 3000.0 / 180.0;
    let x = lng - 0.0065;
    let y = lat - 0.006;
    let z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
    let theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
    let lngs = z * Math.cos(theta);
    let lats = z * Math.sin(theta);
    return {
        lng: lngs,
        lat: lats
    }
}
let pointObj = bMapTransQQMap(lng,lat); // 轉換以後的座標值;
複製代碼

結束:

若是你也同樣喜歡前端開發,歡迎加入咱們的討論/學習羣,羣內能夠提問答疑,分享學習資料;

歡迎添加羣主微信和qq羣答疑:

相關文章
相關標籤/搜索