微信小程式

蓝幻ﹺ發表於2024-06-13

微信小程式賬號註冊

  • 訪問【微信公眾平臺】,註冊一個微信小程式賬號

https://mp.weixin.qq.com/

  • 申請賬號需要準備一個郵箱,該郵箱要求:

    • 未被微信公眾平臺註冊
    • 未被微信開放平臺註冊
    • 未被個人微訊號繫結過
    • 如果被繫結了需要解綁 或 使用其他郵箱
  • 獲取 小程式id

AppID(小程式ID)	     wxd63f21a664e8009b
AppSecret(小程式金鑰)   513e6cd6ea1a2692c9727004af729f1c

建立專案

  • 下載【微信開發工具】--需要聯網才能使用

https://developers.weixin.qq.com/miniprogram/dev/devtools/stable.html

  • 本地開發支援http

小程式預設只支援https,我們需要做如下配置,讓其支援http,方便我們本地開發

image-20240523145341780

專案目錄結構

介紹

# 1 專案主配置檔案
	專案主配置檔案必須放到專案的根目錄下,控制整個專案
    	- app.js:  小程式入口檔案
    	- app.json:小程式的全域性配置檔案
    	- app.wxss:小程式的全域性樣式
    	-app.js 和 app.json 檔案是必須的,不能沒有
        
# 2 頁面檔案
	小程式有一個個頁面,每個頁面所需的檔案,都存放在 pages 目錄下,一個頁面一個資料夾
        -xx.js:  頁面邏輯  js程式碼存放位置
        -xx.wxml:頁面結構  類html檔案存放位置
        -xx.wxss:頁面樣式  css存放位置
        -xx.json:小頁面配置 
        -xx.js 檔案和 xx.wxml 檔案是必須的,不能沒有

        
# 3 相關配置文件
https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/app.html

結構

├── components                  【頁面中使用的元件】
├── pages   					【頁面檔案目錄】
│   ├── index					【頁面】
│   │   ├── index.js				【頁面JS】
│   │   ├── index.json				【頁面配置】
│   │   ├── index.wxml				【頁面HTML】
│   │   └── index.wxss				【頁面CSS】
│   └── logs					【頁面】
│       ├── logs.js					...
│       ├── logs.json				...
│       ├── logs.wxml				...
│       └── logs.wxss				...
├── utils						【自定義工具】
│	└── utils.js					【功能的定義】
├── app.js						【全域性JS】
├── app.json					【全域性配置】
├── app.wxss					【全域性CSS】
├── project.config.json			【開發者工具預設配置】
├── project.private.config.json	【開發者工具使用者配置,在這裡修改,優先用這個,可以刪除】
├── .eslintrc.js				【ESlint語法檢查配置】
├── sitemap.json				【微信收錄頁面,用於搜尋,上線後,搜尋關鍵字就可以搜到我們】

常用元件

# 參考地址:
https://developers.weixin.qq.com/miniprogram/dev/component/

text,類似於span

<text>Justin</text>

view,類似於div

<view>
    <view>Python山頂會</view>
    <view>Justin</view>
    <view>微信:616564099</view>
</view>

image,類似於img標籤

<image src="/images/1.png" style="width: 750rpx;height: 400rpx;"></image>

icon

<icon type="success" size='198rpx' color="red"/>
<icon type="download" size='198rpx' color="#ddd"/>
success, success_no_circle, info, warn, waiting, cancel, download, search, clear

跳轉,類似於a標籤

<navigator class="menu" url="/pages/login/login">
    <label class="fa fa-superpowers" style="color:#32CD32"></label>
  <view>登入</view>
</navigator>

繫結事件,在js中跳轉:

<view bindtap="clickMe" data-nid="123" >點我跳轉</view>
Page({

  clickMe:function(e){
    var nid = e.currentTarget.dataset.nid;
    console.log(nid);
    wx.navigateTo({
      url: '/pages/login/login'
    })
  }
})

跳轉到其他頁面之後,可以在onLoad中獲取引數

wx.navigateTo({
	url: '/pages/login/login?name=justin'
})
Page({
  onLoad: function (options) {
    console.log(options);
  }
})

