uni-app 開発アプレット: プロジェクトの構造と経験の共有

uni-app 開発アプレット: プロジェクトの構造と経験の共有

2022App2019 年に、製品を迅速に完成させて発売するために、同社は WeChat アプレットをキャリアとして選択しました。なぜなら、その後も開発する予定であるためです。会社は契約を結んでいますが、コードセットiosAndroid複数のパッケージにパッケージ化できる場合には、端末、コストはある程度解決できます;フロントエンド技術スタックまたvue、検査の選択でuni-appその後、小規模なプログラムプロジェクトを数多く開発し、経験を積み、より多くの業務コンポーネントをパッケージ化してきましたが、ここではプロジェクトの全体構造、共通メソッドのパッケージ化、注意点などをuni-app紹介します。uni-app全文コードが配置されgithub、最初に「いいね!」してから読んでください, 年間数百万ドルを稼ぎます!

プロジェクトを作成する

uni-appプロジェクトを作成するには 2 つの方法があります。

小程序⚠️プロジェクトの作成方法はプロジェクトの要件に応じて選択する必要があることに注意してください。単一の開発または開発環境のみの場合は、ビジュアルツールで作成Appできます。HBuilderXマルチターミナル開発で、同じコードのセットをパッケージ化して複数の小さなプログラムを生成する可能性がある場合は、それを使用して作成することをお勧めします。そうしないと、後で指定された条件に従ってビルドvue-cliとコンパイルを自動化するのがより困難になります。条件付きコンパイルについては、この記事の後半で詳しく説明します。

以下を使用してvue-cliインストールして実行するのは比較的簡単です。

1. vue-cli をグローバルにインストールする

npm install -g @vue/cli

2. ユニアプリの作成

vue create -p dcloudio/uni-preset-vue 项目名称

3. プロジェクトフォルダーに入る

cd 项目名称

4. プロジェクトが WeChat アプレットに基づいている場合、プロジェクトを実行するには、package.jsonその中のコマンドを次のように変更します。

"scripts": {
    "serve": "npm run dev:mp-weixin"
}

それから実行します

npm run serve

cliデフォルトではプリコンパイルなしでプロジェクトを作成しますcss。手動でインストールする必要があります。例を次に示しますsass

npm i sass --save-dev
npm i sass-loader --save-dev

プロジェクト全体の構造

通过HBuilderX或者vue-cli创建的项目,目录结构有稍许不同,但基本没什么差异,这里就按vue-cli创建的项目为例,整体架构配置如下:

    ├──dist 编译后的文件路径
    ├──package.json 配置项
	├──src 核心内容
        ├──api 项目接口
        ├──components 全局公共组件
        ├──config 项目配置文件
        ├──pages 主包
        ├──static 全局静态资源
        ├──store vuex
        ├──mixins 全局混入
        ├──utils 公共方法
        ├──App.vue 应用配置,配置App全局样式以及监听
        ├──main.js Vue初始化入口文件
        ├──manifest.json 配置应用名称、appid等打包信息
        ├──pages.json 配置页面路由、导航条、选项卡等页面类信息
        └──uni.scss 全局样式

封装方法

工欲善其事,必先利其器。在开发之前,我们可以把一些全局通用的方法进行封装,以及把uni-app提供的api进行二次封装,方便使用。全局的公共方法我们都会放到/src/utils文件夹下。

封装常用方法

下面这些方法都放在/src/utils/utils.js中,文章末尾会提供github链接方便查看。如果项目较大,建议把方法根据功能定义不同的js文件。

小程序Toast提示

/**
 * 提示方法
 * @param {String} title 提示文字
 * @param {String}  icon icon图片
 * @param {Number}  duration 提示时间
 */
export function toast(title, icon = 'none', duration = 1500) {
    if(title) {
        uni.showToast({
            title,
            icon,
            duration
        })
    }
}

缓存操作(设置/获取/删除/清空)

/**
 * 缓存操作
 * @param {String} val
 */
export function setStorageSync(key, data) {
    uni.setStorageSync(key, data)
}

