uniapp+vue3 setup+ts 开发小程序实战(起始篇)-灵析社区

前端码农


前言

如今,小程序已经成了日常生活不可缺少的应用之一,掌握小程序开发对于前端来说,几乎是一个必备的技能。由于原生小程序语法开发体验差,缺乏生态插件等原因,已经诞生过许多第三方框架,如uniapp、taro、wepy、mpvue等,而随着时间的推移,uniapp及taro框架就如同现在vue及react两个主流前端框架一样,被大多数小程序开发者采用。

对于使用vue技术栈的同学来说,想必都知道vue3已经如火如荼,vue主流生态都在“争先恐后”升级至vue3版本,而作为vue语法开发小程序的uniapp框架,也早已经跟上这波潮流,推出了vue3 + vite + setup + typescript开发小程序版本,不论在开发体验还是性能上,都带来了质的飞跃。(详见官方社区文章《vue3和vite双向加持,uni-app性能再次提升》)

“新事物的诞生往往意味着新的开始”,在vue3 + vite + setup + typescript的未来趋势下,意味着我们需要对以前vue2版本学习的经验知识也要跟着做一番迭代,甚至推翻重来。

接下来将从初始化代码项目开始,一步步带你基于uniapp + vue3 + vite + setup + typescript去搭建初始化一个小程序项目,在这过程中会引导你思考如何去做封装优化相关API方法等。举个例子,路由跳转微信官方API写法如下:

wx.navigateTo({
  url: '/pages/index/test?id=1',
})

这种写法平时写个demo倒还好,但在真实项目中涉及众多页面跳转,每次跳转都要写这么长的一段代码,这种体验是很差的。在路由封装模块章节中,经过封装的后的写法如下:

router.navigate('index', {id: 1})

这么一对比是不是一下子清爽很多了呢?

你需要准备的前置知识

  1. 请确保你已经学习过微信小程序基础知识,常见api和uniapp基础知识
  2. 了解vue3基础知识,composition setup写法
  3. 掌握typescript基础知识

项目初始化

全局安装vue-cli

npm install -g @vue/cli@4

初始化代码

npx degit dcloudio/uni-preset-vue#vite-ts my-vue3-project

(如命令行创建失败,请直接访问 gitee下载模板)

安装vscode插件

使用script setup语法,需要配合volar插件使用,在vscode插件中搜索volar:

然后选择Vue Volar extension Pack插件(该插件包含了vue3项目常用到的各种插件)。至此,我们的准备工作就算完成了!

代码基建设置

初始化项目的代码,还非常的简陋,此时我们不能急着立刻上手写业务代码,而是要先完成“基建”工作,只有基建搭好了,才方便后续项目代码的开发和维护。这些基建工作包括诸如:设置统一代码风格规范,路径别名,样式管理等,接下来就开始一步步实现。

设置统一代码风格

正所谓“无规矩不成方圆”,一个好的项目代码,必定是有着一定的代码规范约束。目前主流方案是使用Eslint + Prettier进行设置。

安装Eslint 依赖

在终端中输入:

npm i @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint eslint-config-prettier eslint-plugin-import eslint-plugin-prettier eslint-plugin-vue vue-eslint-parser -D

安装完依赖后,我们在根目录下新建.eslintrc.js文件,内容如下:

module.exports = {
  root: true,
  env: {
    browser: true,
    node: true,
    es6: true,
  },
  parser: 'vue-eslint-parser',
  parserOptions: {
    parser: '@typescript-eslint/parser',
    ecmaVersion: 2020,
    sourceType: 'module',
    jsxPragma: 'React',
    ecmaFeatures: {
      jsx: true,
      tsx: true,
    },
  },
  plugins: ['@typescript-eslint', 'prettier', 'import'],
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:vue/vue3-recommended',
    'prettier',
  ],
  overrides: [
    {
      files: ['*.ts', '*.tsx', '*.vue'],
      rules: {
        'no-undef': 'off',
      },
    },
  ],
  rules: {
    'no-restricted-syntax': ['error', 'LabeledStatement', 'WithStatement'],
    camelcase: ['error', { properties: 'never' }],
    'no-var': 'error',
    'no-empty': ['error', { allowEmptyCatch: true }],
    'no-void': 'error',
    'prefer-const': [
      'warn',
      { destructuring: 'all', ignoreReadBeforeAssign: true },
    ],
    'prefer-template': 'error',
    'object-shorthand': [
      'error',
      'always',
      { ignoreConstructors: false, avoidQuotes: true },
    ],
    'block-scoped-var': 'error',
    'no-constant-condition': ['error', { checkLoops: false }],
    'no-redeclare': 'off',
    '@typescript-eslint/no-redeclare': 'error',
    '@typescript-eslint/ban-ts-comment': 'off',
    '@typescript-eslint/ban-types': 'off',
    '@typescript-eslint/explicit-module-boundary-types': 'off',
    '@typescript-eslint/no-empty-function': 'off',
    '@typescript-eslint/no-explicit-any': 'off',
    '@typescript-eslint/no-non-null-assertion': 'off',
    '@typescript-eslint/no-non-null-asserted-optional-chain': 'off',
    '@typescript-eslint/no-var-requires': 'off',
    '@typescript-eslint/no-unused-vars': [
      'error',
      {
        argsIgnorePattern: '^_',
        varsIgnorePattern: '^_',
      },
    ],
    'no-unused-vars': [
      'error',
      {
        argsIgnorePattern: '^_',
        varsIgnorePattern: '^_',
      },
    ],

    // vue
    'vue/no-v-html': 'off',
    'vue/require-default-prop': 'off',
    'vue/require-explicit-emits': 'off',
    'vue/multi-word-component-names': 'off',

    // prettier
    'prettier/prettier': 'error',

    // import
    'import/first': 'error',
    'import/no-duplicates': 'error',
    'import/order': [
      'error',
      {
        groups: [
          'builtin',
          'external',
          'internal',
          'parent',
          'sibling',
          'index',
          'object',
          'type',
        ],
        pathGroupsExcludedImportTypes: ['type'],
      },
    ],
  },
}

新建.eslintignore文件

创建ESLint忽略文件配置 .eslintignore,来指定我们不需要进行检查的目录或文件

node_modules
dist
*.md
*.woff
*.ttf
.vscode
.idea

新建.prettierrc文件

{
  "semi": false,
  "tabWidth": 2,
  "trailingComma": "all",
  "singleQuote": true,
  "endOfLine": "auto"
}

新建.prettierignore文件

**/*.svg
**/*.ico
package.json
package-lock.json
/dist
.DS_Store
.eslintignore
*.png
.editorconfig
.gitignore
.prettierignore
.eslintcache
*.lock
yarn-error.log
**/node_modules/**

vscode安装eslint跟prettier插件

路径别名设置

修改vite.config.ts,这里我们先设置两个别名,一个是针对src下代码文件,一个是针对图片静态文件,内容如下:

import path from 'path'
import { defineConfig } from 'vite'
import uni from '@dcloudio/vite-plugin-uni'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [uni()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src'),
      '@img': path.resolve(__dirname, 'src/static/images'),
    },
  },
})

接着我们在.vue文件的template中可以这么写:

<image class="logo" src="@img/logo.jpg" />

假设我们要引入src -> router -> index.ts文件,在script里面这么写:

可以看到,此时ts会报找不到模块的错误提示,此时我们需要在tsconfig.json文件做相关修改:

在compilerOptions下添加

 "paths": {
      "@/*": ["src/*"]
    }

即可。

样式管理

css预处理比较成熟的有sass,less,stylus,大家可以根据自己选择对应的css预处理器。这里以sass为例:

先安装相关依赖

npm i sass sass-loader -D

接着在src目录下创建styles文件夹,存放样式相关文件。

新建vars.scss文件:管理颜色变量

例如:

$font-size: 28rpx;

$primary-color: #54d339;

新建mixins.scss文件(以下示例供参考)

例如

@mixin flex-row {
  display: flex;
  align-items: center;
}

@mixin flex-column {
  display: flex;
  flex-direction: column;
}

// 文字超出隐藏
@mixin text-eli {
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-box-orient: vertical;
}

新建common.scss:全局公共样式(以下示例供参考)

@import "./vars.scss";
@import "./mixins.scss";

page {
  box-sizing: border-box;
  font-size: $font-size;
}

view,
text {
  font-size: $font-size;
  box-sizing: border-box;
  color: #333;
}
// 去除按钮默认边框
button::after {
  border: none;
}

.flex-row {
  @include flex-row();
}

.flex-row-between {
  @include flex-row();
  justify-content: space-between;
}

.flex-row-around {
  @include flex-row();
  justify-content: space-around;
}

.flex-row-center {
  @include flex-row();
  justify-content: center;
}

.flex-row-end {
  @include flex-row();
  justify-content: flex-end;
}

.flex-column {
  @include flex-column();
}

.flex-column-center {
  @include flex-column();
  align-items: center;
  justify-content: center;
}

.flex1 {
  flex: 1;
  height: 100%;
}

.text-line1 {
  @include text-eli();
  -webkit-line-clamp: 1;
}

.text-line2 {
  @include text-eli();
  -webkit-line-clamp: 2;
}

/* 间隔相关 */
.pad20 {
  padding: 20rpx;
}
.mb32 {
  margin-bottom: 32rpx;
}
.mb40 {
  margin-bottom: 40rpx;
}
.mt60 {
  margin-top: 60rpx;
}
.ml20 {
  margin-left: 20rpx;
}
.ml40 {
  margin-left: 40rpx;
}

