1.创建项目

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

命令最后空格加 项目名

创建可能会出现报错情况


uniapp中AES加密_前端框架



这种直接到gitee 下载源码就行

TS 类型校验

  • 安装 类型声明文件
npm i -D miniprogram-api-typings @uni-helper/uni-app-types
  • 配置 tsconfig.json 参考
// tsconfig.json
{
  "extends": "@vue/tsconfig/tsconfig.json",
  "compilerOptions": {
    "sourceMap": true,
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    },
    "lib": ["esnext", "dom"],
    // 类型声明文件
    "types": [
      "@dcloudio/types", // uni-app API 类型
      "miniprogram-api-typings", // 原生微信小程序类型
      "@uni-helper/uni-app-types" // uni-app 组件类型
    ]
  },
  // vue 编译器类型,校验标签类型
  "vueCompilerOptions": {
    // 原配置 `experimentalRuntimeMode` 现调整为 `nativeTags`
    "nativeTags": ["block", "component", "template", "slot"], 
    "experimentalRuntimeMode": "runtime-uni-app" 
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
}

打开代码会发现 manifest.json 和 pages.json 会出现报错 原因是不能有注释
解决办法: 在 settings.json 中 添加以下代码

"files.associations": {

    "pages.json": "jsonc",

    "manifest.json": "jsonc",

  },

uniapp中AES加密_前端框架_02

2. ui组件库(vant-ui)引用(官网)

安装vant4

组件按需引入配置
1.安装插件

# 通过 npm 安装
npm i @vant/auto-import-resolver unplugin-vue-components -D

# 通过 yarn 安装
yarn add @vant/auto-import-resolver unplugin-vue-components -D

# 通过 pnpm 安装
pnpm add @vant/auto-import-resolver unplugin-vue-components -D

# 通过 bun 安装
bun add @vant/auto-import-resolver unplugin-vue-components -D

2.配置插件
如果是基于 vite 的项目,在 vite.config.js 文件中配置插件:

import vue from '@vitejs/plugin-vue';
import Components from 'unplugin-vue-components/vite';
import { VantResolver } from '@vant/auto-import-resolver';

export default {
  plugins: [
    vue(),
    Components({
      resolvers: [VantResolver()],
    }),
  ],
};

如果是基于 vue-cli 的项目,在 vue.config.js 文件中配置插件:

const { VantResolver } = require('@vant/auto-import-resolver');
const ComponentsPlugin = require('unplugin-vue-components/webpack');

module.exports = {
  configureWebpack: {
    plugins: [
      ComponentsPlugin({
        resolvers: [VantResolver()],
      }),
    ],
  },
};

如果是基于 webpack 的项目,在 webpack.config.js 文件中配置插件:

const { VantResolver } = require('@vant/auto-import-resolver');
const ComponentsPlugin = require('unplugin-vue-components/webpack');

module.exports = {
  plugins: [
    ComponentsPlugin({
      resolvers: [VantResolver()],
    }),
  ],
};

3.使用组件

<template>
   <van-button type="primary" >按钮 </van-button>
</template>

有vant4 效果说明成功

3. Pinia 持久化 (官网)

使用方法

  • List itemdefineStore( ) 方法的第一个参数:相当于为容器起一个名字。注意:这里的名字必须唯一,不能重复。
  • defineStore( ) 方法的第二个参数:可以简单理解为一个配置对象,里边是对容器仓库的配置说明。当然这种说明是以对象的形式。
  • state 属性: 用来存储全局的状态的,这里边定义的,就可以是为SPA里全局的状态了。
  • getters属性: 用来监视或者说是计算状态的变化的,有缓存的功能。
  • actions属性: 对state里数据变化的业务逻辑,需求不同,编写逻辑不同。说白了就是修改state全局状态数据的。
import { defineStore } from 'pinia'

export const mainStore = defineStore("名称(唯一)", {
    state:() => { 
        return {
        } 
    },
    getters: {

    },
    actions: {

    }
})

1.安装

npm i pinia

2.配置mian.ts

import { createPinia } from 'pinia'

  app.use(createPinia())

3.在src中创建stores 文件夹 和index.ts

import useMemberStore from './modules/user'
 
export default function useStore() {
  return {
    user: useMemberStore(),
  }
}