export function getStorageSync(key) {
    return uni.getStorageSync(key)
}

export function removeStorageSync(key) {
    return uni.removeStorageSync(key)
}

export function clearStorageSync() {
    return uni.clearStorageSync()
}

页面跳转

/**
 * 页面跳转
 * @param {'navigateTo' | 'redirectTo' | 'reLaunch' | 'switchTab' | 'navigateBack' | number } url  转跳路径
 * @param {String} params 跳转时携带的参数
 * @param {String} type 转跳方式
 **/
export function useRouter(url, params = {}, type = 'navigateTo') {
    try {
        if (Object.keys(params).length) url = `${url}?data=${encodeURIComponent(JSON.stringify(params))}`
        if (type === 'navigateBack') {
            uni[type]({ delta: url })
        } else {
            uni[type]({ url })
        }
    } catch (error) {
        console.error(error)
    }
}

图片预览

/**
 * 预览图片
 * @param {Array} urls 图片链接
 */
export function previewImage(urls, itemList = ['发送给朋友', '保存图片', '收藏']) {
    uni.previewImage({
        urls,
        longPressActions: {
            itemList,
            fail: function (error) {
                console.error(error,'===previewImage')
            }
        }
    })
}

图片下载

/**
 * 保存图片到本地
 * @param {String} filePath 图片临时路径
 **/
export function saveImage(filePath) {
    if (!filePath) return false
    uni.saveImageToPhotosAlbum({
        filePath,
        success: (res) => {
            toast('图片保存成功', 'success')
        },
        fail: (err) => {
            if (err.errMsg === 'saveImageToPhotosAlbum:fail:auth denied' || err.errMsg === 'saveImageToPhotosAlbum:fail auth deny') {
                uni.showModal({
                    title: '提示',
                    content: '需要您授权保存相册',
                    showCancel: false,
                    success: (modalSuccess) => {
                        uni.openSetting({
                            success(settingdata) {
                                if (settingdata.authSetting['scope.writePhotosAlbum']) {
                                    uni.showModal({
                                        title: '提示',
                                        content: '获取权限成功,再次点击图片即可保存',
                                        showCancel: false
                                    })
                                } else {
                                    uni.showModal({
                                        title: '提示',
                                        content: '获取权限失败,将无法保存到相册哦~',
                                        showCancel: false
                                    })
                                }
                            },
                            fail(failData) {
                                console.log('failData', failData)
                            }
                        })
                    }
                })
            }
        }
    })
}

更多函数就不在文章中展示了,已经放到/src/utils/utils,js里面,具体可以到github查看。

请求封装

为了减少在页面中的请求代码,所以我们要对uni-app提供的请求方式进行二次封装,在/src/utils文件夹下建立request.js,具体代码如下:


import {toast, clearStorageSync, getStorageSync, useRouter} from './utils'
import {BASE_URL} from '@/config/index'

const baseRequest = async (url, method, data, loading = true) =>{
	header.token = getStorageSync('token') || ''
	return new Promise((reslove, reject) => {
	loading && uni.showLoading({title: 'loading'})
        uni.request({
                url: BASE_URL + url,
                method: method || 'GET',
                header: header,
                timeout: 10000,
                data: data || {},
                success: (successData) => {
                    const res = successData.data
                    uni.hideLoading()
                    if(successData.statusCode == 200){
                            if(res.resultCode == 'PA-G998'){
                                    clearStorageSync()
                                    useRouter('/pages/login/index', 'reLaunch')
                            }else{
                                    reslove(res.data)
                            }
                    }else{
                            toast('网络连接失败,请稍后重试')
                            reject(res)
                    }
                },
                fail: (msg) => {
                    uni.hideLoading()
                    toast('网络连接失败,请稍后重试')
                    reject(msg)
                }
        })
    })
}

const request = {};

['options', 'get', 'post', 'put', 'head', 'delete', 'trace', 'connect'].forEach((method) => {
	request[method] = (api, data, loading) => baseRequest(api, method, data, loading)
})

export default request

