banner
xingli

xingli

猫娘爱好者

uniapp integrates viewPlus vue3

The Most Complete and Detailed Steps to Set Up a Project with uniapp+vue3+vite+ts+uview-plus#

Preparation for setting up the project:

Create a uni-app project using the vue-cli scaffolding for better compatibility with TS syntax.

Node version: v18.16.0

pnpm version: 8.3.0

Install uni-app development plugins in vscode:

  • uni-create-view: Quickly create uni-app pages;
  • uni-helper: Code suggestions for uni-app, including 5 mini-program extension packages;

1. Create a uni-app Project#

The main method is to create a uni-app project using vue-cli scaffolding for better compatibility with TS syntax, using the Vue3/Vite version:

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

Note:

  • The Vue3/Vite version requires node version ^14.18.0 || >=16.0.0
  • If the command line creation fails, please directly visit gitee to download the template.

For more installation processes and precautions, you can refer to the official website: uni-app Official Website

2. Compile and Run the uni-app Project#

Install dependencies pnpm install

2. Run the project pnpm dev:mp-weixin

When running the project, you can open the package.json file and check the command to run the project in the scripts configuration. If you are running a WeChat mini-program, use pnpm dev:mp-weixin, and for packaging, use pnpm build:mp-weixin. You can also configure a shortcut startup command, such as "serve": "pnpm dev:mp-weixin".

After running the project, a dist folder will be generated in the directory, and the mp-weixin file in the dev folder is used for running the compiled files.

3. Import into WeChat Developer Tools

After running the project, follow the prompt to run: open WeChat Developer Tools, import dist\dev\mp-weixin to run, and you can successfully run and compile the project in WeChat Developer Tools.

3. TS Type Checking#

Open the project structure, and you will find an error prompt in tsconfig.json:

Option 'importsNotUsedAsValues' is deprecated and will stop functioning in TypeScript 5.5. Specify compilerOption '"ignoreDeprecations": "5.0"' to silence this error.
  Use 'verbatimModuleSyntax' instead.ts

Description: The warning message is related to the deprecation of the TypeScript compiler option importsNotUsedAsValues and suggests using the verbatimModuleSyntax option instead. To silence the error message before TypeScript 5.5, you can add "ignoreDeprecations": "5.0" to the compiler options.

Solution: You can add "ignoreDeprecations": "5.0" in the "compilerOptions" configuration item in the tsconfig.json file.

  "compilerOptions": {
    "ignoreDeprecations": "5.0"
  },

At this point, when we open the vue file, we can write some components, such as:

<image mode="xxx"></image>

It is evident that the mode attribute in the image built-in component does not have the property value "xxx", but there is no error prompt in the code. Therefore, to comply with TS checking, we need to configure TS type checking additionally:

1. Install type declaration files:

npm i -D @types/wechat-miniprogram @uni-helper/uni-app-types

2. Configure tsconfig.json:

// tsconfig.json
{
  "extends": "@vue/tsconfig/tsconfig.json",
  "compilerOptions": {
    "ignoreDeprecations": "5.0",
    "sourceMap": true,
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    },
    "lib": ["esnext","dom"],
    "types": [
      "@dcloudio/types", // uni-app API types
      "miniprogram-api-typings", // Native WeChat mini-program types
      "@uni-helper/uni-app-types" // uni-app component types
    ]
  },
  // Vue compiler types, check tag types
  "vueCompilerOptions": {
    "nativeTags": ["block","component","template","slot"],
  },
  "include": ["src/**/*.ts","src/**/*.d.ts","src/**/*.tsx","src/**/*.vue"]
}

After the configuration is complete, the previous vue component will prompt error messages, and there may be a red wavy line displayed under the image component; or it may not.

4. JSON Comment Issues#

In the manifest.json and pages.json files, we often add some comment information, but the JSON specification does not support adding comments in the file, which will be regarded as invalid tokens and lead to parsing errors.

At this point, we can configure it in the vscode workspace:

In the vscode panel, click the settings button in the lower right corner → click settings → search for "file associations" in the settings → find the configuration item for Files: Associations → click to add items → set manifest.json and pages.json to jsonc.

5. Install uview-plus#

The UI framework we use is uview-plus, which is based on uView2.0 with initial modifications, supporting Vue3 syntax, and has a rich set of components. Here we will briefly introduce the installation and configuration steps. For detailed steps, please refer to the official website: uview-plus 3.0 - Fully Compatible with nvue's uni-app Ecosystem Framework - uni-app UI Framework

1. Install

npm install uview-plus
npm install dayjs
npm install clipboard

