当前位置: 代码网 > 移动>腾讯>微信 > 利用Taro + Vue3如何开发小程序?(实践)

利用Taro + Vue3如何开发小程序?(实践)

2025年03月31日 微信 我要评论
如何使用 taro3 + vue3 开发小程序?下面本篇文章给大家介绍一下使用 taro3 + vue3 开发微信小程序的方法,希望对大家有所帮助!微信小程序是以微信为运行环境的一种应用,其实质是 h

如何使用 taro3 + vue3 开发小程序?下面本篇文章给大家介绍一下使用 taro3 + vue3 开发微信小程序的方法,希望对大家有所帮助!

利用taro + vue3如何开发小程序?(实践)

微信小程序是以微信为运行环境的一种应用,其实质是 hybrid 技术的应用,hybrid app 即混合模式移动应用,因此与 h5 类似,但又比 h5 拥有很多原生的能力,例如调用位置信息和摄像头等。

小程序的开发方式与 h5 十分相似,用的也是  javascript、html、css  语言。

因此,小程序开发可以说是一名前端工程师必须要掌握的技能。

原生小程序开发有一定的学习成本,现如今市面上有很多开发小程序的第三方多端框架,如果不是追求极致性能和稳定,还是不要用原生小程序开发了,开发效率太低。

第三方多端框架中,taro 和 uni-app 的使用度是最广的,一般来说,做技术选型时,团队用 react,就用 taro,团队用 vue,就用 uni-app,两者之间没有什么优劣之分,都挺好用的。

但很多开发者可能不知道,taro3.0 以上版本是支持使用 vue 的,本篇文章就来介绍一下如何使用 taro3 + vue3 开发微信小程序。

我根据网上的资料完成了本项目的搭建之后,用本项目开发过一个小程序,那种开发体验真的是超越了我以往开发过的所有项目,非常丝滑(可能是我第一次写 vue3 的 script setup 吧,用起来确实很舒服)。

可直接访问本项目 github 地址 clone 使用。

目标功能

  • 集成 vue3,使用 script setup 语法开发
  • 集成 typescript
  • 代码检查和格式优化
  • 全局状态管理
  • 小程序分包配置
  • 样式封装,兼容刘海儿屏等样式问题
  • http 方法封装

主要技术栈

  • taro3
  • vue3
  • typescript
  • nutui
  • pinia

vue3 刚发布时,由于没有合适的 ui 框架支持,我学习 vue3 的热情直接被劝退了。直到现在,类似于github 地址github 地址github 地址 等优秀框架陆续支持 vue3,并且许多 vue3 项目被用到了生产环境中,才发现大家是把 vue3 真的用起来了。

比如我们公司隔壁项目组,重构项目就用了 vue3,这时我才发现自己学习 vue3 有点晚了(tips:前端真的太卷了)

github 地址 是京东风格的移动端组件库,它支持使用 vue 语言来编写可以在 h5,小程序平台上的应用,帮助研发人员提升开发效率,改善开发体验。

我是从 github 地址 知道 nutui 的,taro 官方推荐使用 nutui 开发,他们似乎也都是来自京东同一个开发团队,我抱着试一试的心态上手使用,使用体验还不错。

github 地址 是一个用于 vue 的状态管理库,类似 vuex, 是 vue 的另一种状态管理方案,支持 vue2 和 vue3。

我第一次接触前端状态管理工具,是刚实习时公司的一个后台管理系统,用的 dva,那可叫一个折磨啊,差点直接把我劝退。后面慢慢熟悉了一些,但是不管用 redux,还是 vuex,还是觉得写着麻烦。

这次尝试使用 pinia,用起来确实很舒服,符合直觉,易于学习 ,有点类似于 github 地址,但没有 recoil 那么多的概念和 api,主体非常精简,极易上手。github 地址

vscode 需安装插件

  • eslint
  • prettier
  • volar

与vetur相同,volar是一个针对 vue 的 vscode 插件,不过与 vetur 不同的是,volar 提供了更为强大的功能。

github 地址

搭建项目架构

初始化项目

初始化项目之前,需安装 taro,请参考 github 地址,完成 taro 安装

使用命令创建模板项目:

taro init myapp
登录后复制

1.png

安装 cli 用来执行构建等操作,之后启动项目,会生成一个 dist 目录

yarn add @tarojs/cli
yarn dev:weapp
登录后复制
打开微信开发工具 工程目录需要指向构建出来的 dist 文件

2.png

3.png

hello world 出现,项目成功跑起来了!

设置代码规范

  • 代码规范 eslint
  • 代码格式化 prettier
  • 提交前检查 husky

个人认为,eslint + prettier 足以应付大部分前端代码规范问题了,且配置起来很简单,有特殊需求也可继续配置。