请求封装好以后,我们在/src/api文件夹下按业务模块建立对应的api文件,拿获取用户信息接口举例子:

/src/api文件夹下建立user.js,然后引入request.js

import request from '@/utils/request'

//个人信息
export const info = data => request.post('/v1/api/info', data)

在页面中直接使用:

import {info} from '@/api/user.js'

export default {
    methods: {
        async getUserinfo() {
            let info = await info()
            console.log('用户信息==', info)
        }
    }
}

版本切换

很多场景下,需要根据不同的环境去切换不同的请求域名、APPID等字段,这时候就需要通过环境变量来进行区分。下面案例我们就分为三个环境:开发环境(dev)、测试环境(test)、生产环境(prod)。

建立env文件

在项目根目录建立下面三个文件并写入内容(常量名要以VUE开头命名):

.env.dev(开发环境)

VUE_APP_MODE=build
VUE_APP_ID=wxbb53ae105735a06b
VUE_APP_BASE=https://www.baidu.dev.com

.env.test(テスト環境)

VUE_APP_MODE=build
VUE_APP_ID=wxbb53ae105735a06c
VUE_APP_BASE=https://www.baidu.test.com

.env.prod(本番環境)

VUE_APP_MODE=wxbb53ae105735a06d
VUE_APP_ID=prod
VUE_APP_BASE=https://www.baidu.prod.com

package.jsonファイルを変更する

"scripts": {
    "dev:mp-weixin": "cross-env UNI_PLATFORM=mp-weixin vue-cli-service uni-build --watch --mode dev",
    "build:mp-weixin": "cross-env UNI_PLATFORM=mp-weixin vue-cli-service uni-build --watch --mode prod"
},

それから実行します

npm run dev:mp-weixin

以下に次のように/src/pages/index/index.vue出力します。

onLoad() {
    console.log(process.env.VUE_APP_MODE, '====VUE_APP_BASE')
    console.log(process.env.VUE_APP_BASE, '====VUE_APP_BASE')
},

この時点での出力は、

dev ====VUE_APP_BASE
https://www.baidu.dev.com ====VUE_APP_BASE

appidを動的に変更する

複数の小さなプログラムを生成するために同じコード セットをパッケージ化する必要がある場合は、動的に変更する必要があります。appid記事の冒頭で、appid は/src/manifest.jsonファイル内で構成されていると述べましたが、jsonファイルには変数を直接書き込むことができません。現時点では、公式の解決策を参照できます:vue.config.jsファイルを作成します。具体的な操作は次のとおりです。

ルート ディレクトリにファイルを作成しvue.config.js、次の内容を書き込みます。

// 读取 manifest.json ,修改后重新写入
const fs = require('fs')

const manifestPath = './src/manifest.json'
let Manifest = fs.readFileSync(manifestPath, { encoding: 'utf-8' })
function replaceManifest(path, value) {
  const arr = path.split('.')
  const len = arr.length
  const lastItem = arr[len - 1]

  let i = 0
  let ManifestArr = Manifest.split(/\n/)

  for (let index = 0; index < ManifestArr.length; index++) {
    const item = ManifestArr[index]
    if (new RegExp(`"${arr[i]}"`).test(item)) ++i
    if (i === len) {
      const hasComma = /,/.test(item)
      ManifestArr[index] = item.replace(
        new RegExp(`"${lastItem}"[\\s\\S]*:[\\s\\S]*`),
        `"${lastItem}": ${value}${hasComma ? ',' : ''}`
      )
      break
    }
  }

  Manifest = ManifestArr.join('\n')
}
// 读取环境变量内容
replaceManifest('mp-weixin.appid', `"${process.env.VUE_APP_ID}"`)

fs.writeFileSync(manifestPath, Manifest, {
  flag: 'w'
})

終わり

これでプロジェクトの初期作業は終了です。後で、電子商取引アプレット プロジェクトuni-appの完全なセットを作成する機会があるので、注意してください。uniコードはgithubに送信されています。役に立った場合は、忘れずにstar!をクリックしてください。

おすすめ

転載: juejin.im/post/7259589417736847416