>  기사  >  위챗 애플릿  >  Taro + Vue3를 사용하여 작은 프로그램을 개발하는 방법은 무엇입니까? (관행)

Taro + Vue3를 사용하여 작은 프로그램을 개발하는 방법은 무엇입니까? (관행)

青灯夜游
青灯夜游앞으로
2022-01-13 10:28:216589검색

Taro3 + Vue3를 사용하여 작은 프로그램을 개발하는 방법은 무엇입니까? 다음 기사에서는 Taro3 + Vue3을 사용하여 WeChat 애플릿을 개발하는 방법을 소개하겠습니다. 도움이 되길 바랍니다!

Taro + Vue3를 사용하여 작은 프로그램을 개발하는 방법은 무엇입니까? (관행)

WeChat 애플릿은 WeChat을 운영 환경으로 사용하는 애플리케이션입니다. 그 본질은 Hybrid 기술을 적용한 혼합 모드 모바일 애플리케이션이므로 H5code>는 유사하지만 위치 정보 호출, 카메라 등 H5보다 기본 기능이 더 많습니다. Hybrid 技术的应用,Hybrid App 即混合模式移动应用,因此与 H5 类似,但又比 H5 拥有很多原生的能力,例如调用位置信息和摄像头等。

小程序的开发方式与 H5 十分相似,用的也是  JavaScriptHTMLCSS  语言。

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

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

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

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

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

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

目标功能

  • 集成 vue3,使用 script setup 语法开发
  • 集成 Typescript
  • 작은 프로그램의 개발 방법은 JavaScript, HTML, CSS 언어를 사용하는 H5와 매우 유사합니다.
  • 그러므로 소규모 프로그램 개발은 프론트엔드 엔지니어가 반드시 마스터해야 하는 기술이라고 할 수 있습니다.
  • 네이티브 미니 프로그램 개발에는 일정한 학습 비용이 있습니다. 요즘에는 미니 프로그램 개발을 위한 타사 멀티 터미널 프레임워크가 많이 나와 있습니다. 궁극적인 성능과 안정성을 추구하지 않는다면 개발하지 않는 것이 좋습니다. 네이티브 미니 프로그램 개발 효율성이 너무 낮습니다.
  • 타사 다중 터미널 프레임워크 중에서 tarouni-app이 가장 널리 사용됩니다. 일반적으로 팀에서는 기술을 선택할 때 를 사용합니다. React에는 taro를 사용하고, 팀에서는 vue를 사용하고, uni-app을 사용합니다. 둘 사이에는 차이가 없으며 둘 다 매우 사용하기 쉽습니다.
  • 그러나 많은 개발자는 taro3.0 이상이 vue 사용을 지원한다는 사실을 알지 못할 수도 있습니다. 이 기사에서는 Taro3 + Vue3을 사용하여 WeChat 애플릿을 개발하는 방법을 소개합니다.
  • 인터넷 정보를 바탕으로 이 프로젝트의 구축을 완료한 후 이 프로젝트를 사용하여 작은 프로그램을 개발했습니다. 개발 경험은 정말 이전에 개발했던 모든 프로젝트를 능가했습니다. vue3의 스크립트 설정을 처음으로 작성해 보겠습니다. 사용하기가 정말 편합니다.

이 프로젝트에 직접 액세스할 수 있습니다 github 주소

클론 사용.

    대상 기능

  • vue3 통합, 스크립트 설정 구문 개발 사용
  • Typescript 통합
  • 코드 검사 및 서식 지정 최적화
  • 글로벌 상태 관리
미니 프로그램 하도급 구성

스타일 캡슐화, 노치 화면 및 기타 스타일 문제와 호환http 메서드 캡슐화주요 기술 스택

Taro3

Vue3

TypeScript

NutUi

Pinia

vue3이 처음 출시되었을 때 적합한 UI 프레임워크 지원이 부족하여 vue3 학습에 대한 열정이 직접적으로 좌절되었습니다. 지금까지

quasar

,