尺寸單位 和樣式

  • rpx 可以根據不同的手機螢幕進行自動調整,自適應縮放
  • 無論什麼手機--》螢幕寬度都是 750rpx
  • 區域性樣式: xxx.wxss
  • 全域性樣式: app.wxss

tabbar配置

"tabBar": {
    "selectedColor": "#b4282d",
    # 放置位置只有兩個,top:頂部;bottom:底部
    "position": "bottom", 
    # list是陣列,裡面的tabbar至少2個至多5個
    "list": [
        {
            # 頁面的路徑
            "pagePath": "pages/index/index", 
             # 文字的內容
            "text": "首頁",
            # 預設圖示路徑
            "iconPath": "images/home.png", 
            #選中的圖示路徑
            "selectedIconPath": "images/home_select.png"
        },
        ...
    ]
},

實現輪播圖 swiper+swiper-item

<swiper 
autoplay 
interval="2000" 
indicator-dots 
indicator-color="#00FF00"
indicator-active-color="#70DB93"
circular
>
  <swiper-item>
    <image src="/images/banner1.jpg" mode="widthFix"/>
  </swiper-item>
  <swiper-item>
    <image src="/images/banner2.png" mode="widthFix"/>
  </swiper-item>
  <swiper-item>
    <image src="/images/banner3.jpg" mode="widthFix"/>
  </swiper-item>
</swiper>

引入向量圖示庫

https://www.iconfont.cn/

# 1 搜尋想要的圖示
	-加入購物車
    -在購物車中新增至專案
    
# 2 我的專案--專案設定--》開啟base64

# 3 選擇font class --》生成程式碼--》點選連結地址開啟

# 4 把開啟的連結地址內容複製到專案中
	-static/css/iconfont.wxss
    
# 5 在app.wxss中引入
@import "/static/css/iconfont.wxss";
   
# 6 在想用圖示的位置,加入text元件
<text class="iconfont icon-anquan">

事件繫結

  • bind:tab bindtab
# 1 方式一
<view bind:tab="showLog"></view>
# 2 方式二
<view bindtab="showLog"></view>

# 3 js中寫方法
  showLog(){
    console.log("我被點了")
  }

阻止事件冒泡

catch:tap

<view style="height:300rpx;display: flex;justify-content: center;align-items: center; background-color: orange;" bind:tap="handleView">
<button type="primary" plain catch:tap="handleButton">阻止事件冒泡</button>
</view>
  handleView() {
    console.log("view被點了")
  },
  handleButton() {
    console.log("button被點了")
  },

事件物件和傳參

data-*方案
mark:自定義屬性
target :事件觸發者                   :dataset  data定義的屬性
currentTarget:事件繫結者             :dataset  data定義的屬性

頁面跳轉

  • 使用 navigator 元件實現跳轉

open-type :跳轉方式

navigate:保留當前頁面,跳轉到應用內的某個頁面。但是不能跳到 tabbar 頁面redirect: 關閉當前頁面,跳轉到應用內的某個頁面。但不能跳轉到 tabbar 頁面
switchTab:跳轉到 tabBar 頁面,並關閉其他所有非 tabBar 頁面
reLaunch:關閉所有頁面,開啟到應用內的某個頁面
navigateBack:關閉當前頁面,返回上一頁面或多級頁面

wxml語法

#  1 在頁面 xx.js 的 Page() 方法的 data 物件中進行宣告定義
#  2 在xx.wxml 中使用 {{}} 包裹,顯示資料
#  3 可以顯示如下,不能編寫js語句或js方法
	-變數
	-算數運算
	-三元運算
	-邏輯判斷
    
# 4 只是單純透過賦值,js中變數會變化,但是wxml中的頁面不會變化,沒有聯動效果,需要使用setData()方法修改

setData案例 修改物件