安装依赖

yarn add @vue/eslint-config-prettier @vue/eslint-config-typescript eslint-plugin-prettier vue-tsc husky -d
登录后复制

设置代码规范和格式化规则

.eslintrc.js

module.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/"
}
登录后复制

添加 github 地址 触发 git 钩子,代码提交前检查

npx husky install
登录后复制

编辑 pre-commit 执行 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---"
登录后复制

至此,项目的代码规范和格式规范配置完毕,多人协作也不是问题了。

引入 nutui

yarn 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-import

yarn add babel-plugin-import -d
登录后复制

样式处理 因为 nutui 的设计稿是 375 的 所以将框架的设计尺寸调整为 375

项目配置文件 config/index.js 中配置:

designwidth: 375
登录后复制

app.ts

import { createapp } from 'vue'
import { button } from '@nutui/nutui-taro'

const app = createapp()

app.use(button)
登录后复制

index.vue 中,nut-button 组件直接在 template 中写,不用再引入

<template>
  <view>
    <text>{{ msg }}</text>
    <nut-button>主要按钮</nut-button>
  </view></template>
登录后复制

4.png

说实话,配置起来还是有点麻烦,不过按照官网文档说明来配也没有踩坑,还行。

小程序分包配置

小程序主包超过 2m,就无法真机预览了,为了提前做好准备在一开始就进行分包处理。比如下面这个小程序的配置,分了四个包。

app.config.ts

pages: ['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']
}
],
登录后复制

可以在小程序开发工具编辑器里的代码依赖分析,查看主包和分包的大小

5.png

使用 script setup 语法封装小程序页面生命周期方法

hooks/life.ts

import { getcurrentinstance } from '@tarojs/taro'
import { onmounted } from 'vue'

const current = getcurrentinstance()

export function usedidshow(callback) {
    onmounted(callback) current?.page?.onshow &amp;&amp; (current.page.onshow = callback)
}
export function usepulldownrefresh(callback) {
    current?.page?.onpulldownrefresh &amp;&amp; (current.page.onpulldownrefresh = callback)
}
登录后复制

使用

import { usedidshow } from '@/hooks/life'

usedidshow(() =&gt; {
  // console.log('onshow')
})
登录后复制

安装 github 地址 进行状态管理

yarn add pinia
yarn add taro-plugin-pinia
登录后复制

项目配置文件 config/index.js 中配置:

plugins: ['taro-plugin-pinia']
登录后复制

以管理用户信息和用户登录状态为例,实现一个用户登录功能

6.png

需要处理的文件代码如下:

stores/auth.ts

import { definestore } from 'pinia'

interface userinfoprop {
  nickname: string
  avatarurl: string
}

const useauth = definestore({
  id: 'authinfo',
  state: () =&gt; ({
    userinfo: {
      nickname: '',
      avatarurl: ''
    },
    islogin: false
  }),
  actions: {
    login() {
      this.islogin = true
    },
    logout() {
      this.islogin = false
    },
    setuserinfo(userinfo: userinfoprop) {
      this.userinfo = userinfo
    }
  }
})
export { useauth }
登录后复制

stores/index.ts

import { createpinia } from 'pinia'
import { useauth } from './auth'

export const store = createpinia()

const storeobj = {
  auth: useauth
}

// 封装成usestore的形式,这样一看引用就知道是store的数据
export function usestore(key: string) {
  return storeobj[key]()
}
登录后复制

个人中心 index.vue

<template>
  <main>
    <user-info></user-info>
  </main>
  <main>
    <nut-button>微信一键登录</nut-button>
  </main></template><script>
import taro from &#39;@tarojs/taro&#39;
import { computed } from &#39;vue&#39;
import { usestore } from &#39;@/stores&#39;

import userinfo from &#39;./userinfo.vue&#39;

