@heqinglin
2023-05-04T10:40:42.000000Z
字数 6564
阅读 33
文档
vue
layout 模板选择由 状态管理控制 store/modules/app.ts layout,动态修改也是改这个,系统默认把layout的值加到了缓存里(wsCache封装的),如果想一套系统两套2布局需要修改。
新增布局需要在 src/layout/Layout.vue 在renderLayout()中增加stitch、然后在useRenderLayout.tsx中新增模板
封装自web-storage-cache
,可直接存储对象数组,位置在src/hooks/web/useCache.ts,其实就是webstorage,不需要JSON.stringify() JSON.parse()
插件自动帮我们做了
使用
import { useCache } from '@/hooks/web/useCache'
const { wsCache } = useCache()
wsCache.set('key', value)
wsCache.get('key')
wsCache.clear() //全部清除
wsCache.set('username', 'wqteam', {exp : 100});//超时100s
wsCache.deleteAllExpires();// 手工删除所有超时CacheItem,
登录状态token就是存在这里的
全局的总线程类似vue2的EventBus,实现发布订阅
mitt.emit('mymsg',data);
mitt.on('mymsg',(data)=>{
console.log("接收到的内容是:"+ data);
});
使用
import { useEmitt } from '@/hooks/web/useEmitt'
const { emitter } = useEmitt()
emitter.emit('getList', 'add') //发送数据
//接收数据
useEmitt({
name: 'getList',
callback: (type: string) => {
console.log(type) //add
}
})
封装在 src/hooks/web/userDesign.ts
getPrefixCls(scope)
方法返回一个拼接的字符串 v-scope
return `${lessVariables.namespace}-${scope}`
样式, 比如 scope = layout
<style lang="less" scoped>
@prefix-cls: ~'@{namespace}-layout';
.@{prefix-cls} {}
</style>
个人不喜欢这种马甲式调来调去的方式,顶层class根据页面命名,一目了然最好。
登录成功, 把用户信息缓存wsCache.set(appStore.getUserInfo, res.data)
,appStore.getUserInfo
是store中预设的key,默认为'userInfo'
缓存用于导航守卫在页面跳转时,判断是否登陆。导航守卫代码位于 src/permission.ts
store/modules/app.ts中设置
dynamicRouter: wsCache.get('dynamicRouter') || false, // 是否动态路由
动态路由是根据账号来加载不同的路由,框架写死了2种账号权限,admin和test。
在mock/role/index.ts 分别维护两个list,模拟接口返回。
调用 store/modules/permission.ts
里 generateRoutes
方法会根据账号类型,把动态路由与静态路由合并。
admin/test 合并之前,有个generateRoutesFn函数,对后端返回的路由,与asyncRouterMap 进行核对,将有权限访问的筛选出来,有权访问但项目缺失的路由也会打印错误提示。
详情见【动态路由完全解读】
vite打包已经没有node环境下的process全局变量了,需要如下使用环境变量
import.meta.env.VITE_APP_TITLE
await可以直接解出promise的返回值,相当于获取then()的值,如果遇到reject则什么也不会走,可以用catch劫持。
async () => {
const res = await loginOutApi().catch(() => {})
}
https://vueuse.org/guide/
VueUse 是一组基于Composition API的实用函数,也是尤雨溪团队出,旨在将复杂的功能实现简单化。
使用
import { 具体方法 } from '@vueuse/core'
vite不支持 require,需要安装插件
https://github.com/WarrenJones/vite-plugin-require-transform
npm i vite-plugin-require-transform --save-dev
// vite.config
import requireTransform from 'vite-plugin-require-transform';
export default defineConfig({
plugins: [
requireTransform({
fileRegex: /.ts$|.tsx$ |.vue$/
}),
],
});
借助requre(.html?raw)
https://cn.vitejs.dev/config/shared-options.html#assetsinclude
vite.config.ts
assetsInclude: ['**/*.html'],
完整
<template>
<div class="iframe_box">
<iframe width="100%" height="800px" frameborder="0" id="myIframe"></iframe>
</div>
</template>
<script setup lang="ts">
import { onMounted, nextTick } from 'vue'
const iframeData = require('/static/pdfjs-3.1.81-dist/web/viewer.html?raw')
onMounted(() => {
nextTick(() => {
const myIframe: any = document.getElementById('myIframe')
myIframe.contentDocument.documentElement.innerHTML = iframeData
})
})
</script>
import { useAppStore } from '@/store/modules/app'
const appStore = useAppStore()
const footer = computed(() => appStore.getFooter) //取值
src/components/ConfigGlobal.vue 中 watch width store.setLayout() actions实现切换layout
并且layout是存在wsCache
https://windicss.org/utilities/layout/display.html
flex display: flex;
inline-block display: inline-block;
justify-start justify-content: flex-start;
justify-between justify-content: space-between;
justify-around justify-content: space-around;
items-center align-items: center;
flex-col flex-direction: column;
p-0 padding: 0px;
px-0 padding-left: 0px;
padding-right: 0px;
py-0 padding-top: 0px;
padding-bottom: 0px;
pt-0 padding-top: 0px;
pt-0 padding-right: 0px;
pb-0 padding-bottom: 0px;
pl-0 padding-left: 0px;
m-0px margin: 0px;
mb-30px margin-bottom: 30px;
w-30px width: 30px;
w-[100%] width:100%;
max-w-500px width: max-width:500px;
h-30px height: 30px;
leading-[35px] line-height:35px;
text-16px font-size: 16px;
line-height: 1;
text-[#ff9f15] color:#ff9f15;
text-center text-align:center;
bg-[#ff9f15] background-color:#ff9f15;
font-bold font-weight: 700;
overflow-hidden overflow: hidden;
rounded-full border-radius:50% //border-radius: 9999px;
rounded boredr-radius:4px
rounded-md boredr-radius:6px
border-bottom-1 border-bottom-width: 1px;
border-solid border-style: solid;
<sm:hidden @media (max-width: 640px){display:none;} //屏幕小于640执行
<md @media (max-width: 768px)
<lg @media (max-width: 1024px)
<xl @media (max-width: 1280px)
<2xl @media (max-width: 1536px)
vue3已弃用,改成 :deep(inner-select){}
src/components/Table/src/Table.vue ,96
让element-table的 selection-change 事件可以从父组件监听
const selectionChange = (selection: Recordable[]) => {
selections.value = selection
emit('seleChange',selection)
}
使用
<Table @sele-change="selectionChange">
只想取一下选中项可用ref方法,作者已通过暴露属性的方法给父组件使用
refTable.value?.selections
unref(formRef)?.formModel
git commit -m 'message' --no-verify
或者删除 根目录下 .husky 中的commit-msg、pre-commit
根目录/types/env.d.ts 或者 global.d.ts
declare interface Window {
BMapGL: any
mapvgl: any
BMapGLLib: any
stylejson: any
}
项目已经安装了lodash-es 支持摇树优化
import {findKey} from 'lodash-es'
//不推荐
import * as _ from 'lodash-es'
_.findKey(...)
封装了单例模式,用于跨组件操作
使用:直接 webSocket.instance.xxx
在实例上调用方法
注意:
只有send方法需要在init的回调中,确保链接成功才能发送。
组件卸载的回调里记得.instance.close()
断开链接
import ws from '@/utils/webSocket'
//初始化
ws.instance.init('ws://localhost:3000', () => {
console.log('连接成功的回调:', ws.instance.getState())
ws.instance.send('hello')
})
console.log(ws.instance.getState())
//接收数据
ws.instance.onMessage((res) => {
console.log(res)
})
src/store/modules/app.ts 可以设置theme
, 它其实是和action中的setCssVarTheme
一起工作的。
在APP.vue
主入口使用了一个自定义的ConfigGlobal
组件,用来设置全局EL组件,在这里面也运行了设置主题的代码。
onMounted(() => {
appStore.setCssVarTheme()
})
会把样式变量定义在document.documentElement
也就是html上,然后就可以全局使用了。
用'vue-types'进行类型约束,位置在 utils/propTypes.ts。
下面介绍下vue-types:
vue-types
默认导出一个模拟 React prop-type 的 ES6 类对象
import VueTypes from 'vue-types'
export default {
props: {
message: VueTypes.string.isRequired,
}
}
也可以把这个类对象解构出来,每一个都是工厂函数。
import { number, oneOf } from 'vue-types'
export default {
props: {
id: number().isRequired,
status: oneOf(['open', 'close']).def('open'),
},
}
vue-types
还提供了一个createTypes()函数用来自定义命名空间。
import { createTypes } from 'vue-types'
const MyTypes = createTypes()
export default {
props: {
message: MyTypes.string.isRequired
}
}
也可以给自定义的命名空间设置默认值,默认的默认值也是undefined
const MyTypes = createTypes({
string: undefined
})
import { propTypes } from '@/utils/propTypes'
const props = defineProps({
title: propTypes.string.def('xxx'),
})
这个
propTypes
其实就是自定义的命名空间。
也可以用extend扩展自己的类型
createTypes().extend([
{
name: 'style',
getter: true,
type: [String, Object],
default: undefined
}
])