李维亮_前端开发攻城狮 - vue
type: channel
link: https://liweiliang.com/category/vue/
items: nodejs v24 Error: No such module: http_parser
items: vue LogicFlow 流程图基础配置
items: element的tree树形菜单回显、父级设置半选状态
items: ElementUI 中 Table expend嵌套另一个子Table，fixed+嵌套多选实现
items: 解决elementui中el-radio或el-cascader报错：Blocked aria-hidden on an element because its descendant retained focus.
items: 在vue3中代替vue2 .sync修饰符
items: svg渲染use占位符宽高都是0，页面显示空白问题
items: pc端屏幕显示设置缩放比例对页面布局的适配
items: vue国际化配置
items: vue 项目启动报错：Syntax Error: Unexpected token 的解决方法
items: vue-pdf使用demo
items: jszip demo
items: vue-quill-editor 简单配置demo
items: [Vue warn]: Failed to resolve directive: ant-portal (found in <Anonymous>)
items: vConsole - 移动端开发调试利器
items: Vue style scoped 使用@import引入css, 作用域是全局的解决方案
items: vue 组件中动态引入外部js库
items: never reassigned. Use 'const' instead prefer-const
items: Pinia 快速入门
items: Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: No "exports" main defined in D:\project\saas-platform-pc\node_modules\@babel\helper-compilation-targets\package.json
items: vue for循环中按顺序axios请求拿到每条数据对应的状态
items: 使用自定义指令directive如何修改v-model绑定的键值对
items: Ant Design of Vue —— Table表格组件 —— 设置动态表头
items: vue-baidu-map or 百度地图API 禁止点击时弹出地址详情的方法
items: antdv Modal this.$confirm对话框 使用vnode修改标题icon问题
items: Warning: [antdv: Each record in table should have a unique `key` prop,or set `rowKey` to an unique primary key.]
items: vue 报错 You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.
items: Vue父子组件生命周期执行顺序及钩子函数的个人理解（转载）
items: moment.js常用时间差
items: 图片转base64 方法

