Skip to content

Latest commit

 

History

History
418 lines (251 loc) · 7.38 KB

笔记.md

File metadata and controls

418 lines (251 loc) · 7.38 KB

Vue3-ts-cms

npm i vue@latest

前置:配置

tsconfig.json

vue将ts的配置大多都隐藏了

如果想看: "extends": "@vue/tsconfig/tsconfig.web.json" 表示,tsconfig配置继承自里面的文件

vite.config.ts中的

 alias: {
      "@": fileURLToPath(new URL("./src", import.meta.url)),
    },

是打包时解析别名

tsconfig.json中的

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

是用于代码路径提示

"references": [
    {
      "path": "./tsconfig.config.json"
    }
  ]

如果想修改ts配置,建议在./tsconfig.config.json里修改

不建议在 **"extends": "@vue/tsconfig/tsconfig.web.json"**里修改

这些配置 最终都会汇总到tsconfig.json里

//tsconfig.config.json
"extends": "@vue/tsconfig/tsconfig.node.json"  //ssr相关配置

en.d.ts

引用了vite/client里的 文件声明

Editorconfig插件

有助于不同IDE编辑器上处理同一项目的多个开发人员维护一致的编码风格

Prettier

{
	"useTabs": false,
	"tabWidth": 2,
	"printWidth": 80,
	"singleQuote": false,
	"semi": true
}

Eslint

环境变量

1.vite提供了一些接口来判断当前项目环境

import.meta.env.DEV //是否为开发环境 boolean
import.meta.env.PROD //是否为生产环境
import.meta.env.SSR //是否为服务器端渲染

import.meta.env.BASE_URL //
import.meta.env.MODE //当前模式 "production"/"development" 

**2.**dotenv配置环境

变量必须以VITE开头

//.env
VITE_
//.env.production
VITE_URL=
//.env.development
VITE_URL=

Element-plus导入

快速开始 | Element Plus (element-plus.org)

按需导入

npm install -D unplugin-vue-components unplugin-auto-import
// vite.config.ts
import { defineConfig } from 'vite'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

export default defineConfig({
  // ...
  plugins: [
    // ...
    AutoImport({
      resolvers: [ElementPlusResolver()],
    }),
    Components({
      resolvers: [ElementPlusResolver()],
    }),
  ],
})

重启项目

根目录会自动生成

auto-import.d.ts(声明文件)

components.d.ts

两个声明文件

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

在ts配置处声明两个文件,否则不会生效

登录开发

panelAccount暴露登录方法 defineExpose({loginAction})

父组件可以直接选到子组件的根类名

vue-scoped

原理:

.father[data-v-7a7a37b1] father上有对应属性

子组件根的类名的data属性的值与父组件的一样

.father[data-v-7a7a37b1] .son[data-v-7a7a37b1]

动态路由

1.基于角色的动态路由

const roles={
	'superadmin':[所有路由]=>router.main.children
	'admin':[部分路由]=>router.main.children
	'user':[少部分路由]=>router.main.children
	'mannager':[]=>后端返回路由表json
}

弊端:每增加一个角色,都要增加key,value

2.基于菜单的动态路由(推荐)

userMenus=>动态展示菜单

登录接口中请求的三个内容:

1.token

2.用户信息:角色(role)

3.菜单信息

刷新时数据会丢失,做持久化缓存

pinia中定义action获取本地数据

在pinia初始化完后,将本地数据都挂载到pinia上,并添加路由表

加载路由

app.use(pinia);
//pinia加载完后将本地数据都挂载到pinia上
const loginStore = useLoginStore();
loginStore.loadLocalData();
//再加载路由
app.use(router);

el-table

scoped.row

NextTick

<div @click="increment" class="count">当前计数:{{count}}</div>


const count=ref(100)
function increment(){
    count.value+=100
    const countEl=document.querselector("count");
    console.log(countEl?.textContent) //100,这里拿不到200
}

DOM已经更新为了200

但countEl?.textContent获取到的值仍为100

此时可以用nextTick(()=>{})

<div @click="increment" class="count">当前计数:{{count}}</div>


const count=ref(100)
function increment(){
    count.value+=100
   	nextTick(()=>{
        const countEl=document.querselector("count");
    	console.log(countEl?.textContent) //200
   })
}

放到nextTick里时就可以获取到200了

NextTick是等待下一次 DOM 更新刷新的工具方法。

你在 Vue 中更改响应式状态时,最终的 DOM 更新并不是同步生效的,

如:执行count.value+=100时,DOM并没有更新。

而是由 Vue 将它们缓存在一个队列中,直到下一个“tick”才一起执行。

一次Tick: pre代码操作——》更新队列——》生命周期里的操作——》nextTick()里的操作

这样是为了确保每个组件无论发生多少状态改变,都仅执行一次更新。

nextTick() 可以在状态改变后立即使用,以等待 DOM 更新完成。你可以传递一个回调函数作为参数,或者 await 返回的 Promise。

vue3中nextTick是微任务: 在Promise的.then里

vue2中nextTick是宏任务还是微任务发生了好几次变化

原理:

将nextTick放在promise的.then中

const promise=new Promise(()=>{
	pre
	queue
	post
}).then( nextTick(()=>{}) )

按钮权限

1.登陆时,userMenus的第三层会带有permission属性(Array数组),用于存储不同页面下的不同权限:如下例

"system:users:create"

系统-用户-创建权限

数据准备

在登陆Action时,将后台传过来的Menu过滤出permissions,并将permissions保存到state中。

为防止刷新后store数据丢失,在pinia加载完后,就将本地数据都挂载到pinia上(调用useLoginStore里的loadLocalData()方法)

这里,permisssion也需要做持久化缓存,所以loadLocalData()中也要加载permisssion

权限验证

封装usePermission的Hook,根据传入的permissionId,返回是否有这个权限

在Table通用组件中使用Hook,再用v-if判断是否显示

Pinia中监听Action

useXXXStore暴露出了一个API,用于监听某Action,并在Action执行后的运行回调

$onAction(()=>{})

要放执行Action函数之前

const unsubscribe = someStore.$onAction(
  ({
    name, // action 名称
    store, // store 实例,类似 `someStore`
    args, // 传递给 action 的参数数组
    after, // 在 action 返回或解决后的钩子
    onError, // action 抛出或拒绝的钩子
  }) => {
    // 为这个特定的 action 调用提供一个共享变量
    const startTime = Date.now()
    // 这将在执行 "store "的 action 之前触发。
    console.log(`Start "${name}" with params [${args.join(', ')}].`)

    // 这将在 action 成功并完全运行后触发。
    // 它等待着任何返回的 promise
    after((result) => {
      console.log(
        `Finished "${name}" after ${
          Date.now() - startTime
        }ms.\nResult: ${result}.`
      )
    })

    // 如果 action 抛出或返回一个拒绝的 promise,这将触发
    onError((error) => {
      console.warn(
        `Failed "${name}" after ${Date.now() - startTime}ms.\nError: ${error}.`
      )
    })
  }
)

// 手动删除监听器
unsubscribe()