data: {
        name: 'justin',
        age: 19,
        userinfo: {
          name: 'qcc',
          age: 99
        }
      },

  handleChangeName() {
    // 增加資料
    this.setData({
      'userinfo.hobby': '籃球'
    })
    // 修改資料
    this.setData({
      'userinfo.name': '彭于晏'
    })

    // 修改多個資料--》簡便方案--》展開運算子
      
    // const userinfo = {
    //   ...this.data.userinfo,
    //   name: '新名字',
    //   hobby: '乒乓球'
    // }
    // this.setData({
    //   // userinfo:userinfo
    //   userinfo //簡寫形式
    // })
    // 修改多個資料--》簡便方案-->assign
    const userinfo = Object.assign(this.data.userinfo, {
      name: 'xxzz',
      hobby: 'aa'
    })
    this.setData({
      // userinfo:userinfo
      userinfo //簡寫形式
    })

    //刪除資料-->單個
    delete this.data.userinfo.name // 頁面刪除不了,需要用setData更新
    this.setData({
      userinfo:this.data.userinfo
    })

    //刪除資料-->多個--解構賦值
    const {name,age,...res}=this.data.userinfo
    this.setData({
      userinfo:res
    })

  },

setData 修改陣列

data: {
    names:['劉亦菲','迪麗熱巴','古力娜扎','馬爾扎哈']
  },
    
   handleChangeList(){
    //1 增加再設定值
    this.data.names.push('xxx')
    this.setData({
      names:this.data.names
    })

    // 1.2 透過陣列拼接
    const newList=this.data.names.concat("aaa")
    	this.setData({
    	names:newList
    })

    // 1.3 透過解構賦值
    const newList=[...this.data.names,"李白"]
    this.setData({
      names:newList
    })

    // 2 修改陣列
    this.setData({
      'names[1]':'justin'
    })

    // 3 刪除陣列
    this.data.names.slice(1)
    this.setData({
      names:this.data.names.slice(1)
    })
  },

雙向資料繫結:input checkbox

  <input type="text" model:value='{{name}}'/>
  <checkbox model:checked="{{isCheck}}"/>

列表渲染

  • 預設每個物件是item,預設每個下標是index
  • wx:key 提升效能,不寫會警告 可以用 index或 *this:代指item本身 要唯一
<view wx:for="{{List}}" wx:key="*this">
{{item}}</text> -->
</view>

修改wx:for-index wx:for-item

  <view wx:for="{{List}}" wx:key="*this" wx:for-item="info">
<text>{{info}}</text>
</view>

條件渲染 wx:if wx:elif wx:else

<view>
  <input type="text" model:value='{{score}}' style="border:orange solid 1rpx"/>
  <view wx:if="{{score>=90&&score<=100}}">優秀</view>
  <view wx:elif="{{score>=80&&score<90}}">良好</view>
  <view wx:elif="{{score>=60&&score<80}}">及格</view>
  <view wx:else>不及格</view>
</view>

傳送網路請求

傳送網路請求的域名,必須在微信公眾平臺配置

 handleLoadData(){
    wx.showLoading({
      title: '載入中,稍後',
      mask:true  // 顯示透明蒙層
    })
    wx.request({
      url: 'http://192.168.71.100:5000',
      method:'GET',
      data:{},
      header:{},
      success:(res)=>{
        wx.hideLoading()
        console.log(res.data)
        this.setData({
          userinfo:res.data,
        })
        console.log(this.data.name)
      },
      fail:(err)=>{},
      complete:(res)=>{}

    })
  },

loading提示框

# 顯示
 wx.showLoading({
      title: '載入中,稍後',
      mask:true  // 顯示透明蒙層
    })
    
    
#關閉
 wx.hideLoading()

對話方塊

模態對話方塊

##### wxml
<button type="default" size="mini" bind:tap="showModel">彈出模態框</button>
### js ###
showModel(){
    wx.showModal({
        title: '這是標題',
        content: '這是內容部分~~',
        complete: (res) => {
            if (res.cancel) {
                console.log('使用者取消了')
            }

            if (res.confirm) {
                console.log('使用者確認了')
            }
        }
    })
}

訊息對話方塊

#### wxml
<button type="default" size="mini" bind:tap="showToast">彈出訊息框</button>
### js
showToast(){
    wx.showToast({
        title: '恭喜您,秒殺成功',
        icon:"success",
        duration:2000
    })
}



儲存