4.在stores中创建modules文件夹 创建user.ts

import { defineStore } from 'pinia'
import { ref } from 'vue'

// 定义 Store
 const useMemberStore = defineStore(
  'user',
  () => {
    // 用户信息
    const userfile = ref<any>()
    // 保存用户信息,登录时使用
    const setProfile = (val: any) => {
        userfile.value = val
    }
    // 清理用户信息,退出时使用
    const clearProfile = () => {
        userfile.value = undefined
    }
    // 记得 return
    return {
        userfile,
      setProfile,
      clearProfile,
    }
  }
)

export default useMemberStore

遇到问题:

uniapp中AES加密_uniapp中AES加密_03

这种情况需要pinia 降级 降为:2.0.36 有效 vue 版本:3.3.4

测试:

4.Router(插件说明)路由配置

1.安装(需要跨平台可以用uni-app自带路由或者安装router跨平台插件,这里只做H5配置)

npm install uni-mini-router --save

npm install uni-parse-pages --save

2.配置
项目src目录下(HbuilderX创建的项目可以在根目录下)创建router文件夹,并在该文件夹创建index.ts

//index.ts
import { createRouter } from 'uni-mini-router'
// 导入pages.json
import pagesJson from '../pages.json'
// 引入uni-parse-pages
import pagesJsonToRoutes from 'uni-parse-pages'
// 生成路由表
const routes = pagesJsonToRoutes(pagesJson)
const router = createRouter({
  routes: [...routes] // 路由表信息
})
export default router

配置main.ts

import { createSSRApp } from "vue";
import pinia from './stores'
import App from "./App.vue";
import router from './router'  

export function createApp() {
  const app = createSSRApp(App);
  app.use(pinia)
  app.use(router)  
  return {
    app,
  };
}

配置pages.json

{
  "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
    {
      "path": "pages/index/index",
      "name": "home",
      "style": {
        "navigationBarTitleText": "首页",
        "navigationBarBackgroundColor": "#E7F0FF"
      }
    },
    {
      "path": "pages/login/login",
      "name": "login",
      "style": {
        "navigationBarTitleText": "登录",
        "navigationBarBackgroundColor": "#E7F0FF"
      }
    },
    {
      "path": "pages/mine/mine",
      "name": "mine",
      "style": {
        "navigationBarTitleText": "",
        "navigationBarBackgroundColor": "#E7F0FF"
      }
    }
  ],
  "tabBar": {
    "color": "#333",
    "selectedColor": "#27ba9b",
    "backgroundColor": "#fff",
    "borderStyle": "white",
    "list": [
      {
        "pagePath": "pages/index/index",
        "iconPath": "static/tabs/home_default.png",
        "selectedIconPath": "static/tabs/home_selected.png",
        "text": "首页"
      },
      {
        "pagePath": "pages/mine/mine",
        "iconPath": "static/tabs/user_default.png",
        "selectedIconPath": "static/tabs/user_selected.png",
        "text": "我的"
      }
    ]
  },
  "globalStyle": {
    "navigationBarTextStyle": "black",
    "navigationBarTitleText": "",
    "navigationBarBackgroundColor": "#F8F8F8",
    "backgroundColor": "#F8F8F8"
  }
}

页面测试:

// pages/index/index.vue

<template>
<van-button type="primary" @click="login"> 登录按钮 </van-button>
</template>

<script setup lang="ts">
import router from '@/router'

const login = () => {
  router.replaceAll({ name: 'mine' })
}

uniapp中AES加密_前端框架_04


uniapp中AES加密_vue.js_05

显示mine 则成功

5.axios(官网)请求封装

1.axios 安装

npm install axios

2.在src文件夹下创建utils文件夹, utils文件夹下创建http.ts

// http.ts
import axios from 'axios'

    const instance = axios.create({
      baseURL :'http://localhost:5173/src/styles',
      timeout :60000
    })

    instance.interceptors.request.use(
      (request) => {
        return request
      },
      (error) => {
        return Promise.reject(error)
      }
    )

    instance.interceptors.response.use(
      (response) => {
        return response.data
      },
      (error) => {
        return Promise.reject(error)
      }
    )
    
export default instance

3.在src/styles下 创建虚拟text.json数据