element-plus🎜, 🎜ant-design-vue🎜 등 우수한 프레임워크들이 vue3를 잇달아 지원해왔고, 많은 vue3 프로젝트가 프로덕션 환경에서 사용되어 왔지만 모두가 실제로 vue3을 사용하고 있습니다. 🎜🎜예를 들어 우리 회사 옆 프로젝트 팀은 리팩토링 프로젝트를 위해 vue3을 사용했습니다. 그제서야 vue3를 배우는 것이 조금 늦었다는 것을 깨달았습니다. (팁: 프론트엔드가 정말 너무 복잡합니다.) 🎜🎜🎜NutUI 🎜는 JD 스타일의 모바일 컴포넌트 라이브러리로, Vue 언어를 사용하여 H5 및 미니 프로그램 플랫폼에서 사용할 수 있는 애플리케이션을 작성하도록 지원하여 개발자가 개발 효율성과 개발 경험을 향상시킬 수 있도록 돕습니다. 🎜🎜NutUI에 대해 🎜Taro 문서🎜에서 배웠습니다. Taro는 공식적으로 NutUI를 사용하여 개발할 것을 권장합니다. 그들은 모두 JD.com의 동일한 개발 팀에 속한 것 같습니다. 한 번 해보자는 마음으로 사용하기 시작했습니다. 경험은 나쁘지 않습니다. 🎜🎜🎜Pinia🎜는 Vuex와 유사한 Vue용 상태 관리 라이브러리로, Vue2 및 Vue3를 지원하는 또 다른 Vue용 상태 관리 솔루션입니다. 🎜🎜제가 프론트엔드 상태 관리 도구를 처음 접한 것은 제가 인턴이었을 때 회사의 백엔드 관리 시스템이었습니다. 그것은 고문이었고 거의 그만두도록 설득했습니다. 점점 익숙해지긴 했지만, redux를 사용하든 vuex를 사용하든 여전히 작성하는 것이 번거롭습니다. 🎜

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

vscode 需安装插件

  • Eslint
  • Prettier
  • Volar

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

Volar 介绍

搭建项目架构

初始化项目

初始化项目之前,需安装 taro,请参考 Taro 文档,完成 taro 安装

使用命令创建模板项目:

taro init myApp

Taro + Vue3를 사용하여 작은 프로그램을 개발하는 방법은 무엇입니까? (관행)

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

yarn add @tarojs/cli
yarn dev:weapp

打开微信开发工具 工程目录需要指向构建出来的 dist 文件

Taro + Vue3를 사용하여 작은 프로그램을 개발하는 방법은 무엇입니까? (관행)

Taro + Vue3를 사용하여 작은 프로그램을 개발하는 방법은 무엇입니까? (관행)

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/"
}

添加 husky 触发 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 class="index">
    <text>{{ msg }}</text>
    <nut-button type="primary">主要按钮</nut-button>
  </view>
</template>

Taro + Vue3를 사용하여 작은 프로그램을 개발하는 방법은 무엇입니까? (관행)

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

小程序分包配置

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

app.config.ts