#### wxml####
<button type="default" plain bind:tap="handleSave">儲存資料</button>
<button type="primary" plain bind:tap="handleGet">獲取資料</button>
<button type="default" plain bind:tap="handleDelete">刪除資料</button>
<button type="primary" plain bind:tap="handleClear">清空資料</button>
###js### 同步####
handleSave() {
    wx.setStorageSync('name', "justin")
    wx.setStorageSync('userinfo', {name:'lqz',age:19})
},
handleGet() {
    const name=wx.getStorageSync('name')
    const userinfo=wx.getStorageSync('userinfo')
    console.log(name)
    console.log(userinfo)
},
handleDelete() {
    wx.removeStorageSync('name')
},
handleClear() {
    wx.clearStorageSync()
}

###js### 非同步####
handleSave() {
    wx.setStorage({
        key:'name',
        data:"justin"
    })
    wx.setStorage({
        key:'userinfo',
        data:{name:'lqz',age:19}
    })
},

async handleGet() {
    const name= await wx.getStorage({key:'name'})
    const userinfo= await wx.getStorage({key:'userinfo'})
    console.log(name)
    console.log(userinfo)
},
handleDelete() {
    wx.removeStorage({key:'name'})
},
handleClear() {
    wx.clearStorage()
}

上拉下拉載入

方式一

###### js####
// index.js
Page({
    data: {
        page: 1,
        goods: []
    },
    refresh(page) {
        wx.showLoading({
            title: '載入中',
            mask: true
        })
        wx.request({
            url: 'http://127.0.0.1:8000/api/v1/course/actual/?page=' + page,
            method: 'GET',
            success: res => {
                console.log(res.data.code == 100);
                if (page == 1) {
                    this.setData({
                        goods: res.data.results
                    })
                } else {
                    const resData = this.data.goods.concat(res.data.results)
                    this.setData({
                        goods: resData
                    })
                }
            },
            complete: () => {
                wx.hideLoading()
            }
        })
    },
    onLoad() {
        this.refresh(this.data.page)
    },
    onReachBottom() {
        this.data.page++
        console.log('上拉了');
    },
    onPullDownRefresh() {
        this.data.page = 1
        this.refresh(this.data.page)
        if (this.data.goods.length == 3) {
            wx.stopPullDownRefresh()
        }
    }
})
####wxml#####

<view wx:for="{{goods}}" wx:key="index">{{item.name}}</view>

### wxss###
view{
  height: 400rpx;
  display: flex;
  justify-content: center;
  align-items: center;
}
/* 奇數 */
view:nth-child(odd){
  background-color: pink;
}
/* 偶數 */
view:nth-child(even){
  background-color: green;
}

#### json####
{
  "usingComponents": {},
  "onReachBottomDistance": 50,
  "enablePullDownRefresh": true,
  "backgroundColor": "#efefef",
  "backgroundTextStyle":"dark"
}

方式二 scroll-view

##### wxml####
<scroll-view 
class="scroll"
scroll-y
lower-threshold="100"
bindscrolltolower="handleGetData"


refresher-enabled="true"  
refresher-default-style="black"
refresher-background="#f0f0f0"
bindrefresherrefresh="handleReload"
refresher-triggered="{{isRefresh}}"

enable-back-to-top="true"
>
  <view wx:for="{{goods}}" wx:key="index">{{item.name}}</view>
</scroll-view>
### wxss####
.scroll{
  /* 100vh就是指元素的高度等於當前瀏覽器的視窗高度,即瀏覽器內部的可視區域的高度大小 */
  height: 100vh; 
  background-color: grey;
}

view{
  height: 400rpx;
  display: flex;
  justify-content: center;
  align-items: center;
}
/* 奇數 */
view:nth-child(odd){
  background-color: pink;
}
/* 偶數 */
view:nth-child(even){
  background-color: green;
}
    
### js#####
// pages/my/my.js
Page({
    data: {
        page: 0,
        goods: [],
        isRefresh: false
    },
    refresh(page) {
        wx.showLoading({
            title: '載入中',
            mask: true
        })
        wx.request({
            url: 'http://127.0.0.1:8000/api/v1/course/actual/?page=' + page,
            method: 'GET',
            success: res => {
                if (page == 1) {
                    this.setData({
                        goods: res.data.results
                    })
                } else {
                    const resData = this.data.goods.concat(res.data.results)
                    this.setData({
                        goods: resData
                    })
                }
            },
            complete: () => {
                wx.hideLoading()
            }
        })
    },
    handleGetData() {
        this.data.page++
        console.log('上拉了')
        this.refresh(this.data.page)

    },
    handleReload() {
        console.log('下拉重新整理了')
        wx.showToast({
            title: '下拉重新整理',
        })
        this.data.page = 1
        this.refresh(this.data.page)
        this.setData({
            isRefresh: false
        })
    }
})

