【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】怎么用Taro+Vue3開(kāi)發(fā)小程序_第1頁(yè)
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】怎么用Taro+Vue3開(kāi)發(fā)小程序_第2頁(yè)
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】怎么用Taro+Vue3開(kāi)發(fā)小程序_第3頁(yè)
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】怎么用Taro+Vue3開(kāi)發(fā)小程序_第4頁(yè)
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】怎么用Taro+Vue3開(kāi)發(fā)小程序_第5頁(yè)
已閱讀5頁(yè),還剩16頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】怎么用Taro+Vue3開(kāi)發(fā)小程序

這篇文章主要介紹了怎么用Taro+Vue3開(kāi)發(fā)小程序,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓在下帶著大家一起了解一下。微信小程序是以微信為運(yùn)行環(huán)境的一種應(yīng)用,其實(shí)質(zhì)是Hybrid技術(shù)的應(yīng)用,HybridApp即混合模式移動(dòng)應(yīng)用,因此與H5類似,但又比H5擁有很多原生的能力,例如調(diào)用位置信息和攝像頭等。小程序的開(kāi)發(fā)方式與H5十分相似,用的也是

JavaScript、HTML、CSS

語(yǔ)言。因此,小程序開(kāi)發(fā)可以說(shuō)是一名前端工程師必須要掌握的技能。原生小程序開(kāi)發(fā)有一定的學(xué)習(xí)成本,現(xiàn)如今市面上有很多開(kāi)發(fā)小程序的第三方多端框架,如果不是追求極致性能和穩(wěn)定,還是不要用原生小程序開(kāi)發(fā)了,開(kāi)發(fā)效率太低。第三方多端框架中,taro和uni-app的使用度是最廣的,一般來(lái)說(shuō),做技術(shù)選型時(shí),團(tuán)隊(duì)用react,就用taro,團(tuán)隊(duì)用vue,就用uni-app,兩者之間沒(méi)有什么優(yōu)劣之分,都挺好用的。但很多開(kāi)發(fā)者可能不知道,taro3.0以上版本是支持使用vue的,本篇文章就來(lái)介紹一下如何使用Taro3+Vue3開(kāi)發(fā)微信小程序。我根據(jù)網(wǎng)上的資料完成了本項(xiàng)目的搭建之后,用本項(xiàng)目開(kāi)發(fā)過(guò)一個(gè)小程序,那種開(kāi)發(fā)體驗(yàn)真的是超越了我以往開(kāi)發(fā)過(guò)的所有項(xiàng)目,非常絲滑(可能是我第一次寫vue3的scriptsetup吧,用起來(lái)確實(shí)很舒服)。目標(biāo)功能集成vue3,使用scriptsetup語(yǔ)法開(kāi)發(fā)集成Typescript代碼檢查和格式優(yōu)化全局狀態(tài)管理小程序分包配置樣式封裝,兼容劉海兒屏等樣式問(wèn)題http方法封裝主要技術(shù)棧Taro3Vue3TypeScriptNutUiPiniavue3剛發(fā)布時(shí),由于沒(méi)有合適的ui框架支持,我學(xué)習(xí)vue3的熱情直接被勸退了。直到現(xiàn)在,類似于quasar、element-plus、ant-design-vue等優(yōu)秀框架陸續(xù)支持vue3,并且許多vue3項(xiàng)目被用到了生產(chǎn)環(huán)境中,才發(fā)現(xiàn)大家是把vue3真的用起來(lái)了。比如我們公司隔壁項(xiàng)目組,重構(gòu)項(xiàng)目就用了vue3,這時(shí)我才發(fā)現(xiàn)自己學(xué)習(xí)vue3有點(diǎn)晚了(tips:前端真的太卷了)NutUI是京東風(fēng)格的移動(dòng)端組件庫(kù),它支持使用Vue語(yǔ)言來(lái)編寫可以在H5,小程序平臺(tái)上的應(yīng)用,幫助研發(fā)人員提升開(kāi)發(fā)效率,改善開(kāi)發(fā)體驗(yàn)。我是從Taro文檔知道NutUI的,taro官方推薦使用NutUI開(kāi)發(fā),他們似乎也都是來(lái)自京東同一個(gè)開(kāi)發(fā)團(tuán)隊(duì),我抱著試一試的心態(tài)上手使用,使用體驗(yàn)還不錯(cuò)。Pinia是一個(gè)用于Vue的狀態(tài)管理庫(kù),類似Vuex,是Vue的另一種狀態(tài)管理方案,支持Vue2和Vue3。我第一次接觸前端狀態(tài)管理工具,是剛實(shí)習(xí)時(shí)公司的一個(gè)后臺(tái)管理系統(tǒng),用的dva,那可叫一個(gè)折磨啊,差點(diǎn)直接把我勸退。后面慢慢熟悉了一些,但是不管用redux,還是vuex,還是覺(jué)得寫著麻煩。這次嘗試使用Pinia,用起來(lái)確實(shí)很舒服,符合直覺(jué),易于學(xué)習(xí),有點(diǎn)類似于recoil,但沒(méi)有recoil那么多的概念和API,主體非常精簡(jiǎn),極易上手。Pinia快速入門vscode需安裝插件EslintPrettierVolar與vetur相同,volar是一個(gè)針對(duì)vue的vscode插件,不過(guò)與vetur不同的是,volar提供了更為強(qiáng)大的功能。Volar介紹搭建項(xiàng)目架構(gòu)初始化項(xiàng)目初始化項(xiàng)目之前,需安裝taro,請(qǐng)參考Taro文檔,完成taro安裝使用命令創(chuàng)建模板項(xiàng)目:taro