Note: This installation method must follow the configuration instructions in npm installation configuration, and the project name cannot contain Chinese characters.

Since uview-plus depends on SCSS, this plugin must be installed; otherwise, it will not run properly.

// Install sass
npm install sass -D 
// Install sass-loader, note that version 10 is required; otherwise, it may cause compatibility issues between vue and sass and throw errors
npm install sass-loader@10 -D

2. Configuration Steps

Import the main JS library of uview-plus: In the main.ts file in the project's src directory, import and use the JS library of uview-plus. Note that these two lines should be placed after const app = createSSRApp(App).

// main.ts
import uviewPlus from 'uview-plus'
import App from './App.vue'
// #ifdef VUE3
import { createSSRApp } from 'vue'
export function createApp() {
  const app = createSSRApp(App)
  app.use(uviewPlus)
  return {
    app
  }
}
// #endif

Import the global SCSS theme file of uview-plus: In the uni.scss file in the project root directory, import this file.

/* uni.scss */
@import 'uview-plus/theme.scss';

Remember to delete other CSS files.

Import the basic styles of uview-plus: In the first line of App.vue, import it, and remember to add the lang="scss" attribute to the style tag.

// App.vue
<style lang="scss">
	/* Note to write in the first line and add lang="scss" attribute to the style tag */
	@import "uview-plus/index.scss";
</style>

Configure easycom component mode: This needs to be done in the pages.json file in the project's src directory.

// pages.json
{
	"easycom": {
		// Note that it must be placed in custom; otherwise, it will be invalid, https://ask.dcloud.net.cn/question/131175
		"custom": {
			"^u--(.*)": "uview-plus/components/u-$1/u-$1.vue",
			"^up-(.*)": "uview-plus/components/u-$1/u-$1.vue",
	        "^u-([^-].*)": "uview-plus/components/u-$1/u-$1.vue"
		}
	},
	
	// This is the existing content
	"pages": [
		// ......
	]
}

Note:

After the configuration, you may find that there is a TS error prompt when importing uview-plus in main.ts: cannot find module declaration file for "uview-plus".

You can create a types folder in the src directory specifically for storing TS type declaration files, and create a uview.d.ts file in it with the following declaration code:

declare module "uview-plus"

3. Usage

After downloading and configuring, you can directly use components on a page without importing them.

<u-button text="Submit"></u-button>

6. Configure Pinia Persistence#

The state management library used in vue3+vite is pinia. Official website: Pinia Chinese Documentation

1. Install pinia: If using HBuilder X, no manual installation is needed; just use it directly. If using CLI, manual installation is required:

  1. Usage:
//main.ts
 
import { createSSRApp } from 'vue';
import * as Pinia from 'pinia';
 
export function createApp() {
	const app = createSSRApp(App);
	app.use(Pinia.createPinia());
	return {
		app,
		Pinia, // Pinia must be returned here
	};
}

Create a Store folder counter.ts

// stores/counter.js
import { defineStore } from 'pinia';
 
export const useCounterStore = defineStore('counter', {
	state: () => {
		return { count: 0 };
	},
	// You can also define it this way
	// state: () => ({ count: 0 })
	actions: {
		increment() {
			this.count++;
		},
	},
});

Use it in a component:

<script setup>
import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
counter.count++
// Auto-completion! ✨
counter.$patch({ count: counter.count + 1 })
// Or use action instead
counter.increment()
</script>
<template>
  <!-- Directly access state from store -->
  <div>Current Count: {{ counter.count }}</div>
</template>

Note: Pinia, like Vuex, has the drawback that data will be lost after refreshing the page. Therefore, information such as login tokens will be saved in both the store and local storage to achieve persistent storage.

Here we use the plugin Quick Start | pinia-plugin-persistedstate to implement persistent storage.

1. Install the plugin

pnpm i pinia-plugin-persistedstate

2. Add the plugin to the pinia instance

import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
 
const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)

3. Usage

When creating a Store, set the persist option to true

import { defineStore } from 'pinia'
 
export const useStore = defineStore(
  'main',
  () => {
    const someState = ref('Hello pinia')
    return { someState }
  },
  {
    persist: true,
  },
)

4. Multi-end Compatibility

export const useMemberStore = defineStore(
  'main',
  () => {
    //…omitted
  },
  {
    // Configure persistence
    persist: {
      // Adjust to be compatible with multi-end APIs
      storage: {
        setItem(key, value) {
          uni.setStorageSync(key, value) 
        },
        getItem(key) {
          return uni.getStorageSync(key) 
        },
      },
    },
  },
)

7. Encapsulate HTTP Requests#