{
    "code":"200",
    "message":"请求成功",
    "lists":[
    {
        "date": "2016-05-02",
        "name": "王小虎",
        "address": "上海市普陀区金沙江路 1518 弄",
        "token":"bug666"
    }
]
}

4.在src文件夹下创建api ,创建login.ts

import request from '@/utils/http'

export function text(data:any){
    return request({
        //访问到styles下的text.json文件
        url:'/text.json',
        method:'post',
        data
    })
}

5.在pages/index/index.vue 中 写入测试接口测试是否成功响应

<template>
  <van-button type="primary" @click="login"> 登录按钮 </van-button>
</template>

<script setup lang="ts">
import { text } from "@/api/login"

//login()
const login = () => {

  text('').then((res: any) => {
    console.log(res);
  });

};

</script>

<style>

</style>

点击按钮 出现如图则成功

uniapp中AES加密_uni-app_06

6.Eslint(官网)

1.安装

uniapp中AES加密_前端框架_07

npm i eslint -D
npm i eslint-plugin-vue -D

2.在根目录创建.eslintrc.js

module.exports = {
    //此项是用来告诉eslint找当前配置文件不能往父级查找
    root: true,
    //指定eslint继承的模板
    extends: ["plugin:vue/essential", "@vue/standard"],
    //此项指定环境的全局变量,下面的配置指定为浏览器环境
    env: {
      browser: true
    },
    // 此项是用来提供插件的,插件名称省略了eslint-plugin-,下面这个配置是用来规范html的
    plugins: ["vue"],
    //指定javaScript语言类型和风格
    parserOptions: {
      parser: "babel-eslint"
    },
    //规则https://www.wenjiangs.com/docs/eslint,vue规则:https://eslint.vuejs.org/rules/
    // 主要有如下的设置规则,可以设置字符串也可以设置数字,两者效果一致
    // "off" -> 0 关闭规则
    // "warn" -> 1 开启警告规则
    //"error" -> 2 开启错误规则
    rules: {
      // 使用 === 替代 == allow-null允许null和undefined== [2, "allow-null"]
      eqeqeq: 0,
      // 双峰驼命名格式
      camelcase: 0,
      //要求或者禁止Yoda条件
      yoda: 2,
      // 行尾不使用分号
      semi: 0,
      //强制一致地使用反引号、双引号或单引号。
      quotes: 2,
      //强制函数中的变量在一起声明或分开声明
      "one-var": 2,
      // 禁用 console
      "no-console": process.env.NODE_ENV === "production" ? "error" : "off",
      // 强制 generator 函数中 * 号周围使用一致的空格
      "generator-star-spacing": "off",
      // 禁用 debugger
      "no-debugger": process.env.NODE_ENV === "production" ? "error" : "off",
      // 禁止对象字面量中出现重复的 key
      "no-dupe-keys": 2,
      // 函数参数不能重复
      "no-dupe-args": 2,
      // 禁止重复的函数声明
      "no-func-assign": 2,
      // 禁止重复的 case 标签
      "no-duplicate-case": 2,
      // 禁用未声明的变量
      "no-undef": 1,
      //禁止出现多个空格
      "no-multi-spaces": 2,
      // 不允许标签与变量同名
      "no-label-var": 2,
      //禁止tab
      "no-tabs": 1,
      // 禁止 var 声明 与外层作用域的变量同名
      "no-shadow": 0,
      // 禁止 if 语句中有 return 之后有 else
      "no-else-return": 0,
      // 禁止出现空函数.如果一个函数包含了一条注释,它将不会被认为有问题。
      "no-empty-function": 1,
      // 禁止出现未使用过的变量
      "no-unused-vars": 1,
      //禁止在返回语句中赋值
      "no-return-assign": 0,
      // 禁用行尾空格
      "no-trailing-spaces": 2,
      // 禁止修改 const 声明的变量
      "no-const-assign": 2,
      // 禁止类成员中出现重复的名称
      "no-dupe-class-members": 2,
      //禁止使用alert confirm promp
      "no-alert": process.env.NODE_ENV === "production" ? "error" : "off",
      //禁止多余的冒号
      "no-extra-semi": 2,
      //禁止在条件中使用常量表达式
      "no-constant-condition": 2,
      //空行最多不能超过2行
      "no-multiple-empty-lines": [1, { max: 2 }],
      //禁止无用的表达式
      "no-unused-expressions": 1,
      //禁用不必要的嵌套块
      "no-lone-blocks": 2,
      //不允许使用逗号操作符
      "no-sequences": 2,
      //禁止不规则的空白
      "no-irregular-whitespace": 2,
      //函数括号前的空格
      "space-before-function-paren": 0,
      //处理回调错误
      "handle-callback-err": 1,
      //首选承诺拒绝错误
      "prefer-promise-reject-errors": 0,
      //要求或禁止在注释前有空白 (space 或 tab)
      "spaced-comment": 1,
      //强制关键字周围空格的一致性
      "keyword-spacing": 1,
      //强制在花括号中使用一致的空格
      "object-curly-spacing": 1,
      // 控制逗号前后的空格
      "comma-spacing": [
        2,
        {
          before: false,
          after: true
        }
      ],
      // 要求或禁止 var 声明语句后有一行空行
      "newline-after-var": 0,
      //强制使用一致的缩进
      indent: 0,
      // html 内 缩进
      "vue/html-indent": 0,
      // 插值两端必须留一个空格
      "vue/mustache-interpolation-spacing": 0,
      //强制每行的最大属性数
      "vue/max-attributes-per-line": 0,
      //vue/属性顺序
      "vue/attributes-order": 0,
      // 强制要求在对象字面量的属性中键和值之间使用一致的间距 "var obj = { "foo": 42 };"
      "key-spacing": 0,
      // 禁止末尾逗号
      "comma-dangle": 0,
      // 强制在块之前使用一致的空格 "function a() {}"
      "space-before-blocks": 0,
      // 要求操作符周围有空格 "a ? b : c"
      "space-infix-ops": 2,
      // "() => {};" // 强制箭头函数前后使用一致的空格
      "arrow-spacing": 2,
      //插值中强制统一间距
      //强制组件中的属性顺序
      "vue/order-in-components": 0,
      //不允许字段名称重复
      "vue/no-dupe-keys": 2,
      //多次引用同个包
      "import/no-duplicates": 2,
      //执行有效v-for指令
      "vue/valid-v-for": 2,
      //V-bind:key使用v-for指令要求
      "vue/require-v-for-key": 2,
      //不允许解析错误<template>
      "vue/no-parsing-error": [2, { "x-invalid-end-tag": false }],
      //强制执行自闭式
      "vue/html-self-closing": "off",
      //不允许计算属性中的副作用
      "vue/no-side-effects-in-computed-properties": 0,
      //禁止 v-for 指令或范围属性的未使用变量定义
      "vue/no-unused-vars": 1,
      //执行有效v-model指令
      "vue/valid-v-model": 2,
      //强制执行有效的模板根
      "vue/valid-template-root": 2
    }
  };