init

myApp安裝cli用來(lái)執(zhí)行構(gòu)建等操作,之后啟動(dòng)項(xiàng)目,會(huì)生成一個(gè)dist目錄yarn

add

@tarojs/cli

yarn

dev:weapp打開(kāi)微信開(kāi)發(fā)工具工程目錄需要指向構(gòu)建出來(lái)的dist文件打開(kāi)微信開(kāi)發(fā)工具工程目錄需要指向構(gòu)建出來(lái)的dist文件Helloworld出現(xiàn),項(xiàng)目成功跑起來(lái)了!設(shè)置代碼規(guī)范代碼規(guī)范ESlint代碼格式化Prettier提交前檢查husky個(gè)人認(rèn)為,eslint+prettier足以應(yīng)付大部分前端代碼規(guī)范問(wèn)題了,且配置起來(lái)很簡(jiǎn)單,有特殊需求也可繼續(xù)配置。安裝依賴yarn

add

@vue/eslint-config-prettier

@vue/eslint-config-typescript

eslint-plugin-prettier

vue-tsc

husky

-D設(shè)置代碼規(guī)范和格式化規(guī)則.eslintrc.jsmodule.exports

=

{

root:

true,

env:

{

node:

true,

'vue/setup-compiler-macros':

true

},

extends:

['plugin:vue/vue3-essential',

'eslint:recommended',

'@vue/prettier',

'@vue/typescript'],

parserOptions:

{

parser:

'@typescript-eslint/parser'

},

rules:

{

'prettier/prettier':

[

'error',

{

singleQuote:

true,

semi:

false,

trailingComma:

'none',

arrowParens:

'avoid',

printWidth:

100

}

],

'no-console':

process.env.NODE_ENV

===

'production'

?

'warn'

:

'off',

'no-debugger':

process.env.NODE_ENV

===

'production'

?

'warn'

:

'off'

}

}.prettierrc{

"tabWidth":

2,

"singleQuote":

true,

"semi":

false,

"trailingComma":

"none",

"arrowParens":

"avoid",

"endOfLine":

"auto",

"printWidth":

100

}在package.json中script添加Ts檢查命令和Eslint檢查命令"scripts":{

"tsc":

"vue-tsc

--noEmit

--skipLibCheck",

"lint":

"eslint

--ext

.vue

--ext

.js

--ext

.ts

src/"

}添加husky觸發(fā)Git鉤子,代碼提交前檢查npx

husky

install編輯pre-commit執(zhí)行Eslint檢查和Ts檢查#!/bin/sh

.

"$(dirname

"$0")/_/husky.sh"

echo

"eslint

start"

npm

run

lint

echo

"eslint

end"

echo

"ts

lint

start"

npm

run

tsc

echo

"ts

lint

end"至此,項(xiàng)目的代碼規(guī)范和格式規(guī)范配置完畢,多人協(xié)作也不是問(wèn)題了。引入NutUIyarn

add

@nutui/nutui-taro在.babelrc或babel.config.js中添加配置:module.exports

=

{

//

...

plugins:

[

[

'import',

{

libraryName:

'@nutui/nutui',

libraryDirectory:

'dist/packages/_es',

camel2DashComponentName:

false

},

'nutui3-vue'

],

[

'import',

{

libraryName:

'@nutui/nutui-taro',

libraryDirectory:

'dist/packages/_es',

camel2DashComponentName:

false

},

'nutui3-taro'

]

]

}按需引入,安裝插件babel-plugin-importyarn

add

babel-plugin-import

-D樣式處理因?yàn)閚utui的設(shè)計(jì)稿是375的所以將框架的設(shè)計(jì)尺寸調(diào)整為375項(xiàng)目配置文件config/index.js中配置:designWidth:

375app.tsimport

{

createApp

}

from

'vue'

import

{

Button

}

from

'@nutui/nutui-taro'

const

app

=

createApp()

app.use(Button)index.vue中,nut-button組件直接在template中寫,不用再引入<template>