更新

強制更新

  • 訪問小程式,微信會將小程式程式碼包,下載到微信本地,開啟使用
  • 當小程式更新版本後,微信會檢查小程式版本有沒有更新,並下載最新小程式
  • 更新方式:啟動時同步更新,啟動時非同步更新
### 同步更新####
啟動時同步更新:微信執行時,會定期檢查最近使用的小程式是否有更新。如果有更新,下次小程式啟動時會同步進行更新,更新到最新版本後再開啟小程式。如果 使用者長時間未使用小程式時,會強制同步檢查版本更新
-如果更新失敗,還是會使用本地版本
-新版本釋出24小時後,基本會覆蓋全部使用者
### 非同步更新####
啟動時非同步更新:在啟動前沒有發現更新,小程式每次 冷啟動 時,都會非同步檢查是否有更新版本。如果發現有新版本,將會非同步下載新版本的程式碼包,將新版本的小程式在下一次冷啟動進行使用,當前訪問使用的依然是本地的舊版本程式碼
## 強制更新###
在啟動時非同步更新的情況下,如果開發者希望立刻進行版本更新,可以使用 wx.getUpdateManager API 進行處理。在有新版本時提示使用者重啟小程式更新新版本

在app.js中加入

App({
  // 生命週期函式,啟動小程式就會執行
  onLaunch(){
    const update=wx.getUpdateManager()
    update.onUpdateReady(function(){
      wx.showModal({
        title: '發現新版本',
        content: '重啟應用,更新版本新版本?',
        success:(res)=>{
          if(res.confirm){
            update.applyUpdate()
          }
        }
      })
    })
  }
})

image-20240527145927505

生命週期

應用生命週期

// app.js
App({

  /**
   * 當小程式初始化完成時,會觸發 onLaunch(全域性只觸發一次)
   */
  onLaunch: function () {
    console.log('小程式啟動了')
    
  },

  /**
   * 當小程式啟動,或從後臺進入前臺顯示,會觸發 onShow
   */
  onShow: function (options) {
    console.log('後臺切前臺了')
  },

  /**
   * 當小程式從前臺進入後臺,會觸發 onHide
   */
  onHide: function () {
    console.log('進後臺了')
  },

})

頁面生命週期

Page({

  /**
   * 生命週期函式--監聽頁面載入
   */
  onLoad(options) {
    console.log('1 頁面載入了')

  },

  /**
   * 生命週期函式--監聽頁面初次渲染完成
   */
  onReady() {
    console.log('3 初次渲染完成')
  },

  /**
   * 生命週期函式--監聽頁面顯示
   */
  onShow() {
    console.log('2 頁面顯示')
  },

  /**
   * 生命週期函式--監聽頁面隱藏
   */
  onHide() {
    console.log('4 頁面隱藏')
  },

  /**
   * 生命週期函式--監聽頁面解除安裝
   */
  onUnload() {
    console.log('5 頁面解除安裝')
  },


})

轉發給朋友

方式一:透過右上方 ...

Page({
    onShareAppMessage() {
        return {
          title:"是朋友就點一下",
          query: 'name=justin&age=19',
          imageUrl:'/images/b.jpg'
        }
      },
})

方式二:透過按鈕, 需要給button設定 open-type="share"

####wxml####
<button open-type="share">轉發</button>
####js####
  onShareAppMessage() {
    return {
      title:"是朋友就點一下",
      path:"/pages/my/my", //當前轉發的頁面
      imageUrl:'/images/b.jpg'
    }

  },

分享到朋友圈

  • 必須有分享給朋友
onShareTimeline(){
    return {
        title:"這是一個神奇的頁面",
        query:'name=justin&age=19',
        imageUrl:'/images/b.jpg'
    }
},

獲取頭像

#### js###
Page({
  data:{
    phono: '/static/img/b.jpg'
  },
  choosePhoto(event){
    console.log(event.detail.avatarUrl)
    this.setData({
      phono:event.detail.avatarUrl
    })

  }
})