To facilitate axios data requests, you can encapsulate the mini-program data requests as Promise request functions.

1. Request and Upload File Interceptors

uniapp Interceptors: uni.addInterceptor

// src/utils/http.ts
 
// Base request address
const baseURL = 'xxxx'
 
// Interceptor configuration
const httpInterceptor = {
  // Triggered before interception
  invoke(options: UniApp.RequestOptions) {
    // 1. If not starting with http, concatenate the address
    if (!options.url.startsWith('http')) {
      options.url = baseURL + options.url
    }
    // 2. Request timeout
    options.timeout = 10000
    // 3. Add mini-program request header identifier
    options.header = {
      'source-client': 'miniapp',
      ...options.header,
    }
    // 4. Add token request header identifier
    const memberStore = useMemberStore()
    const token = memberStore.profile?.token
    if (token) {
      options.header.Authorization = token
    }
  },
}
 
// Intercept request requests
uni.addInterceptor('request', httpInterceptor)
// Intercept uploadFile file uploads
uni.addInterceptor('uploadFile', httpInterceptor)

Note: For WeChat mini-programs, you need to log in to the WeChat Official Platform to configure valid domain names.

2. Encapsulate Promise Request Function

Requirement: Return a Promise object to handle return value types, successfully extract data through resolve and add generics, and capture errors through reject in case of failure.

/**
 * Request function
 * @param  UniApp.RequestOptions
 * @returns Promise
 *  1. Returns a Promise object for handling return value types
 *  2. Successfully obtaining data
 *    2.1 Extract core data res.data
 *    2.2 Add types, supporting generics
 *  3. Failed to obtain data
 *    3.1 401 error  -> Clear user information and redirect to login page
 *    3.2 Other errors -> Provide light prompts based on backend error information
 *    3.3 Network errors -> Prompt users to change networks
 */
type Data<T> = {
  code: string
  msg: string
  result: T
}
// 2.2 Add types, supporting generics
export const http = <T>(options: UniApp.RequestOptions) => {
  // 1. Return Promise object
  return new Promise<Data<T>>((resolve, reject) => {
    uni.request({
      ...options,
      // Response success
      success(res) {
        // Status code 2xx, refer to axios design
        if (res.statusCode >= 200 && res.statusCode < 300) {
          // 2.1 Extract core data res.data
          resolve(res.data as Data<T>)
        } else if (res.statusCode === 401) {
          // 401 error  -> Clear user information and redirect to login page
          const memberStore = useMemberStore()
          memberStore.clearProfile()
          uni.navigateTo({ url: '/pages/login/login' })
          reject(res)
        } else {
          // Other errors -> Provide light prompts based on backend error information
          uni.showToast({
            icon: 'none',
            title: (res.data as Data<T>).msg || 'Request error',
          })
          reject(res)
        }
      },
      // Response failure
      fail(err) {
        uni.showToast({
          icon: 'none',
          title: 'Network error, try changing the network',
        })
        reject(err)
      },
    })
  })
}

8. Other Configurations#

1. Automatic On-Demand Import in Vue3:

Using methods in Vue3 such as 'ref' requires manual imports, which can be cumbersome. Here we use the plugin unplugin-auto-import to achieve automatic on-demand imports. Official website: unplugin-auto-import - npm

Installation:

npm i unplugin-auto-import -save

Add configuration in the vue.config.js file:

//vite.config.ts
 
import { defineConfig } from 'vite'
import uni from '@dcloudio/vite-plugin-uni'
import AutoImport from 'unplugin-auto-import/vite'
 
// https://vitejs.dev/config/
export default defineConfig({
  build: {
    sourcemap: process.env.NODE_ENV === 'development',
  },
  plugins: [
    uni(),
    AutoImport({ // Use
      imports: ['vue'],
      dts: 'src/auto-import.d.ts',
      // If using eslint, remember to add this; if not, it can be ignored
      eslintrc: {
        enabled: true,
      },
    })
  ],
})

Configuration for eslintrc.js file (only configure if using eslint):

//.eslintrc.js
  extends: [
    'plugin:vue/vue3-essential',
    'eslint:recommended',
    '@vue/eslint-config-typescript',
    '@vue/eslint-config-prettier',
    'plugin:prettier/recommended', // Add prettier plugin,
  ],

After completing the configuration, restart the project!


During the project configuration process, you can refer to the Bilibili website: Day1-01-uni-app Little Rabbit Fresh Introduction Video_哔哩哔哩_bilibili

All experts are welcome to discuss and provide suggestions for additions...

Source

Other Dependencies#

npm install miniprogram-api-typings --save-dev

If vscode reports related errors, install this package.

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.