<view

class="index">

<text>{{

msg

}}</text>

<nut-button

type="primary">主要按鈕</nut-button>

</view>

</template>說(shuō)實(shí)話,配置起來(lái)還是有點(diǎn)麻煩,不過(guò)按照官網(wǎng)文檔說(shuō)明來(lái)配也沒(méi)有踩坑,還行。小程序分包配置小程序主包超過(guò)2M,就無(wú)法真機(jī)預(yù)覽了,為了提前做好準(zhǔn)備在一開(kāi)始就進(jìn)行分包處理。比如下面這個(gè)小程序的配置,分了四個(gè)包。app.config.tspages:

['pages/create/index',

'pages/find/index',

'pages/my/index'],

subpackages:

[

{

root:

'pages/featureA',

pages:

['index/index']

},

{

root:

'pagesSub/search',

pages:

['index']

},

{

root:

'pagesSub/my',

pages:

['detail/index',

'about/index']

},

{

root:

'pagesSub/book',

pages:

['detail/index',

'person/list/index',

'person/detail/index']

}

],可以在小程序開(kāi)發(fā)工具編輯器里的代碼依賴分析,查看主包和分包的大小使用scriptsetup語(yǔ)法封裝小程序頁(yè)面生命周期方法hooks/life.tsimport

{

getCurrentInstance

}

from

'@tarojs/taro'

import

{

onMounted

}

from

'vue'

const

Current

=

getCurrentInstance()

export

function

useDidShow(callback)

{

onMounted(callback)

Current?.page?.onShow

&&

(Current.page.onShow

=

callback)

}

export

function

usePullDownRefresh(callback)

{

Current?.page?.onPullDownRefresh

&&

(Current.page.onPullDownRefresh

=

callback)

}使用import

{

useDidShow

}

from

'@/hooks/life'

useDidShow(()

=>

{

//

console.log('onShow')

})安裝Pinia進(jìn)行狀態(tài)管理yarn

add

pinia

yarn

add

taro-plugin-pinia項(xiàng)目配置文件config/index.js中配置:plugins:

['taro-plugin-pinia']以管理用戶信息和用戶登錄狀態(tài)為例,實(shí)現(xiàn)一個(gè)用戶登錄功能需要處理的文件代碼如下:stores/auth.tsimport

{

defineStore

}

from

'pinia'

interface

UserInfoProp

{

nickName:

string

avatarUrl:

string

}

const

useAuth

=

defineStore({

id:

'authInfo',

state:

()

=>

({

userInfo:

{

nickName:

'',

avatarUrl:

''

},

isLogin:

false

}),

actions:

{

login()

{

this.isLogin

=

true

},

logout()

{

this.isLogin

=

false

},

setUserInfo(userInfo:

UserInfoProp)

{

this.userInfo

=

userInfo

}

}

})

export

{

useAuth

}stores/index.tsimport

{

createPinia

}

from

'pinia'

import

{

useAuth

}

from

'./auth'

export

const

store

=

createPinia()

const

storeObj

=

{

auth:

useAuth

}

//

封裝成useStore的形式,這樣一看引用就知道是store的數(shù)據(jù)

export

function

useStore(key:

string)

{

return

storeObj[key]()

}個(gè)人中心index.vue<template>

<main

v-if="isLogin">

<user-info

/>

</main>

<main

v-else>

<nut-button

type="primary"

@click="handleLogin">微信一鍵登錄</nut-button>

</main>

</template>

<script

setup>

import

Taro

from

'@tarojs/taro'

import

{

computed

}

from

'vue'

import

{

useStore

}

from

'@/stores'

import

UserInfo

from

'./userInfo.vue'

const

auth

=

useStore('auth')

const

isLogin

=

computed(()

=>

auth.isLogin)

const

handleLogin

=

()

=>

{

setTimeout(()

=>

{

//

模擬后端請(qǐng)求得到token和userInfo

Taro.setStorageSync('token',

'xxxx')

auth.setUserInfo({

nickName:

'林',

avatarUrl:

'/imagetools/jfs/t1/143702/31/16654/116794/5fc6f541Edebf8a57/4138097748889987.png'

})

auth.login()

},

500)

}

</script>

</script>userInfo組件<template>

<article>

<nut-avatar

size="large"

:icon="userInfo.avatarUrl"></nut-avatar>

<span

class="ellipsis

name">{{

userInfo.nickName

}}</span>

</article>

</template>

<script

setup>

import

Taro

from

'@tarojs/taro'

import

{

computed

}

from

'vue'

import

{

useStore

}

from

'@/stores'

const

auth

=

useStore('auth')

const

userInfo

=

computed(()

=>

auth.userInfo)