#####wxml###
<button class="btn" open-type="chooseAvatar" bindchooseavatar="choosePhoto">
<image src="{{phono}}" class="photo"/>
</button>

###wxss###
.btn{
  /* 透明的 */
  background-color: transparent;
}
/* 去掉邊框 */
.btn::after{
  border: none;
}
.photo{
  height: 250rpx;
  width: 250rpx;
  border-radius: 50%;
}

獲取暱稱

### wxml###
<input  type="nickname" placeholder="輸入或獲取暱稱" model:value="{{username}}"/>
<button type="primary" plain bind:tap="showName">提交</button>
    
###js####
Page({
  data:{
    username:"",
  },
  showName(){
    console.log(this.data.username)
  }
})


###wxss##
input {
  border: 1rpx solid pink;
  border-radius: 10rpx;
  padding: 10rpx;
  margin: 10rpx;
}

手機號快速驗證

# 步驟1:需要將 button 元件 open-type 的值設定為 getPhoneNumber,當使用者點選並同意之後,透過 bindgetphonenumber 事件獲取回撥資訊;

# 步驟2:將 bindgetphonenumber 事件回撥中的動態令牌code傳到開發者後臺,並在開發者後臺呼叫微信後臺提供的 phonenumber.getPhoneNumber 介面,消費code來換取使用者手機號。每個code有效期為5分鐘,且只能消費一次。


# 步驟3:後端拿到code --》呼叫getuserphonenumber 換取手機號
https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-info/phone-number/getPhoneNumber.html

# 步驟4:去咱們自己使用者表中查
	-能查到---之前用過,註冊了--》簽發token
    -查不到--》第一次用--執行註冊--》簽發token

手機號實時驗證

# 步驟1:需要將 button 元件 open-type 的值設定為 getRealtimePhoneNumber,當使用者點選並同意之後,透過 bindgetrealtimephonenumber 事件獲取回撥資訊;

# 步驟2:將 bindgetrealtimephonenumber 事件回撥中的動態令牌code傳到開發者後臺,並在開發者後臺呼叫微信後臺提供的 phonenumber.getPhoneNumber 介面,消費code來換取使用者手機號。每個code有效期為5分鐘,且只能消費一次
###wxml###
<button  type="warn" open-type="getPhoneNumber" 
bindgetphonenumber="getPhoneNumber">快速手機號</button>
<button  type="default" plain open-type="getRealtimePhoneNumber"
bindgetrealtimephonenumber="getRealPhoneNumber"
>快速手機號</button>


###js###
getPhoneNumber(event) {
    console.log(event)
    // 透過獲取手機號返回的code--傳遞給後端--後端呼叫:POST https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=ACCESS_TOKEN -->獲取手機號--》後端簽發token給前端

    雲呼叫
    wx.request({
        url: '我們後端地址',
        method:'POST',
        data:{
            code:event.detail.code
        },
        success:(res)=>{
            //在此返回登入資訊,使用者登入
        }

    })
},
getRealPhoneNumber(event) {
    console.log(event)
}

客服功能

微信為小程式提供客服訊息能力,以便小程式使用者可以方便快捷地與小程式服務提供方進行溝通

https://developers.weixin.qq.com/miniprogram/introduction/custom.html

## wxml##
<button type="default" plain open-type="contact">聯絡客服</button>

vant-app

https://vant-ui.github.io/vant-weapp/#/home

使用npm包

  • 專案根目錄,開啟終端【在內建終端開啟】
npm init -y  # 會生成package.json檔案
  • 安裝vant
npm i @vant/weapp -S  
# package.json 能看到下載完成,專案目錄下有node_modules
#(可以使用cnpm:npm install -g cnpm --registry=https://registry.npm.taobao.org)
  • 將 app.json 中的 "style": "v2" 去除,小程式的新版基礎元件強行加上了許多樣式,難以覆蓋,不關閉將造成部分元件樣式混亂

  • project.config.json 的settings中加入

"packNpmManually": true,
"packNpmRelationList": [
  {
    "packageJsonPath": "./package.json",
    "miniprogramNpmDistDir": "./"
  }
]
  • 構建 工具---》構建npm

相關文章