3.在setting.json 配置

uniapp中AES加密_json_08

"[vue]": {
    "editor.defaultFormatter": "Vue.volar"
  },
  // vscode默认启用了根据文件类型自动设置tabsize的选项
  "editor.detectIndentation": false,
  // 重新设定tabsize
  "editor.tabSize": 2,
  // #每次保存的时候自动格式化
  "editor.formatOnSave": true,
  // eslint配置项,保存时自动修复错误
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
  // 添加 vue 支持
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    "html",
    "vue"
  ],
  //  #让函数(名)和后面的括号之间加个空格
  "javascript.format.insertSpaceBeforeFunctionParenthesis": true,
  //打开文件不覆盖
  "workbench.editor.enablePreview": false,
  // 设置不同文件使用的格式化配置
  "[html]": {
    // "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[javascript]": {
    "editor.defaultFormatter": "vscode.json-language-features"
  },
  "[json]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[jsonc]": {
    "editor.defaultFormatter": "vscode.json-language-features"
  },
  "vetur.format.defaultFormatter.css": "prettier",
  "vetur.format.defaultFormatter.postcss": "prettier",
  "vetur.format.defaultFormatter.scss": "prettier",
  "vetur.format.defaultFormatter.less": "prettier",
  "vetur.format.defaultFormatter.stylus": "stylus-supremacy",
  "vetur.format.defaultFormatter.ts": "prettier",
  // vetur 缩进是4
  "vetur.format.options.tabSize": 2,
  "vetur.format.options.useTabs": false,
  // #vue组件中html代码格式化样式
  "prettier.vueIndentScriptAndStyle": true,
  "vetur.format.defaultFormatterOptions": {
    "prettier": {
      // Prettier option here
      "trailingComma": "es5", // 多行时,尽可能打印尾随的逗号
      "tabWidth": 2, // 会忽略vetur的tabSize配置
      "useTabs": false, // 是否利用tab替代空格
      "semi": true, // 句尾是否加;
      "singleQuote": false, // 使用单引号而不是双引号
      "arrowParens": "avoid", // allow paren-less arrow functions 箭头函数的参数使用圆括号
    },
    "js-beautify-html": {
      //属性强制折行对齐
      "wrap_attributes": "force-aligned"
    }
  },
  "eslint.options": {
    "configFile": "./`.eslintrc`.js"
  },
  "[typescript]": {
    "editor.defaultFormatter": "vscode.typescript-language-features"
  }