nodejs v24 Error: No such module: http_parser
type: item
date: 2026-01-07T18:01:31+08:00
description: 最近跑了个老项目由于node版本太高启动的时候报如下错误对应报错的文件C:\code\siemens\bsceba\node_modules\http-deceiver\lib\deceiver.js主要问题 process.binding('http_parser') 是 Node已弃用。解决方法：HTTPParser = process.binding('http_parser').HTTPParser; 改成：HTTPParser = require('http-parser-js').HTTPParser; 兼容修改成如下：try { // 尝试使用原生绑定 HTTPParser = process.binding('http_parser').HTTPParser; } catch (e) { // 降级到 JavaScript 实现 HTTPParser = require('http-parser-js').HTTPParser; }

vue LogicFlow 流程图基础配置
type: item
date: 2026-01-06T17:35:00+08:00
description: LogicFlow 配置项：LogicFlow 流程图上所有的节点实例操作以及事件new LogicFlow()初始化的详情 点击这里跳转官方说明 图片显示demo在文章底部用到的依赖包 "@logicflow/core": "^2.1.7", "@logicflow/extension": "^2.1.9", "@logicflow/layout": "^2.0.7", LogicFlow apinew LogicFlow 初始化基础DEMO CODEthis.lf = new LogicFlow({ container: this.$refs.container, grid: true, // 等同于默认属性如下 // grid: { // size: 20, // 设置网格大小 // visible: true, // 设置是否可见，若设置为false则不显示网格线但是仍然保留size栅格的效果 // type: "dot", // 设置网格类型，目前支持 dot 点状和 mesh 线状两种 // config: { // color: "#ababab", // 设置网格的颜色 // thickness: 1, // 设置网格线的宽度 // }, // }, keyboard: { enabled: true, }, // edgeTextDraggable: true, // adjustEdgeStartAndEnd: true, edgeType: 'bezier', // idGenerator(type) { // return type + '_' + Math.random(); // }, }); render渲染图数据的时候可以增加初始化数据renderData是在data中配置的默认初始化数据，可以不填this.lf.render(this.renderData); LogicFlow 事件文档接口 外部拖入节点添加时触发demothis.lf.on("node:dnd-add", (data) => { // 拖拽进入面板内执行 console.log("node:dnd-add", data) }); 基于node:click事件输出的API各个模块默认初始化方法LogicFlow 构造函数graphModel 画布数据属性nodeModel 节点数据属性graphModel 事件transformModel 控制画布的放大、缩小、平移editConfigModel 控制页面编辑状态this.lf.on("node:click", (data) => { console.log("node:click", data) const {lf} = this; let {id} = data.data; // 获取节点的model console.log("getNodeModelById", lf.getNodeModelById(id)) // 获取节点的model数据 console.log("getNodeDataById", lf.getNodeDataById(id)) // 获取流程绘图数据 console.log("getGraphData", lf.getGraphData()) // 获取流程绘图原始数据 console.log("getGraphRawData", lf.getGraphRawData()) // 获取指定区域内的所有元素，此区域必须是 DOM 层。 console.log("getAreaElement", lf.getAreaElement([100, 100], [200, 200])) console.log('========LogicFlow==================') console.log("lf", lf) console.log('========画布数据属性=================') const graphModel = lf.graphModel; console.log("graphModel", graphModel) console.log("graphModel", graphModel.height) console.log('========节点数据属性=================') const nodeModel = lf.getNodeModelById(id); console.log("nodeModel", nodeModel) nodeModel.updateText("hello world"); console.log('========事件====================…

element的tree树形菜单回显、父级设置半选状态
type: item
date: 2025-06-10T17:03:00+08:00
description: 主要代码： keyList.forEach(key => { const node = this.$refs.weiTree.getNode(key); console.log(node.isLeaf) if (node.isLeaf) { this.$refs.weiTree.setChecked(node, true); } }); 完整demo <el-dialog title="tree" class="bp-dialog" :visible.sync="treeVisible" width="850px" append-to-body :close-on-click-modal="false"> {{ item.title }} <el-tree ref="weiTree" :data="treeData" :props="defaultProps" show-checkbox node-key="code" default-expand-all :expand-on-click-node="false"> <span v-if="node.label.length<28">{{ node.label }} <el-tooltip v-else placement="top" effect="light"> {{ node.label }} {{ node.label }} </el-tooltip> <el-image v-if="/.(png|jpg|jpeg)$/.test(item.dfsPath)" :src="item.dfsPath" :preview-src-list="[item.dfsPath]"> </el-image> 文件 <el-tag v-if="!data.notCheck">检查</el-tag> <el-tag v-else type="success">只读</el-tag> <el-tag v-if="[1,2].includes(data.checkResultType)"> {{ checkResultTypeObj[data.checkResultType] }} </el-tag> <el-tag v-else type="succcess"> {{ checkResultTypeObj[data.checkResultType] }} </el-tag> {{ data.sort }} </el-tree> <el-button type="primary" @click="handleInit">初始化</el-button> <el-button type="primary" @click="handleSubmit">确定</el-button> <el-button @click="handleCancel">取消</el-button> </el-dialog>

ElementUI 中 Table expend嵌套另一个子Table，fixed+嵌套多选实现
type: item
date: 2025-04-28T17:28:00+08:00
description: 比较忙，直接贴代码 <el-button size="mini" @click="handleExpand" class="bp-primary-plain" type="primary" plain>一键展开 </el-button> <el-button size="mini" @click="handlePutAway" class="bp-primary-plain" type="primary" plain>一键收起 </el-button> <el-table ref="tableItemRef" class="bp-table" border :data="tableData"> <el-table-column width="50" fixed="left" align="center"> <el-checkbox v-model="globelCheckedAll" @change="clickCheckAll(scope)" :indeterminate="isIndeterminateAll"></el-checkbox> <el-checkbox v-model="scope.row.isChecked" :indeterminate="scope.row.isIndeterminate" @change="handleSelectionChange(scope.row)"></el-checkbox> </el-table-column> <el-table-column align="center" fixed="left" type="expand"> <el-table class="bp-table" :data="props.row.children" row-key="id"> <el-table-column width="97" align="center"> <el-checkbox v-model="props.row.isChecked" :indeterminate="props.row.isIndeterminate" @change="handleSelectionChange(props.row)"></el-checkbox> <el-checkbox v-model="scope.row.isChecked" @change="clickCheckItemFn(props.row, scope.row)"></el-checkbox> </el-table-column> <el-table-column align="center" prop="" min-width="150" label="" show-overflow-tooltip/> <el-table-column align="center" prop="itemFunction" width="150" label="工步" show-overflow-tooltip/> <el-table-column align="center" prop="potentialFailureMode" min-width="150" label="潜在失效模式" show-overflow-tooltip/> <el-table-column align="center" prop="potentialEffectOfFailure" min-width="150" label="潜在失效影响" show-overflow-tooltip/> <el-table-column align="center" prop="sev" label="严重度" min-width="70" show-overflow-tooltip/> <el-table-column align="center" prop="potentialCauseMechanismOfFailure" min-width="120" label="失效起因/机理" show-overflow-tooltip/> <el-table-column align="center" prop="occur" label="频度" min-width="60" show-overflow-tooltip/> <el-table-column align="center" prop="currentDesignControls" min-width="180" label="现行过程控制" show-overflow-tooltip/> <el-table-column align="center" prop="det" label="探测度" min-w…

解决elementui中el-radio或el-cascader报错：Blocked aria-hidden on an element because its descendant retained focus.
type: item
date: 2025-01-07T15:01:00+08:00
description: 在使用elment中el-radio的时候发现控制台报错，Blocked aria-hidden on an element because its descendant retained focus. The focus must not be hidden from assistive technology users. Avoid using aria-hidden on a focused element or its ancestor. Consider using the inert attribute instead, which will also prevent focus. For more details, see the aria-hidden section of the WAI-ARIA specification at https://w3c.github.io/aria/#aria-hidden. Element with focus: input Ancestor with aria-hidden: ​ 解决方案一：::v-deep input[aria-hidden="true"] { display: none !important; } ::v-deep .el-radio:focus:not(.is-focus):not(:active):not(.is-disabled) .el-radio__inner { box-shadow: none !important; } 解决方案二：自定义指令 Vue.directive('removeAriaHidden', { bind(el, binding) { const ariaEls = el.querySelectorAll('.el-radio__original') ariaEls.forEach((item) => { item.removeAttribute('aria-hidden') }) } }) 页面使用<el-radio-group v-model="tableRadio" class="new_radio" @change="changeRadio" v-removeAriaHidden></el-radio-group>

在vue3中代替vue2 .sync修饰符
type: item
date: 2022-12-06T11:41:43+08:00
description: 最近在把vue2升级vue3过程中遇到了各种bug，这次遇到了在vue2中父子传参的过程中发现showSearch数据不更新问题父组件引用 <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> 子组件 this.$emit("update:showSearch", !this.showSearch); 我们需要吧父组件改成v-model:value="value" 模式<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>

svg渲染use占位符宽高都是0，页面显示空白问题
type: item
date: 2022-12-05T20:23:00+08:00
description: <svg-icon icon-class="clipboard" class-name="disabled" /> 经过分析是少了个解析插件 svg-sprite-loader ，用npm安装一下，然后需要在vue.config.js中添加配置'use strict' const path = require('path') function resolve(dir) { return path.join(__dirname, dir) } chainWebpack: config => { config.plugins.delete('preload') // TODO: need test config.plugins.delete('prefetch') // TODO: need test // set svg-sprite-loader config.module .rule('svg') .exclude.add(resolve('src/assets/icons')) .end() config.module .rule('icons') .test(/\.svg$/) .include.add(resolve('src/assets/icons')) .end() .use('svg-sprite-loader') .loader('svg-sprite-loader') .options({ symbolId: 'icon-[name]' }) .end() }

pc端屏幕显示设置缩放比例对页面布局的适配
type: item
date: 2022-11-30T13:49:00+08:00
description: 利用device-pixel-ratio单独适配像素比@media all and (-moz-min-device-pixel-ratio: 1.09) and (-moz-max-device-pixel-ratio: 1.18), (-webkit-min-device-pixel-ratio: 1.09) and (-webkit-max-device-pixel-ratio: 1.18), (min-resolution: 1.09dppx) and (max-resolution: 1.18dppx) { :root { font-size: 14px; } } @media all and (-moz-min-device-pixel-ratio: 1.19) and (-moz-max-device-pixel-ratio: 1.28), (-webkit-min-device-pixel-ratio: 1.19) and (-webkit-max-device-pixel-ratio: 1.28), (min-resolution: 1.19dppx) and (max-resolution: 1.28dppx) { :root { font-size: 13px; } } @media all and (-moz-min-device-pixel-ratio: 1.29) and (-moz-max-device-pixel-ratio: 1.4), (-webkit-min-device-pixel-ratio: 1.29) and (-webkit-max-device-pixel-ratio: 1.4), (min-resolution: 1.29dppx) and (max-resolution: 1.4dppx) { :root { font-size: 12px; } } @media all and (-moz-min-device-pixel-ratio: 1.41) and (-moz-max-device-pixel-ratio: 1.6), (-webkit-min-device-pixel-ratio: 1.41) and (-webkit-max-device-pixel-ratio: 1.6), (min-resolution: 1.41dppx) and (max-resolution: 1.6dppx) { :root { font-size: 10px; } } @media all and (-moz-min-device-pixel-ratio: 1.61) and (-moz-max-device-pixel-ratio: 1.8), (-webkit-min-device-pixel-ratio: 1.61) and (-webkit-max-device-pixel-ratio: 1.8), (min-resolution: 1.61dppx) and (max-resolution: 1.8dppx) { :root { font-size: 9px; } } @media all and (-moz-min-device-pixel-ratio: 1.81) and (-moz-max-device-pixel-ratio: 2.1), (-webkit-min-device-pixel-ratio: 1.81) and (-webkit-max-device-pixel-ratio: 2.1), (min-resolution: 1.81dppx) and (max-resolution: 2.1dppx) { :root { font-size: 8px; } } vue解决办法mounted () { this.handleScreen() window.onresize = () => { this.handleScreen() } }, methods: { handleScreen(){ const zoom = this.detectZoom(); console.log(zoom, 'MMMMMMMMMMMMMMM') const scale = 100 / Number(zoom); console.log('scale', scale, typeof scale) }, detectZoom () { let ratio = 0, screen = window.screen, ua = navigator.userAgent.toLowerCase(); if (window.devicePixelRatio !== undefined)…

vue国际化配置
type: item
date: 2022-11-07T16:31:55+08:00
description: 首先安装vue-i18n包新建locales/i18n.js文件/** * Created by liweiliang 406320591@QQ.com on 2022/10/14 15:16. */ import Vue from "vue"; import VueI18n from "vue-i18n"; import elementZhLocale from "element-ui/lib/locale/lang/zh-CN"; // element-ui lang import elementEnLocale from "element-ui/lib/locale/lang/en"; // element-ui lang import enLocale from "./lang/enLocale"; import zhLocale from "./lang/zhLocale"; const messages = { en: { ...enLocale, ...elementEnLocale, }, zh: { ...zhLocale, ...elementZhLocale, }, }; /** * i18n 配置 * @param locale 本地化语言 * @param fallback 回退语言 * @returns {VueI18n} */ function initI18n(locale, fallback) { Vue.use(VueI18n); let i18nOptions = { locale, fallbackLocale: fallback, silentFallbackWarn: true, messages, }; return new VueI18n(i18nOptions); } export { initI18n }; locales/lang/zhLocale.js文件/** * Created by liweiliang 406320591@QQ.com on 2022/10/17 14:11. */ const zhModulesFiles = require.context("./zh", true, /\.js$/); const zhLang = zhModulesFiles.keys().reduce((modules, modulePath) => { const value = zhModulesFiles(modulePath); modules = { ...modules, ...value.default }; return modules; }, {}); export default zhLang; locales/lang/enLocale.js文件main.js引入import { initI18n } from "@/locales/i18n"; const i18n = initI18n(Cookies.get('language') || 'en', "en"); new Vue({ el: '#app', router, store, i18n, render: h => h(App) })

vue 项目启动报错：Syntax Error: Unexpected token 的解决方法
type: item
date: 2022-11-02T11:09:19+08:00
description: vue项目根目录新增配置文件 .babelrc{ "presets": [ "stage-2" ] } 修复好 Syntax Error: Unexpected token 启动发现又报如下问题Failed to compile with 9 errors Module build failed: Error: No PostCSS Config found in: D:\project\ 根目录新建postcss.config.js/** * Created by liweiliang 406320591@QQ.com on 2022/11/1 14:10. */ module.exports = { plugins: { autoprefixer: {browsers: 'last 5 version'} } }

vue-pdf使用demo
type: item
date: 2022-10-26T09:44:00+08:00
description: <el-button-group> <el-button type="primary" icon="el-icon-arrow-left" size="small" @click="prePage">上一页</el-button> <el-button type="primary" size="small" @click="nextPage">下一页</el-button> </el-button-group> {{ currentPage }} / {{ pageCountNum }} <pdf :page="currentPage" :src="pdfUrl" @progress="loadedRatio = $event" @num-pages="pageCountNum = $event" ></pdf>

jszip demo
type: item
date: 2022-04-01T14:17:37+08:00
description: 安装包 jszip和file-saver代码 downloadZip

vue-quill-editor 简单配置demo
type: item
date: 2022-04-01T14:11:16+08:00
description: 项目main.js文件引入import VueQuillEditor from 'vue-quill-editor' // require styles import 'quill/dist/quill.core.css' import 'quill/dist/quill.snow.css' import 'quill/dist/quill.bubble.css' Vue.use(VueQuillEditor, /* { default global options } */) /* eslint-disable no-new */ new Vue({ el: '#app', router, components: { App,VueQuillEditor }, //组件中注册 template: '<App/>' }) 新建一个editor-demo.vue文件，下面注释部分是局部引入方法 <quill-editor v-model="content" ref="myQuillEditor" :options="editorOption" @blur="onEditorBlur($event)"> </quill-editor> 保存 {{storageCont}}

[Vue warn]: Failed to resolve directive: ant-portal (found in <Anonymous>)
type: item
date: 2021-12-10T09:42:05+08:00
description: 最近在各种魔改一个老项目，遇到了一个这样的错误Ant Design Vue 局部引入 Modal 组件方式import {Row, Col, Button, Collapse, Icon, Modal, Input} from "ant-design-vue"; components: { AButton: Button, AInput: Input, ACollapse: Collapse, ACollapsePanel: Collapse.Panel, AIcon: Icon, AModal: Modal }, 开始看到 directive 以为写的自定义指令有问题，后来查了下是由于modal局部引用导致的，所有要把Modal已use的方式来注册就好了，代码如下import Vue from 'vue' import {Modal} from "ant-design-vue"; Vue.use(Modal)

vConsole - 移动端开发调试利器
type: item
date: 2021-10-27T11:35:00+08:00
description: 最近老搞移动端开发，赶脚调试起来很不方便，然后就发现了腾讯开源的vConsolevConsole是一个轻量、可拓展、针对手机网页的前端开发者调试面板。特性查看 console 日志查看网络请求查看页面 element 结构查看 Cookies、localStorage 和 SessionStorage手动执行 JS 命令行自定义插件上手方法一：使用 npm（推荐）$ npm install vconsole Import 并初始化后，即可使用 console.log 功能，如 Chrome devtools 上一样。import VConsole from 'vconsole'; const vConsole = new VConsole(); // 或者使用 options 选项初始化 const vConsole = new VConsole({ maxLogNumber: 1000 }); // 接下来即可照常使用 `console` 等方法 console.log('Hello world'); // 结束调试后，可移除掉 vConsole.destroy(); 方法二：使用 unpkg 的 CDN 直接插入到 HTML 详细使用方法请参阅使用教程。http://wechatfe.github.io/vconsole/demo.html文档vConsole 本体：使用教程公共属性及方法辅助函数插件：插件：入门插件：编写插件插件：Event 事件列表第三方插件列表vConsole-sourcesvconsole-webpack-pluginvconsole-stats-pluginvconsole-vue-devtools-pluginvconsole-outputlog-pluginvite-plugin-vconsole

Vue style scoped 使用@import引入css, 作用域是全局的解决方案
type: item
date: 2021-10-13T10:55:00+08:00
description: 这两天有开始搞华为VOLTE第二版了，偷懒样式直接@import，这时发现第一版样式全服错乱，查看了下是在使用@import引入css的时候，css-loader对import的文件会当做外部资源来编译造成它变为全局样式案例 修改成 注意：如果想要额外增加样式需要单独写个style，如果在 中增加样式将不生效所以最后改成下面效果，当然你也可以直接写到mian.css里面

vue 组件中动态引入外部js库
type: item
date: 2021-09-24T11:11:00+08:00
description: 最近开发项目在和华为Volte做对接，结果华为volte第一版还是原生加jquery来实现的，由于里面有不少需要引入外部js文件的，就给了一天的时间做对接，没办法只能剑走偏锋了首先定义一个 utils/loadScript.js 封装一个动态加载js文件的方法export function loadScript (url) { return new Promise((resolve, reject) => { const script = document.createElement('script') script.onload = () => resolve() script.onerror = () => reject(new Error(`Load script from ${url} failed`)) script.src = url const head = document.head || document.getElementsByTagName('head')[0] ;(document.body || head).appendChild(script) }) } 然后定义一个 callVoLte.js文件供vue文件引入调用的/** * Created by liweiliang 406320591@QQ.com on 2022-01-12 10:59. */ import { loadScript } from '@/utils/loadScript' const RESOURCE_LIST = [ "https://huawei-volte-v2.oss-cn-beijing.aliyuncs.com/sdk_lib/tools/jquery/jquery-3.1.1.js", "https://huawei-volte-v2.oss-cn-beijing.aliyuncs.com/sdk_lib/tools/jquery/jquery-query.js", "https://huawei-volte-v2.oss-cn-beijing.aliyuncs.com/sdk_lib/tools/jquery/jquery.cookie.js", "https://huawei-volte-v2.oss-cn-beijing.aliyuncs.com/sdk_lib/tools/jquery/jquery.json-2.3.min.js", "https://huawei-volte-v2.oss-cn-beijing.aliyuncs.com/sdk_lib/tools/jquery/jquery.utils.js", "https://huawei-volte-v2.oss-cn-beijing.aliyuncs.com/sdk_lib/tools/jquery/jquery.md5.js", "https://huawei-volte-v2.oss-cn-beijing.aliyuncs.com/sdk_lib/tools/pop/jquery-translucent.js", "https://huawei-volte-v2.oss-cn-beijing.aliyuncs.com/sdk_lib/ams/reconnecting-websocket.min.js", "https://huawei-volte-v2.oss-cn-beijing.aliyuncs.com/sdk_lib/ams/websocket.js", "https://huawei-volte-v2.oss-cn-beijing.aliyuncs.com/sdk_lib/ams/ams-utils.js", "https://huawei-volte-v2.oss-cn-beijing.aliyuncs.com/sdk_lib/ams/xnams-websocket.js", "https://huawei-volte-v2.oss-cn-beijing.aliyuncs.com/sdk_lib/rtcjs/rest-api.js", "https://huawei-volte-v2.oss-cn-beijing.aliyuncs.com/sdk_lib/rtcjs/socket.io.js", "https://huawei-volte-v2.oss-cn-beijing.aliyuncs.com/sdk_lib/rtcjs/adapter-7.0.0.js", "https://huawei-volte-v2.oss-cn-beijing.aliyuncs.com/sdk_lib/rtcjs/rtc.min.js", "h…

never reassigned. Use 'const' instead prefer-const
type: item
date: 2021-08-06T16:05:03+08:00
description: 最近在搞vue3+Typescript脚手架然后在定义变量的时候报错 'name' is never reassigned. Use 'const' instead prefer-const 大概意思就是 标识符'errMsg'永远不会被重新分配;使用'const'而不是'let'。(prefer-const)解决方法就是在eslint配置文件或者tslintt配置文件增加{ "rules":{ "prefer-const": "off" } }

Pinia 快速入门
type: item
date: 2021-08-06T14:12:00+08:00
description: Pinia 是什么?Pinia 是一个用于 Vue 的状态管理库，类似 Vuex, 是 Vue 的另一种状态管理方案Pinia 支持 Vue2 和 Vue3常见问题关于该项目和可能问题的几点说明：问：这是否取代了Vuex，是它的继任者吗？答：不，或者至少这不是主要意图问：动态模块呢？答：动态模块不是安全的类型，因此我们允许创建不同的商店，可以在任何地方导入Pinia 优势符合直觉，易于学习极轻， 仅有 1 KB模块化设计，便于拆分状态安装 Piniayarn add pinia@next # or with npm npm install pinia@next 用法创建一个 pinia（根存储）并将其传递给应用程序：import { createPinia } from 'pinia'; app.use(createPinia()); 核心概念与基本使用StoreStore 是一个保存状态和业务逻辑的实体，可以自由读取和写入，并通过导入后在 setup 中使用创建一个 store// store.js import { defineStore } from "pinia"; interface MainState { counter: number name: string } export const useMainStore = defineStore({ // id: 必须的，在所有 Store 中唯一 id: "main", // a function that returns a fresh state state: () => MainState ({ counter: 0, name: 'Eduardo', }), // optional getters getters: { doubleCount() { return this.counter * 2 }, // use getters in other getters doubleCountPlusOne() { return this.doubleCount * 2 + 1 }, }, // optional actions actions: { reset() { // `this` is the store instance this.counter = 0 }, }, }) 使用 Store// xxx.vue {{store.count}}

Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: No "exports" main defined in D:\project\saas-platform-pc\node_modules\@babel\helper-compilation-targets\package.json
type: item
date: 2021-07-06T11:03:42+08:00
description: 原因：可能是node版本导致引入依赖时bable配置问题。解决办法修改对应文件 node_modules\@babel\helper-compilation-targets\package.json 48行的 “exports”：false 为{ ".": "./lib/index.js" },

vue for循环中按顺序axios请求拿到每条数据对应的状态
type: item
date: 2021-03-10T17:39:00+08:00
description: 在循环数组的时候基于每个对象中的某个参数来进行数据请求，获取当前对象对应的数据状态实现方法基于最新的es6中的async await 来实现首先要把对应的Promise方法进行一个封装_getReportStatus(item){ return new Promise((resolve, reject) => { getReportStatus({reportCode:item.reportNo}).then(data => { if(data.data.code == '0000'){ resolve(data.data.result.taskState); } }) }); }, 然后利用async 来调取async getReportStatus(result){ for (let item of result){ item.taskState = await this._getReportStatus(item); } app.globalData.caseList = result wx.navigateTo({ url: "../progressQuery/progressQuery", }); }, 如果循环中需要用到多个请求的话最后可以加一个 Promise.all 来进行数据解析，还有需要注意的async 中使用 await定义的方法，只能用for，那么为什么不能用forEach,map等方法呢，原因很简单那就是 forEach,map等是一个同步方法，真正要实现异步返回就需要用for of .

使用自定义指令directive如何修改v-model绑定的键值对
type: item
date: 2021-02-02T19:53:37+08:00
description: 主要语句 vnode.elm.dispatchEvent(new CustomEvent('input'));/** * Created by liweiliang 406320591@QQ.com on 2021/01/26 23:04. */ import pattern from '@/utils/pattern' let amountCheck = function (vnode, binding, el) { // console.log(el, vnode, binding) let reopenState = binding.modifiers.reopen; if (!reopenState && !pattern.twoDecimal.test(el.target.value)) { vnode.context.$message.error('输入错误,已重置成最后一次输入正确的值') el.target.value = el.target.oldValue; vnode.elm.dispatchEvent(new CustomEvent('input')); } else if (reopenState && !pattern.twoDecimalReopen.test(el.target.value)) { vnode.context.$message.error('输入错误,已重置成最后一次输入正确的值') el.target.value = el.target.oldValue; vnode.elm.dispatchEvent(new CustomEvent('input')); } } export default { directiveName: 'amounts', bind (el, binding, vnode, oldVnode) { // console.log(el, binding, vnode, oldVnode) if (el.nodeName != 'INPUT') return el.addEventListener('blur', amountCheck.bind(this, vnode, binding)) }, componentUpdated (el, binding, vnode, oldVnode) { console.log(binding.name, 'value', binding.value, 'oldValue', binding.oldValue) console.log(pattern) if (binding.modifiers.reopen) { if (pattern.twoDecimalReopen.test(binding.value)) { el.oldValue = binding.value } else if (pattern.twoDecimalReopen.test(binding.oldValue)) { el.oldValue = binding.oldValue } } else if (pattern.twoDecimal.test(binding.value)) { el.oldValue = binding.value } else if (pattern.twoDecimal.test(binding.oldValue)) { el.oldValue = binding.oldValue } }, unbind (el, binding, vnode, oldVnode) { el.removeEventListener('blur', amountCheck.bind(this, vnode)) } };

Ant Design of Vue —— Table表格组件 —— 设置动态表头
type: item
date: 2020-11-27T13:49:19+08:00
description: Column配置比如：操作列{ key: 'action', scopedSlots: { customRender: 'action', title: '变量名' }, align: 'center' } 代码段 {{动态表头名称}} demo: 注意不要在括号 dataIndex同级节点加title属性名，否则的话scopedSlots设置的title会失效//Column { dataIndex: 'belong', key: 'belong', width:'8.33333333%', scopedSlots: {customRender: 'belong',title:'belongTitle'} } //template {{belongTitle}}

vue-baidu-map or 百度地图API 禁止点击时弹出地址详情的方法
type: item
date: 2020-10-22T09:51:00+08:00
description: 首先来说 百度地图默认的api，通过查看接口文当 中 MapOptions -> enableMapClick:是否开启底图可点功能，默认启用new BMap.Map(mapid,{enableMapClick:false});在vue-baidu-map中，上面这个方法是无效的通过查看源码发现需要在baidu-map上添加个:mapClick="false" 就可以了官方文档：https://dafrok.github.io/vue-baidu-map/#/zh/index

antdv Modal this.$confirm对话框 使用vnode修改标题icon问题
type: item
date: 2020-10-21T17:40:12+08:00
description: icon 自定义图标（1.14.0 新增） string|()=>VNode 一、利用自带的icon赋值个默认的icon名字就可以了，但是有时候我们需要用到实底风格的icon，所以只能用()=>VNodethis.$confirm({ title: '确认设置当前位置为出险地点?', content: this.infoWindow.contents, icon: 'exclamation-circle', onOk: () => { this.onMapClose(); console.log('点击确认') }, onCancel() { }, }); 二、通过()=>VNode修改this.$confirm({ title: '确认设置当前位置为出险地点?', content: this.infoWindow.contents, icon: () => this.$createElement('a-icon', { props: { type: 'exclamation-circle', theme: 'filled' }, }), onOk: () => { this.onMapClose(); console.log('点击确认') }, onCancel() { }, });

Warning: [antdv: Each record in table should have a unique `key` prop,or set `rowKey` to an unique primary key.]
type: item
date: 2020-10-19T17:21:51+08:00
description: Warning: [antdv: Each record in table should have a unique key prop,or set rowKey to an unique primary key.] 使用 Ant Design的时候报key警告，这由于columns中定义的默认key值在返回的数据中没有当前的这个字段造成的，一个是使用rowKey默认指定一个对应的键值对，或者使用类似v-for循环中的下标index来代替:rowKey="(record,index)=>{return index}"

vue 报错 You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.
type: item
date: 2020-09-29T10:07:00+08:00
description: 最近试了下 Vue.extend 方法，写好后发现访问会报如下错误vue.runtime.esm.js?2b0e:619 [Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.接下来我们分析下报错的原因在哪里和解决办法原因vue有两种形式的代码 compiler（模板）模式和runtime模式（运行时），vue模块的package.json的main字段默认为runtime模式， 指向了"dist/vue.runtime.common.js"位置。这是vue升级到2.0之后就有的特点。解决方法在vue.config中增加个配置就可以了runtimeCompiler: true

Vue父子组件生命周期执行顺序及钩子函数的个人理解（转载）
type: item
date: 2020-09-24T10:02:00+08:00
description: 先附一张官网上的vue实例的生命周期图，每个Vue实例在被创建的时候都需要经过一系列的初始化过程，例如需要设置数据监听，编译模板，将实例挂载到DOM并在数据变化时更新DOM等。同时在这个过程中也会运行一些叫做生命周期钩子的函数(回调函数)，这给了用户在不同阶段添加自己代码的机会。1、vue的生命周期图在vue实例的整个生命周期的各个阶段，会提供不同的钩子函数以供我们进行不同的操作。先列出vue官网上对各个钩子函数的详细解析。生命周期钩子详细beforeCreate在实例初始化之后，数据观测(data observer) 和 event/watcher 事件配置之前被调用。created实例已经创建完成之后被调用。在这一步，实例已完成以下的配置：数据观测(data observer)，属性和方法的运算， watch/event 事件回调。 在执行data()方法前props属性有数据已经可以访问，watch和computed监听函数此时为null，此时this.computed里的计算属性值为undefined。 data函数执行完后，watch和computed监听函数才可用，因为data函数执行完后，data函数return的属性这时才可用。然而，挂载阶段还没开始，$el 属性目前不可见。beforeMount在挂载开始之前被调用：相关的 render 函数首次被调用。mountedel 被新创建的 vm.$el 替换，并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素，当 mounted 被调用时 vm.$el 也在文档内。beforeUpdate数据更新时调用，发生在虚拟 DOM 重新渲染和打补丁之前。你可以在这个钩子中进一步地更改状态，这不会触发附加的重渲染过程。updated由于数据更改导致的虚拟 DOM 重新渲染和打补丁，在这之后会调用该钩子。当这个钩子被调用时，组件 DOM 已经更新，所以你现在可以执行依赖于 DOM 的操作。activatedkeep-alive 组件激活时调用。deactivatedkeep-alive 组件停用时调用。beforeDestroy实例销毁之前调用。在这一步，实例仍然完全可用。destroyedVue 实例销毁后调用。调用后，Vue 实例指示的所有东西都会解绑定，所有的事件监听器会被移除，所有的子实例也会被销毁。2、实际操作下面我们在实际的代码执行过程中理解父子组件生命周期创建过程以及钩子函数执行的实时状态变化。测试基于下面的代码，引入vue.js文件后即可执行。（打开页面后，再按一次刷新会自动进入debugger状态） Document {{message}} <keep-alive> <my-components :msg="msg1" v-if="show"></my-components> </keep-alive> 3.1、生命周期调试首先我们创建了一个Vue实例vm，将其挂载到页面中id为“app”的元素上。3.1.1、根组件的beforeCreate阶段可以看出，在调用beforeCreate()函数时，只进行了一些必要的初始化操作（例如一些全局的配置和根实例的一些属性初始化），此时data属性为undefined，没有可供操作的数据。3.1.2、根组件的Created阶段调用Created()函数，在这一步，实例已完成以下的配置：数据代理和动态数据绑定(data observer)，属性和方法的运算， watch/event 事件回调。然而，挂载阶段还没开始，$el 属性目前不可见。3.1.3、根组件的beforeMount阶段在调用boforeMount()函数前首先会判断对象是否有el选项。如果有的话就继续向下编译，如果没有el选项，则停止编译，也就意味着停止了生命周期，直到在该vue实例上调用vm.$mount(el)在这个例子中，我们有el元素，因此会调用boforeMount()函数,此时已经开始执行模板解析函数，但还没有将$el元素挂载页面，页面视图因此也未更新。在标红处，还是 {{message}}，这里就是应用的 Virtual DOM（虚拟Dom）技术，先把坑占住了。到后面mounted挂载的时候再把值渲染进去。3.1.4、子组件的beforeCreate、Created、beforeMount、Mounted阶段在父组件执行beforeMount阶段后，进入子组件的beforeCreate、Created、beforeMount阶段，这些阶段和父组件类似，按下不表。beforeMount阶段后，执行的是Mounted阶段，该阶段时子组件已经挂载到父组件上，并且父组件随之挂载到页面中。由下图可以知道，在beforeMount…

moment.js常用时间差
type: item
date: 2020-07-17T13:19:02+08:00
description: 利用moment.js来实现距离某个时间的时间差，写了个过滤方法filterTaskTime(params){ let x=moment(params); let y=moment(); //当下时间 let duration = moment.duration(y.diff(x,'ms')); //做差 let days = duration.get('days'); let hours = duration.get('hours'); let mins = duration.get('minutes'); let ss = duration.get('seconds'); console.log(days,hours,mins,ss) return days + '天' + hours + '小时' + mins +'分钟' + ss +'秒'; },

图片转base64 方法
type: item
date: 2020-05-16T14:54:13+08:00
description: blobToBase64(blob) {return new Promise((resolve, reject) => { const fileReader = new FileReader(); fileReader.onload = (e) => { resolve(e.target.result); }; fileReader.readAsDataURL(blob); fileReader.onerror = () => { reject(newError('文件流异常')); }; });},使用方法：this.blobToBase64(file).then(data => { console.log(data) }).catch(error => { console.log(error); })