const auth = usestore(&#39;auth&#39;)
const islogin = computed(() => auth.islogin)

const handlelogin = () => {
  settimeout(() => {
    // 模拟后端请求得到token和userinfo
    taro.setstoragesync(&#39;token&#39;, &#39;xxxx&#39;)
    auth.setuserinfo({
      nickname: &#39;林&#39;,
      avatarurl:
        &#39;https://img12.360buyimg.com/imagetools/jfs/t1/143702/31/16654/116794/5fc6f541edebf8a57/4138097748889987.png&#39;
    })
    auth.login()
  }, 500)
}
</script>
登录后复制

userinfo 组件

<template>
  <article>
    <nut-avatar></nut-avatar>
    <span>{{ userinfo.nickname }}</span>
  </article></template><script>
import taro from &#39;@tarojs/taro&#39;
import { computed } from &#39;vue&#39;
import { usestore } from &#39;@/stores&#39;

const auth = usestore(&#39;auth&#39;)
const userinfo = computed(() => auth.userinfo)

</script>
登录后复制

总的来说, pinia 写起来是非常简洁的,这种类 react hooks 的写法,我是非常喜欢的

请求方法封装

http.ts

// 封装axios的请求,返回重新封装的数据格式
// 对错误的统一处理
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>

  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] &amp;&amp; isrequest) {
      this.pending[key]('取消重复请求')
    }
    delete this.pending[key]
  }

  // 设定拦截器
  interceptors(instance: axiosinstance) {
    instance.interceptors.request.use(
      config =&gt; {
        console.log('config :&gt;&gt; ', config)
        let ispublic = false
        publicconfig.publicpath.map(path =&gt; {
          ispublic = ispublic || path.test(config.url || '')
        })
        const token = taro.getstoragesync('token')
        if (!ispublic &amp;&amp; token) {
          config.headers.authorization = 'bearer ' + token
        }
        const key = config.url + '&amp;' + config.method
        this.removepending(key, true)
        config.canceltoken = new canceltoken(c =&gt; {
          this.pending[key] = c
        })
        return config
      },
      err =&gt; {
        errorhandle(err)
        return promise.reject(err)
      }
    )

    // 响应请求的拦截器
    instance.interceptors.response.use(
      res =&gt; {
        const key = res.config.url + '&amp;' + res.config.method
        this.removepending(key)
        if (res.status === 200) {
          return promise.resolve(res.data)
        } else {
          return promise.reject(res)
        }
      },
      err =&gt; {
        errorhandle(err)
        return promise.reject(err)
      }
    )
  }

  // 创建实例
  request(options: axiosrequestconfig) {
    const instance = axios.create()
    const newoptions = object.assign(this.getinsideconfig(), options)
    this.interceptors(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 httprequest</httpresponse></axiosresponse></httpresponse></axiosresponse></string>
登录后复制

request.ts

import httprequest from './http'
import config from '@/config/index'
const baseurl = process.env.node_env === 'development' ? config.baseurl.dev : config.baseurl.pro

const request = new httprequest(baseurl)

export default request
登录后复制

以获取图书列表和图书详情为例

apis/book.ts

import request from '../request'

export function getbooklist() {
  return request.get('books/getbooklist')
}

export function getbookdetail(id: number) {
  return request.post('books/getbookdetail', {
    id
  })
}
登录后复制

请求方法封装还是用到了 axios,只是用的是 axios-miniprogram ,写法和 web 端基本一致,http.js 文件引用的一些模块太多,本文没有列出来,可以直接访问本项目 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;
  border-top: 1px solid $color;
  transform: scaley(0.5);
}

@mixin hairline-bottom($color, $left: 0, $right: 0) {
  @include hairline-common();
  right: $right;
  bottom: 0;
  left: $left;
  border-bottom: 1px solid $color;
  transform: scaley(0.5);
}

[class*='van-hairline'] {
  &amp;::after {
    @include hairline();
  }
}

.van-hairline {
  &amp;,
  &amp;--top,
  &amp;--left,
  &amp;--right,
  &amp;--bottom,
  &amp;--surround,
  &amp;--top-bottom {
    position: relative;
  }

  &amp;--top::after {
    border-top-width: 1px;
  }

  &amp;--left::after {
    border-left-width: 1px;
  }

  &amp;--right::after {
    border-right-width: 1px;
  }

  &amp;--bottom::after {
    border-bottom-width: 1px;
  }

  &amp;,
  &amp;-unset {
    &amp;--top-bottom::after {
      border-width: 1px 0;
    }
  }

  &amp;--surround::after {
    border-width: 1px;
  }
}
登录后复制

多行文字省略

assets/styles/ellipsis.scss

@mixin multi-ellipsis($lines) {
  display: -webkit-box;
  overflow: hidden;
  text-overflow: ellipsis;
  -webkit-line-clamp: $lines;
  -webkit-box-orient: vertical;
}

@mixin ellipsis() {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.ellipsis {
  @include ellipsis();
}

.multi-ellipsis--l2 {
  @include multi-ellipsis(2);
}

.multi-ellipsis--l3 {
  @include multi-ellipsis(3);
}
登录后复制

总结

至此,终于完成了 taro + vue3 的项目搭建,强烈建议直接访问项目 github 地址 clone 使用,有一些配置细节本文无法一一列举,就在项目中去发掘吧!

如果我的文章能帮助到你,那将是我的荣幸!

【相关学习推荐:github 地址

以上就是利用taro + vue3如何开发小程序?(实践)的详细内容,更多请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com