<legend id='kos19z25'><style id='4z412nif'><dir id='eiqjw7bo'><q id='lq0k30in'></q></dir></style></legend>

<small id='rhwh9zeh'></small><noframes id='cmgo9pe1'>

  • <tfoot id='e73st1c4'></tfoot>

        <tbody id='czbjg20h'></tbody>
        <i id='kkhzyvyt'><tr id='5veaag7i'><dt id='94rxfctl'><q id='0rloy415'><span id='iqvxcebn'><b id='8wz3h4ib'><form id='qf7e0pzh'><ins id='yvw1qtii'></ins><ul id='y7rc489f'></ul><sub id='ycd8th6e'></sub></form><legend id='muujirx3'></legend><bdo id='746x9l3p'><pre id='u3jn7lqg'><center id='90v4ygo7'></center></pre></bdo></b><th id='vll5ii8q'></th></span></q></dt></tr></i><div id='24lkfrl6'><tfoot id='kip6uvqt'></tfoot><dl id='st47yea6'><fieldset id='lluy7jlj'></fieldset></dl></div>

        網站建設公司當前位置 : 網站建設公司 > 知識普及

        強烈推介的幾個微信小程序開發小技巧,簡單又實用

        發布時間:2022-03-04 17:07   瀏覽次數:次   
        1. 開發中可能遇到的坑以及 Tips
        本來想寫個小技巧的,結果我總結了一堆坑,沒上手之前完全想象不到微信小程序的開發體驗是如此之差、如此之爛,從微信開發者工具到所謂的「全新語言」,都有一種濃濃的半成品的 five 即視感,實在讓我 emmm.... 另外我發現網上的小程序文章大部分都是如何使用和如何避坑的實用文,而不是技巧文,這也從側面反映了小程序的坑多。
         
        在微信小程序原生開發過程中,我不斷發出這樣的疑問「為什么堂堂技術人才多如牛毛的騰訊,會推出如此 laji」,很多弱智反人類的地方,在兩三年前社區就已經提出來,官方回復已經反饋正在修復中,但幾年過去了,還是沒有音信,官方回復仍然是一句冷冰冰的「已反饋」 ????
         
        微信開發者工具經常熱更新不起作用甚至白屏,重新編譯也不行,只能強行退出后再次打開;
         
        跟上一條類似,有時候一點樣式出錯,預覽整個都白屏,調試器里也不說哪里的問題,直接就給你棄療不顯示,重新編譯也無法解決問題,只能強行退出后再次打開;
         
        跟上一條類似,調試器里報的錯經常沒什么用,驢頭不對馬嘴,讓人很難定位問題;
         
        Android 端自定義 Tabbar 在下拉刷新的時候,也會跟著屏幕一起往下移,而且是無法繞過的 Bug,自定義 Tabbar 樣式都寫好了的我又改成自帶的 Tabbar 了!
         
        import 的路徑不支持絕對路徑,比如你希望引用 utils/fetch.js,在不管多深的組件里面你都要慢慢 ../ 點到根目錄,同樣 .wxss 文件 @import 導入文件時也只能使用相對路徑,所以就會出現 ../../../../../../utils/fetch.js 這種東西;
         
        靜態資源路徑不能有漢字,有漢字就無法加載;
         
        .wxs 文件不支持 ES6,只能使用蹩腳的 ES5 寫法;
         
        .wxml 中只能引入 .wxs 文件不能引入 .js 文件???
         
        模板 {{}} 中連方法都不能執行,只能處理簡單的運算如 + - * /,如果遇到數據需要 filter 的場景,需要在 .js 文件中預先格式化好再一個個 setData,比如經常寫的 [2,3,4].includes(type),居然都跑不起來!
         
        .wxs 文件中無法使用 Date 對象,所以不能 new Date(),只能使用蹩腳的 getDate 方法,正則也是一樣,生成正則對象需要使用 getRegExp 函數 getRegExp(pattern[, flags]);
         
        .wxs 中可以調用其它 .wxs 文件,并且只能 require 調用 .wxs 文件,引入的文件必須使用相對路徑;
         
        setData 連一個對象合并都懶得做,如果 data: {a: {b: 1, c: 1}},那么 setData({a: {b: 2}}) 就會丟失 a.c 的值,真是讓人火冒三丈啊,還要 setData({['a.b': 2]}) 這樣才行;
         
        IOS 上 Date 對象獲取任意時間參數比如 getDay、getTime 都為 NaN,是因為 IOS 的 Date 構造函數不支持 2018-04-26 這種格式的日期,必須轉換為 2018/04/26 這種格式才會顯示正常;
         
        開發版小程序有時候請求莫名其妙發不出去,右上角三個點 enable debug 打開「開發調試」之后就莫名其妙能發出去請求了,在多部手機上都是這樣,不明真相。
         
        2. 微信請求 Promise 化
        2.1 使用現成的庫
        安裝 Promise 庫 wx-promise-pro,記得一定要帶 -s 或 --production,要不然無法構建成功。
         
        npm i -S wx-promise-pro
        然后在 app.js 中:
         
        import { promisifyAll } from 'wx-promise-pro'
         
        promisifyAll()  // promisify all wx api
         
        App({ ... })
        之后就可以正常使用了:
         
        wx.pro.showLoading({
            title: '加載中',
            mask: true
        })
          .then(() => console.log('in promise ~'))
        2.2 自己實現
        其實我們可以自己來實現一個這樣的庫,原理很簡單,以原生 API 的 wx.request 為例:
         
        // 原生 API 使用方式
        wx.request({
            url: '',     // 請求的 url
            data: {},    // 參數
            method: '',  // post、get
            success: res => {
                // 請求成功回調函數,res為回調參數
            },
            fail: res => {
                // 請求失敗回調函數,res為回調參數
            }
        })
        如果我們將其 Promise 化,應該的調用方式希望是:
         
        // Promise 化后的期望使用方式
        wx.pro.request({
            url: '',     // 請求的 url
            data: {},    // 參數
            method: ''   // post、get
        })
          .then(res => {
              // 請求成功回調函數,res為回調參數
          })
          .catch(res => {
              // 請求失敗回調函數,res為回調參數
          })
        并且 then 函數返回的是一個 Promise 對象,讓這個函數可以不斷鏈式調用下去,所以首先需要 new 出來一個 Promise 對象:
         
        function request(opt) {
            return new Promise((resolve, reject) => {
                wx.request({
                    ...opt,
                    success: res => { resolve(res)},
                    fail: res => {reject(res)}
                })
            })
        }
        這里代碼我們可以進一步改進,由于 success、fail 這里傳入的參數只是由 resolve、reject 方法執行了下,所以可以直接傳入 resolve、reject 方法即可。
         
        另外,由于其他小程序原生 API 格式一致,所以我們可以使用柯里化方法,來將其他需要進行 Promise 化的 API 進行處理:
         
        function promisify(api) {
            return (opt = {}) => {
                return new Promise((resolve, reject) => {
                    api({
                        ...opt,
                        fail: reject,
                        success: resolve
                    })
                })
            }
        }
        然后,將柯里化方法執行的結果作為新的 Promise 化的 API 掛載到 wx.pro 對象上:
         
        // 將指定 API 進行 Promise 化
        wx.pro.request = promisify(wx.request)
         
        // 使用
        wx.pro.request({...})
            .then(...)
        然后為了方便我們使用其他方法,可以循環將 wx 對象上可以被 Promise 化的方法比如 request、scanCode、showToast、getUserInfo 等一一掛載到 wx.pro 對象上,使用時可以直接 wx.pro.xx,由于這個方法執行返回的是一個 Promise 對象,因此可以像其它 Promise 化的對象那樣使用。
         
        事實上,不知不覺,我們就自己實現了 wx-promise-pro 的源碼,這個庫的核心代碼也就是上面那這幾行 ????
         
        2.3 在項目中使用
        有了上面的工具后,我們可以將其使用在項目中,為了不在項目中遍布 wx.request 或 wx.pro.request 這里可以簡單進行封裝,新建兩個文件如下:
         
        // utils/api/fetch.js 封裝請求方法、請求攔截器
         
        const app = getApp()
         
        const BaseUrl = 'http://172.0.0.1:7300/mock'
         
        const TokenWhiteList = [
            '/app/user/get-by-code'     // 不需要鑒權的api手動添加到這里
        ]
         
        /**
         * 設置請求攔截器
         * @param params 請求參數
         */
        const fetch = (params = {}) => {
            // 攔截器邏輯
            if (!TokenWhiteList.includes(params.url)) {
                params.header = {
                    'content-type': 'application/json',             // 默認值
                    'token': app.globalData.token || ''
                }
            }
         
            if (params.url.startsWith('/')) {    // 拼接完整URL
                params.url = BaseUrl + params.url
            }
         
            // 返回promise
            return wx.pro.request({ ...params })
              .then(({ data: { code, message, data } }) => {
                  // ... 各種異常情況的邏輯處理
                  // 與后端約定 code 20000 時正常返回
                  if (code === 20000) return Promise.resolve(data)
                  return Promise.reject(message)
              })
        }
         
        export { fetch }
         
        然后再將所有 API 封裝到單獨的文件中集中管理:
         
        // utils/api/apis.js 封裝所有請求 API
         
        import { fetch } from './fetch'
         
        /* 根據微信code獲取用戶信息 */
        const appUserGetByCode = ({ code } = {}) => fetch({
            url: '/app/user/get-by-code',
            data: { code }
        })
         
        /* 掃碼登錄 */
        const appUserQrLogin = ({ qrCode } = {}) => fetch({
            method: 'POST',
            url: '/app/user/qr-login',
            data: { qrCode }
        })
         
        /* 個人信息 */
        const appUserInfo = () => fetch({
            url: '/app/user/info'
        })
         
        /* 系統參數獲取,數據字典 */
        const appSysParamListByParam = () => fetch({
            url: '/app/sys-param/list-by-param'
        })
         
        /* 數據字典所有 */
        const appSysParamListAll = () => fetch({
            url: '/app/sys-param/list-all'
        })
         
        export {
            appSysParamListAll,   // 數據字典所有
            appSysParamListByParam,   // 系統參數獲取,數據字典
            appUserGetByCode,   // 根據微信code獲取用戶信息
            appUserQrLogin,   // 掃碼登錄
            appUserInfo   // 個人信息
        }
         
        在要使用 API 的地方就可以這樣引入:
         
        import * as Api from '../../utils/api/apis.js'   // 相對路徑
         
        // 使用方式
        Api.appSysParamListAll()
          .then(({ dataList }) => this.upData({ sysParamList: dataList }))
          .then(() => {
              const keyList = this.data.sysParamList.map(T => T.key)
              this.upData({
                  keyList,
                  formData: { keys: keyList }
              })
          })
        使用方式就很舒服,這里使用到了 upData,就是下面我要介紹的內容,是在下非常推介的小程序工具~ ????
         
        3. setState 修改 data 中想修改對象的屬性
        在小程序中,data 是不能直接操作的,需要使用 setData 函數。鑒于微信小程序開發時 setData 的使用體驗十分蹩腳,我使用了個庫函數 wx-updata,這個庫函數在開發的時候對我很有幫助,這里特意推介給大家。
         
        3.1 為什么要使用 wx-updata
        你在使用 setData 的時候,是不是有時候覺得很難受,舉個簡單的例子:
         
        // 你的 data
        data: {
            name: '蠟筆小新',
            info: { height: 140, color: '黃色' }
        }
        如果要修改 info.height 為 155,使用 setData 要怎么做呢:
         
        // 這樣會把 info 里其他屬性整不見了
        this.setData({ info: { height: 155 } })
         
        // 你需要取出 info 對象,修改后整個 setData
        const { info } = this.data
        info.height = 155
        this.setData({ info })
        似乎并不太復雜,但如果 data 是個很大的對象,要把比較深且不同的對象、數組項挨個改變:
         
        data: {
            name: '蠟筆小新',
            info: {
                height: 140, color: '黃色',
                desc: [{ age: 8 }, '最喜歡大象之歌', '靚仔', { dog: '小白', color: '白色' }]
            }
        }
        比如某個需求,需要把 info.height 改為 155,同時改變 info.desc 數組的第 0 項的 age 為 12,第 3 項的 color 為灰色呢?
         
        // 先取出要改變的對象,改變數字后 setData 回去
        const { info } = this.data
        info.height = 155
        info.desc[0].age = 12
        info.desc[3].color = '灰色'
        this.setData({ info })
         
        // 或者像某些文章里介紹的,這樣可讀性差,也不太實用
        this.setData({
            'info.height': 155,
            'info.desc[0].age': 12,
            'info.desc[3].color': '灰色'
        })
        上面這兩種方法,是我們平常小程序里經常用的,和其他 Web 端的框架相比,就很蹩腳,一種濃濃的半成品感撲面而來,有沒有這樣一個方法:
         
        this.upData({
            info: {
                height: 155,
                desc: [{ age: 12 }, , , { color: '灰色' }]
            }
        })
        這個方法會幫我們深度改變嵌套對象里對應的屬性值,跳過數組項里不想改變的,只設置我們提供了的屬性值、數組項,豈不是省略了一大堆蹩腳的代碼,而且可讀性也極佳呢。
         
        這就是為什么我在上線的項目中使用 wx-updata,而不是 setData
         
        wx-updata 的原理其實很簡單,舉個例子:
         
        this.upData({
            info: {
                height: 155,
                desc: [{ age: 12 }]
            }
        })
         
        // 會被自動轉化為下面這種格式,
        // this.setData({
        //    'info.height': 155,
        //    'info.desc[0].age': 12,
        // })
        原來這個轉化工作是要我們自己手動來做,現在 wx-updata 幫我們做了,豈不美哉!
         
        3.2 wx-updata 使用方式
        在一般情況下,我們可以將方法直接掛載到 Page 構造函數上,這樣就可以在 Page 實例中像使用 setData 一樣使用 upData 了:
         
        // app.js 中掛載
        import { updataInit } from './miniprogram_npm/wx-updata/index'  // 你的庫文件路徑
         
        App({
            onLaunch() {
                Page = updataInit(Page, { debug: true })
            }
        })
         
        // 頁面代碼中使用方式
        this.upData({
            info: { height: 155 },
            desc: [{ age: 13 }, '帥哥'],
            family: [, , [, , , { color: '灰色' }]]
        })
         
        有的框架可能在 Page 對象上進行了進一步修改,直接替換 Page 的方式可能就不太好了,wx-updata 同樣暴露了工具方法,用戶可以在頁面代碼中直接使用工具方法進行處理:
         
        // 頁面代碼中
        import { objToPath } from './miniprogram_npm/wx-updata/index'  // 你的庫文件路徑
         
        Page({
            data: { a: { b: 2}, c: [3,4,5]},
         
            // 自己封裝一下
            upData(data) {
                return this.setData(objToPath(data))
            },
         
            // 你的方法中或生命周期函數
            yourMethod() {
                this.upData({ a: { b: 7}, c: [8,,9]})
            }
        })
         
        針對修改數組指定項的時候,可能存在的跳過數組空位的情況,wx-updata 提供了 Empty 的 Symbol 類型替位符,還有數組的對象路徑方式,感興趣可以看看 wx-updata 的文檔,也可以參考 <開發微信小程序,我為什么放棄 setData,使用 upData> 這篇介紹文章。
         
        另外,使用了 wx-updata 也還可以使用原來的 setData,特別是有時候要清空數組時,靈活使用,可以獲得更好的小程序開發體驗,祝大家小程序開發愉快 ????
         
        4. 使用 scss 寫樣式
        4.1 Webstorm 配置方法
        關于蹩腳的 .wxss 樣式,我使用 webstorm 的 file watcher 工具把 scss 文件監聽改動并實時編譯成 .wxss 文件,感覺比較好用,這里給大家分享一下我的配置:
         
         
        然后記得在 .gitignore 文件中加入要忽略的樣式:
         
        *.scss
        *.wxss.map
        這樣在上傳到 git 的時候,就不會上傳 scss 文件了~ 當然如果你的團隊成員需要 scss 的話,還是建議 git 上傳的時候也加上 scss 文件。
         
        這樣設置之后,一個組件在本地的會是下面這樣
         
         
        本地文件
        其中我們需要關注的就是 .js、.json、.scss、.wxml 文件,另外的文件 .wxss 會在你改動 .scss 文件之后自動生成并更新,而 .wxss.map 是插件自動生成的映射關系,不用管。
         
        如果不是使用 webstorm,可以直接執行命令 sass --watch index.scss:index.wxss -s expanded,命令行如果關閉,sass 命令就不會監聽文件的變動然后編譯,所以最好用編輯器的插件。
         
        同理,也可以使用 less、stylus 等預編譯語言。
         
        4.2 Visual Studio Code 配置方法
        萬能的 VSC 當然也可以做到這個功能,搜索并下載插件 easy sass,然后在 setting.json 中修改/增加配置:
         
        "easysass.formats": [
          {
            "format": "expanded",
            "extension": ".wxss"
          },
          {
            "format": "compressed",
            "extension": ".min.wxss"
          }
        ]
        上面 expanded 是編譯生成的 .wxss 文件,下面 compressed 是壓縮之后的 .wxss 樣式文件,下面這個用不到可以把下面這個配置去掉,然后在 .gitignore 文件中加入要忽略的中間樣式:
         
        *.scss
        其他跟上面一樣,至此你就可以在小程序開發中快樂使用 scss 了~
         
        5. 使用 iconfont 圖標字體
        在 Web 開發中 iconfont 可謂是最常用的靈活圖標字體工具了,這里介紹一下如何在微信小程序中引入 iconfont 圖標。
         
        首先找到你想使用的圖標們,點擊購物車之后下載到本地。
         
        在下下載icon
        下載到本地是一個壓縮包,解壓縮之后將 iconfont.css 文件復制到微信小程序的 styles 文件夾中 (在下的習慣,也可以放到你想放的地方比如 fonts),將后綴改為 .wxss
         
         
        放到本地
        在 app.wxss 中引入樣式:
         
        @import "styles/iconfont.wxss";
        然后在 .wxml 中就可以使用剛剛你添加的圖標了,Web 使用 i 標簽,小程序中使用 text 標簽:
         
        <text class="iconfont icon-my-edit" style="color: blue"></text>
        如果后面要加新的圖標,要下載新的 iconfont.css 的文件到本地重命名并覆蓋,重新走一遍這個流程。
         
        當然,如果你使用的樣式庫提供的一些 icon 能滿足你的要求,那更好,就不用引入外部圖標字體文件了,不過大部分情況下是不滿足的 ????
         
         
          • <i id='7f7ir3bv'><tr id='ibcwpyb4'><dt id='cvo5ylnd'><q id='n35hxbjh'><span id='dsfom1s2'><b id='v21u48lu'><form id='dc39ku40'><ins id='ax1nv8qo'></ins><ul id='qvs4xuv5'></ul><sub id='irz9biao'></sub></form><legend id='8h5o390h'></legend><bdo id='ddccjudq'><pre id='1aul7vum'><center id='se0mu3pz'></center></pre></bdo></b><th id='p1scopue'></th></span></q></dt></tr></i><div id='ycvv7eys'><tfoot id='c28r1wgs'></tfoot><dl id='3znlhsre'><fieldset id='dsomv9yp'></fieldset></dl></div>

            <legend id='o5gyc8c0'><style id='9rbdhxcn'><dir id='m1vf66f0'><q id='fbxki0lt'></q></dir></style></legend><tfoot id='ksp6zr1c'></tfoot>
              <tbody id='hs0lxs53'></tbody>

              <small id='qosgqh7g'></small><noframes id='kvzpi4a0'>

              本文來源于網絡,若有侵權請聯系3449817223#qq.com,將在第一時間刪除。

            1. <i id='llfia5dw'><tr id='fupmcc1e'><dt id='p2she8y7'><q id='c9rusrb4'><span id='qiwvct9u'><b id='2b9pbipe'><form id='rgjz4cgi'><ins id='bukvo748'></ins><ul id='w6banp7e'></ul><sub id='vics7br2'></sub></form><legend id='t7et3hza'></legend><bdo id='l3cjr8lb'><pre id='4s2j471o'><center id='ejy5sr6s'></center></pre></bdo></b><th id='32cszo50'></th></span></q></dt></tr></i><div id='8dtlgjhx'><tfoot id='jpq673o9'></tfoot><dl id='eyyxitb6'><fieldset id='n9myecns'></fieldset></dl></div>
                <tbody id='zumguvpe'></tbody>

              <small id='ym0bgv3y'></small><noframes id='mwwrllun'>

                <tfoot id='mbaltwae'></tfoot>

                1. <legend id='54pz25w0'><style id='kl2dz0uk'><dir id='i92m639y'><q id='jyexzcel'></q></dir></style></legend>
                2. 人妻丰满熟妇av无码区AAP