pages: [&#39;pages/create/index&#39;, &#39;pages/find/index&#39;, &#39;pages/my/index&#39;],
subpackages: [
{
  root: &#39;pages/featureA&#39;,
  pages: [&#39;index/index&#39;]
},
{
  root: &#39;pagesSub/search&#39;,
  pages: [&#39;index&#39;]
},
{
  root: &#39;pagesSub/my&#39;,
  pages: [&#39;detail/index&#39;, &#39;about/index&#39;]
},
{
  root: &#39;pagesSub/book&#39;,
  pages: [&#39;detail/index&#39;, &#39;person/list/index&#39;, &#39;person/detail/index&#39;]
}
],

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

Taro + Vue3를 사용하여 작은 프로그램을 개발하는 방법은 무엇입니까? (관행)

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

hooks/life.ts

import { getCurrentInstance } from &#39;@tarojs/taro&#39;
import { onMounted } from &#39;vue&#39;

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 &#39;@/hooks/life&#39;

useDidShow(() => {
  // console.log(&#39;onShow&#39;)
})

安装 Pinia 进行状态管理

yarn add pinia
yarn add taro-plugin-pinia

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

plugins: [&#39;taro-plugin-pinia&#39;]

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

Taro + Vue3를 사용하여 작은 프로그램을 개발하는 방법은 무엇입니까? (관행)

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

stores/auth.ts

import { defineStore } from &#39;pinia&#39;

interface UserInfoProp {
  nickName: string
  avatarUrl: string
}

const useAuth = defineStore({
  id: &#39;authInfo&#39;,
  state: () => ({
    userInfo: {
      nickName: &#39;&#39;,
      avatarUrl: &#39;&#39;
    },
    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 &#39;pinia&#39;
import { useAuth } from &#39;./auth&#39;

export const store = createPinia()

const storeObj = {
  auth: useAuth
}

// 封装成useStore的形式,这样一看引用就知道是store的数据
export function useStore(key: string) {
  return storeObj[key]()
}

个人中心 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 &#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>

</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 &#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 &#39;@/common/interface&#39;
import Taro from &#39;@tarojs/taro&#39;
import publicConfig from &#39;@/config/index&#39;
import axios, {
  AxiosInstance,
  AxiosRequestConfig,
  AxiosResponse,
  Canceler
} from &#39;axios-miniprogram&#39;
import errorHandle from &#39;../common/errorHandle&#39;
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: {
        &#39;Content-Type&#39;: &#39;application/json;charset=utf-8&#39;
      },
      timeout: 10000
    }
    return config
  }

  removePending(key: string, isRequest = false) {
    if (this.pending[key] && isRequest) {
      this.pending[key](&#39;取消重复请求&#39;)
    }
    delete this.pending[key]
  }

  // 设定拦截器
  interceptors(instance: AxiosInstance) {
    instance.interceptors.request.use(
      config => {
        console.log(&#39;config :>> &#39;, config)
        let isPublic = false
        publicConfig.publicPath.map(path => {
          isPublic = isPublic || path.test(config.url || &#39;&#39;)
        })
        const token = Taro.getStorageSync(&#39;token&#39;)
        if (!isPublic && token) {
          config.headers.Authorization = &#39;Bearer &#39; + token
        }
        const key = config.url + &#39;&&#39; + config.method
        this.removePending(key, true)
        config.cancelToken = new CancelToken(c => {
          this.pending[key] = c
        })
        return config
      },
      err => {
        errorHandle(err)
        return Promise.reject(err)
      }
    )

    // 响应请求的拦截器
    instance.interceptors.response.use(
      res => {
        const key = res.config.url + &#39;&&#39; + 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)
      }
    )
  }

  // 创建实例
  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: &#39;get&#39;,
        url: url
      },
      config
    )
    return this.request(options)
  }

  post(url: string, data?: unknown): Promise<AxiosResponse> | Promise<HttpResponse> {
    return this.request({
      method: &#39;post&#39;,
      url: url,
      data: data
    })
  }
}

export default HttpRequest

request.ts

import HttpRequest from &#39;./http&#39;
import config from &#39;@/config/index&#39;
const baseUrl = process.env.NODE_ENV === &#39;development&#39; ? config.baseUrl.dev : config.baseUrl.pro

const request = new HttpRequest(baseUrl)

export default request

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

apis/book.ts

import request from &#39;../request&#39;

export function getBookList() {
  return request.get(&#39;books/getBookList&#39;)
}

export function getBookDetail(id: number) {
  return request.post(&#39;books/getBookDetail&#39;, {
    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: &#39; &#39;;
  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*=&#39;van-hairline&#39;] {
  &::after {
    @include hairline();
  }
}

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

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

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

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

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

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

  &--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 使用,有一些配置细节本文无法一一列举,就在项目中去发掘吧!

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

【相关学习推荐:小程序开发教程

위 내용은 Taro + Vue3를 사용하여 작은 프로그램을 개발하는 방법은 무엇입니까? (관행)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 juejin.cn에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제