</script>總的來(lái)說(shuō),pinia寫起來(lái)是非常簡(jiǎn)潔的,這種類reacthooks的寫法,我是非常喜歡的請(qǐng)求方法封裝http.ts//

封裝axios的請(qǐng)求,返回重新封裝的數(shù)據(jù)格式

//

對(duì)錯(cuò)誤的統(tǒng)一處理

import

{

HttpResponse

}

from

'@/common/interface'

import

Taro

from

'@tarojs/taro'

import

publicConfig

from

'@/config/index'

import

axios,

{

AxiosInstance,

AxiosRequestConfig,

AxiosResponse,

Canceler

}

from

'axios-miniprogram'

import

errorHandle

from

'../common/errorHandle'

const

CancelToken

=

axios.CancelToken

class

HttpRequest

{

private

baseUrl:

string

private

pending:

Record<string,

Canceler>

constructor(baseUrl:

string)

{

this.baseUrl

=

baseUrl

this.pending

=

{}

}

//

獲取axios配置

getInsideConfig()

{

const

config

=

{

baseURL:

this.baseUrl,

headers:

{

'Content-Type':

'application/json;charset=utf-8'

},

timeout:

10000

}

return

config

}

removePending(key:

string,

isRequest

=

false)

{

if

(this.pending[key]

&&

isRequest)

{

this.pending[key]('取消重復(fù)請(qǐng)求')

}

delete

this.pending[key]

}

//

設(shè)定攔截器

interceptors(instance:

AxiosInstance)

{

erceptors.request.use(

config

=>

{

console.log('config

:>>

',

config)

let

isPublic

=

false

publicConfig.publicPath.map(path

=>

{

isPublic

=

isPublic

||

path.test(config.url

||

'')

})

const

token

=

Taro.getStorageSync('token')

if

(!isPublic

&&

token)

{

config.headers.Authorization

=

'Bearer

'

+

token

}

const

key

=

config.url

+

'&'

+

config.method

this.removePending(key,

true)

config.cancelToken

=

new

CancelToken(c

=>

{

this.pending[key]

=

c

})

return

config

},

err

=>

{

errorHandle(err)

return

Promise.reject(err)

}

)

//

響應(yīng)請(qǐng)求的攔截器

erceptors.response.use(

res

=>

{

const

key

=

res.config.url

+

'&'

+

res.config.method

this.removePending(key)

if

(res.status

===

200)

{

return

Promise.resolve(res.data)

}

else

{

return

Promise.reject(res)

}

},

err

=>

{

errorHandle(err)

return

Promise.reject(err)

}

)

}

//

創(chuàng)建實(shí)例

request(options:

AxiosRequestConfig)

{

const

instance

=

axios.create()

const

newOptions

=

Object.assign(this.getInsideConfig(),

options)

erceptors(instance)

return

instance(newOptions)

}

get(url:

string,

config?:

AxiosRequestConfig):

Promise<AxiosResponse>

|

Promise<HttpResponse>

{

const

options

=

Object.assign(

{

method:

'get',

url:

url

},

config

)

return

this.request(options)

}

post(url:

string,

data?:

unknown):

Promise<AxiosResponse>

|

Promise<HttpResponse>

{

return

this.request({

method:

'post',

url:

url,

data:

data

})

}

}

export

default

HttpRequestrequest.tsimport

HttpRequest

from

'./http'

import

config

from

'@/config/index'

const

baseUrl

=

process.env.NODE_ENV

===

'development'

?

config.baseUrl.dev

:

config.baseU

const

request

=

new

HttpRequest(baseUrl)

export

default

request以獲取圖書列表和圖書詳情為例apis/book.tsimport

request

from

'../request'

export

function

getBookList()

{

return

request.get('books/getBookList')

}

export

function

getBookDetail(id:

number)

{

return

request.post('books/getBookDetail',

{

id

})

}請(qǐng)求方法封裝還是用到了axios,只是用的是axios-miniprogram,寫法和web端基本一致,http.js文件引用的一些模塊太多,本文沒(méi)有列出來(lái),可以直接訪問(wèn)本項(xiàng)目github地址查看。樣式封裝iPhoneX底部橫線適配assets/styles/common.scss.safe-area-bottom

{

padding-bottom:

constant(safe-area-inset-bottom);

padding-bottom:

env(safe-area-inset-bottom);

}劉海兒屏適配assets/styles/hairline.scss@mixin

hairline-common()

{

position:

absolute;

box-sizing:

border-box;

content:

'

';

pointer-events:

none;

}

@mixin

hairline()

{

@include

hairline-common();

top:

-50%;

right:

-50%;

bottom:

-50%;

left:

-50%;

border:

0

solid

#eaeaea;

transform:

scale(0.5);

}

@mixin

hairline-top($color,

$left:

0,

$right:

0)

{

@include

hairline-common();

top:

0;

right:

$right;

left:

$left;

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論