/* 字体大小相关 */

.font24 {
  font-size: 24rpx;
}

.font48 {
  font-size: 48rpx;
}
.font36 {
  font-size: 36rpx;
}
.font32 {
  font-size: 32rpx;
}
.font-bold {
  font-weight: bold;
}
.text-center {
  text-align: center;
}

.text-white {
  color: #fff;
}
.text-color-main {
  color: $main;
}
.text-color-6 {
  color: #666;
}
.text-color-9 {
  color: #999;
}
.bg-white {
  background-color: #fff;
}
.bg-gray {
  background-color: $bg-gray;
}

App.vue文件中引入

<style lang="scss">
/*全局公共样式 */
@import "./styles/common.scss";
</style>

配置自动导入颜色变量

我们在vars.scss文件中定义的颜色变量,在页面中使用时,需要手动导入才能使用。那要怎么实现自动导入呢?
我们可以在vite.config.js中配置即可:
在return对象下新增:

css: {
      preprocessorOptions: {
        scss: {
          additionalData: `@import "@/styles/vars.scss";`,
        },
      },
    }

这样我们在页面中就可以直接使用vars中定义的颜色变量了。此时还没完,我们还可以借助一个插件帮助我们识别定义的变量: SCSS IntelliSense

在vscode中安装该插件后,如下图可以看到已经给出提示,开发体验又上升了一个台阶!

自动导入vue方法

vue3 script setup 写法中,组件间通信有defineProps跟defineEmits这种编译器宏方法,无需导入就可以直接使用。而对于vue当中导出的代码,我们还是需要手动显示引入,如下:

import { computed, ref } from 'vue'
const count = ref(0)

那有没有办法像defineProps等编译器宏方法一样,无需手动导入就可以直接使用呢?对此,我们可以使用unplugin-auto-import npm包实现。

安装依赖包

npm i -D unplugin-auto-import

vite.config.ts中引入

import AutoImport from 'unplugin-auto-import/vite'


 plugins: [
      uni(),
      AutoImport({
        imports: ['vue', 'uni-app'],
        dts: './auto-imports.d.ts', // 安装好依赖后,重新运行编译即可自动在根目录下生成此声明文件
      }),
    ]

tsconfig.ts中引入声明文件

接着我们需要在tsconfig.ts文件include属性中引入声明文件,否则直接使用ts会报错。

"include": [
    "src/**/*.ts",
    "src/**/*.d.ts",
    "src/**/*.vue",
    "auto-imports.d.ts"
  ]

接着我们就可以直接在代码中无需导入直接使用vue中方法了:

// import { computed, ref } from 'vue' 这行代码不用写了
const count = ref(0)

总结

至此,我们已经完成了项目代码初始化及基建工作(代码风格统一,样式管理,路由别名设置),并通过一些插件提升代码开发体验。当然这只是起始篇,接下来更有趣的请移步《状态管理篇》。


阅读量:2036

点赞量:0

收藏量:0