7.权限控制

1.在src/enums中 添加user.ts

export default class UserInfo {
  // 帐号
  userId: string | null = null;
  // token
  token: string | null = null;
  //名称
  name: string | null = null;
  //用户类型
  UserType: string | null = null;
}

2.在src/stores/modules/user.ts中配置状态管理

import { defineStore } from "pinia";
import type UserInfo from "@/enums/user";

interface AuthStore {
  userInfo: UserInfo | null;
}
// 定义 Store
const useMemberStore = defineStore("user", {
  state: (): AuthStore => ({
    userInfo: null,
  }),
  getters: {},
  actions: {
    logout() {
      sessionStorage.removeItem("userInfo");
      localStorage.removeItem("user");
    },
  },
});

export default useMemberStore;

3.在src/style/text.json

{
  "code": "200",
  "message": "请求成功",
  "lists": [
    {
      "userId": "123456",
      "token": "abc123",
      "name": "xpf",
      "UserType": "bug666"
    }
  ]
}

4.src/api/login.ts

import request from "@/utils/http";

export function text(data: any) {
  return request({
    //访问到styles下的text.json文件
    url: "/text.json",
    method: "post",
    data,
  });
}

5.login.ts代码:

<template>
  <van-form @submit="onSubmit">
    <van-cell-group inset>
      <van-field v-model="username" name="用户名" label="用户名" placeholder="用户名"
        :rules="[{ required: true, message: '请填写用户名' }]" />
      <van-field v-model="password" type="password" name="密码" label="密码" placeholder="密码"
        :rules="[{ required: true, message: '请填写密码' }]" />
    </van-cell-group>
    <div style="margin: 16px;">
      <van-button round block type="primary" native-type="submit">
        登录
      </van-button>
    </div>
  </van-form>
</template>

<script lang="ts" setup>
import router from "@/router";
import { ref } from "vue";
import { text } from "@/api/login"
import PiniaInfo from '@/stores/index';
import { storeToRefs } from "pinia"

const username = ref("");
const password = ref("");
debugger
if (sessionStorage["userInfo"]) {
  router.replaceAll({ name: "home" });
}

const onSubmit = () => {
  text(null).then((res: any) => {
    const user = storeToRefs(PiniaInfo().user)
    user.userInfo.value = res.lists[0];
    sessionStorage["userInfo"] = JSON.stringify(res.lists[0]);
    router.replaceAll({ name: "home" });
  });
};


</script>

<style></style>

6.src/pages/index/index.ts代码

<template>
  <van-button type="primary" @click="loginHtml"> 登录页 </van-button>
</template>

<script setup lang="ts">
import router from "@/router";

const loginHtml = () => {
  router.replaceAll({ name: "login" });
}


</script>

<style></style>

7.src/pages/mine/mine.ts代码

<template>
  <van-button type="primary" @click="mine"> 退出登录 </van-button>
</template>

<script lang="ts"  setup>
import router from "@/router";
import userInfo from "@/stores/index"
const mine = () => {
  const out = userInfo()
  out.user.logout()
  router.replaceAll({ name: "login" })
}
</script>

<style></style>

测试…