关于vue.js:axios模块化封装实例化和vue本地解决跨域

1.开发环境 vue+axios+typescript+eslint+prettier2.电脑系统 windows10专业版3.在应用vue开发的过程中,咱们在数据交互的过程中,个别会抉择应用axios,很多小伙伴都在应用,上面我来分享一下axios封装和vue开发解决跨域。4.装置axios npm i axios -S4-1.后端接口如下: 主机一:http://192.168.0.103:8020 接口: /api/login主机二: http://192.168.0.103:3000 接口: /chen5.在根目录下,新建文件,目录构造如下: ----src----.env.development----.env.production----.env.test5-1 .env.development代码如下: NODE_ENV = 'development'//指定以后环境模式VUE_APP_CURRENTMODE = 'development'VUE_APP_BASE_URL = "http://192.168.0.103:8020"VUE_APP_BASE_PL="http://192.168.0.103:3000"VUE_APP_BASE_PLAPI="/chen"VUE_APP_BASE_API="/api"6.在src录下,新建network文件夹,目录构造如下: ----src-----network------Instances(实例汇合)-------index.ts(引入实例)-------Instance1.ts(实例1)-------Instance2.ts(实例2)------api.js(接口封装)6-1.Instances下Instance1.ts代码如下: import axios from "axios";export const Instance1 = (config: Object) => { const instance = axios.create({ baseURL: process.env.VUE_APP_BASE_PLAPI, timeout: 900000, }); instance.interceptors.request.use( (config) => { if (config.method === "get") { config.url = config.url + "?" + config.data; } if (sessionStorage.getItem("Authorization")) { config.headers.Authorization = "auth " + sessionStorage.getItem("Authorization"); } // //console.log("申请拦挡胜利啦"); // //console.log(config); return config; }, (err) => { console.log("申请失败啦"); console.log(err); } ); // instance.interceptors.response.use( (res) => { return res.data; }, (err) => { console.log("响应失败"); console.log(err); // return err; } ); return instance(config);};6-2.Instances下Instance2.ts代码如下: ...

August 19, 2021 · 2 min · jiezi

关于vue.js:CRMEB多商户二开-–-自定义组合数据

本文给大家介绍CRMEB多商户如何创立,保护,应用组合数据性能. 创立组合数据规定先找到组合数据管理页面,点击增加组合数据按钮 创立组合数据规定, 这里以首页banner数据为例 先填写组合数据信息并设置一个惟一的 key 设置字段规定, 例如首页banner须要一个图片字段和一个跳转链接字段 编辑好之后点击确定按钮即可创立胜利 增加数据编辑菜单先找到刚刚增加的组件数据规定的 id, 例如72 进入菜单治理页面,在对应的菜单下增加子菜单, 编辑数据页面的链接为/promoter/bank/72. 72是刚刚新增加的组合数据规定的 id 增加后新页面就会在对应的菜单下 在代码中获取组合数据的值在代码中通过 systemConfig公共办法获取 例如: $banner = systemConfig(‘home_banner’); 以上就是组合数据的应用形式 如果你感觉这篇文章对你有点用的话,麻烦请给咱们的开源我的项目点点star:http://github.crmeb.net/u/defu 不胜感激 !

August 19, 2021 · 1 min · jiezi

关于vue.js:vue两种方式实现用户长时间不操作退出到登录页

问题形容产品说,出于平安思考,用户长时间不操作,就回到登录页面,让用户从新登录,就像银行的app一样。本文就记录一下实现这种成果的两种形式,别离是前端管制和后端管制,各有细节及实用应用场景 前端管制(形式一)思路首先,用户长时间不操作具体表现形式是啥?其实就是事件是否长时间没有被触发执行。 比方用户长时间不操作,就没有鼠标点击(click)事件、鼠标滚轮(mousewheel)事件、鼠标挪动(mousemove)事件之类的,咱们只须要监听这些事件,如果这些事件长时间没有触发,就阐明用户长时间未操作,而后路由跳转到登录页面即可。 这三个事件我抉择的是比拟实用的鼠标点击事件,咱们晓得,一般来说我的项目的第一个页面是登录页面,所以在登录页面用户点击登录按钮的时候,就记录一下点击登录按钮的工夫,存储到sessionstorage中去,当跳转到主页面的时候,当用户每点击一次页面,就更新一下sessionstorage中的存储的工夫,同时也给页面绑定一个循环定时器,距离一段时间就把以后工夫和sessionstorage贮存的上一次点击事件的工夫做一个差值比照,当差值超过肯定工夫,就强制用户退出到登录页面即可。 代码login.vue页面 // html<el-button type="primary" @click="loginIn">点击登录</el-button>// jsmethods: { loginIn() { // 存第一份点击的工夫 sessionStorage.setItem("lastClickTime", new Date().getTime()); // 模仿后端返回存一个token sessionStorage.setItem('token',"token") this.$router.push({ path: "/", }); },}Home.vue页面 <template> <div class="homeBox"> <!-- 右边是菜单层级 --> <div class="left"> <div class="leftNav"> <el-menu :default-active="activeIndex" class="elMenu" background-color="#333" text-color="#B0B0B2" active-text-color="#fff" :unique-opened="true" router ref="elMenu" > <el-menu-item index="/vue"> <i class="el-icon-location-outline"></i> <span slot="title">vue页面</span> </el-menu-item> <el-menu-item index="/react"> <i class="el-icon-star-off"></i> <span slot="title">react页面</span> </el-menu-item> <el-menu-item index="/angular"> <i class="el-icon-pear"></i> <span slot="title">angular页面</span> </el-menu-item> </el-menu> </div> </div> <!-- 左边是视图层级 --> <div class="right"> <div class="rightTop"> <el-button type="primary" plain @click="loginOut">登出</el-button> </div> <div class="rightBottom"> <router-view></router-view> </div> </div> </div></template><script>export default { name: "Home", data() { return { activeIndex: this.$route.path, timer: null, }; }, created() { /* 第一步: 组件初始化加载就绑定监听点击事件,留神:addEventListener的第三个参数,这里要加上。 因为第三个参数决定了是冒泡还是捕捉(false冒泡默认,true捕捉),因为绑定监听点击事件,咱们是在最 顶层的DOM地位进行捕捉点击事件,所以第三个参数true,要加上的,这样的话,内层的任意中央的点击事件 咱们就都能监听到了,而后存储一下点击的工夫 */ window.addEventListener( "click", () => { // 为了不便,咱们把点击事件的工夫间接存到sessionStorage中去,这样不便获取比拟 sessionStorage.setItem("lastClickTime", new Date().getTime()); }, true ); }, mounted() { /* 第二步: 组件初始化加载时也要绑定一个定时器,通过定时器定时轮询,去比照以后工夫和上次点击的工夫的差值 */ this.isTimeOut(); }, methods: { isTimeOut() { // 应用定时器之前,要革除一下定时器 clearInterval(this.timer); this.timer = setInterval(() => { let lastClickTime = sessionStorage.getItem("lastClickTime") * 1; // 把上次点击时候的字符串工夫转换成数字工夫 let nowTime = new Date().getTime(); // 获取以后工夫 console.log("以后工夫和之前点击工夫", nowTime, lastClickTime); // 假如咱们需要是:5秒钟不进行点击操作,就提醒登录退出 if (nowTime - lastClickTime > 1000 * 5) { // 提醒一下用户 this.$message({ type: "warning", message: "超时了,已退出登录" }); // 这里要革除定时器,结束任务 clearInterval(this.timer); // 最初返回到登录页 this.$router.push({ path: "/login" }); } }, 1000); }, }, beforeDestroy() { // 最初一步,来到页面的时候,革除一下定时器,也解绑点击事件 clearInterval(this.timer); window.removeEventListener("click", () => {}, true); },};</script>这里留神一下,层级对应关系,我我的项目搭建的层级关系是Home.vue页面是App.vue页面的外面一层,也有对应的视图,视图对应的也是整个页面的关系。依据层级和路由表路由视图router-view关系,抉择适合的层级去绑定对应的点击事件和定时器即可。 ...

August 19, 2021 · 2 min · jiezi

关于vue.js:crmeb单商户pro15一键换色

在原有的五套主题色调上减少: 一、后盾设置: 门路:crmeb1.5\src\pages\setting\themeStyle 例如:增加一个青色主题色调的 <Radio :label="6" border class="box orange">青色</Radio> 对应上面显示的效果图你能够在前台截取,在data外面提前定义,如图: 对应的切换成果定义(将你data外面新定义的增加进去): changeColor(e){ switch(e){ case 1: this.picList = this.picListBule; break; case 2: this.picList = this.picListGreen; break; case 3: this.picList = this.picListRed; break; case 4: this.picList = this.picListPink; break; case 5: this.picList = this.picListOrange; break; default: break}} 注:数据配置(后盾crmeb1.5\src\pages\system\group)、集体核心也是相似办法(后盾crmeb1.5\src\pages\setting\devise) 二、挪动端设置: 门路:crmebPro1.5/App.vue 定义你的主题色调: 增加主色调: 阐明: --view-theme:主题色;--view-priceColor:价格色;--view-minorColor和--view-minorColorT:辅助色;--view-bntColor:按钮色; 注: 首先主题色与价格色调定义好,--view-minorColorT色值为主题色的0.1的透明度; --view-minorColor色值也是在主题色的根底上淡化,--view-bntColor次要用于有左右按钮的,个别左边为主题色,右边按钮为此色彩; 对于砍价列表和砍价详情图片(因为此图片没方法用代码写,需自行添加): 门路:crmebPro1.5/pages/activity/goods_bargain/index.vue crmebPro1.5/pages/activity/goods_bargain_details/index.vue要是想要用现有的图片也是能够的,目前除了现有的五套对应的图片,在不没有对应图片的前提下,默认的是激情红,你也能够进行批改 例如: 默认(激情红): default: this.picUrl = picList[2] ...

August 18, 2021 · 1 min · jiezi

关于vue.js:javascript截取video视频第一帧作为封面方案

写在前边:因为我的项目是用vue.js框架实现,所以以下代码是vue.js语法。 首先,看一下Dom元素(video相干属性和事件): <video @loadeddata="createPreImg($event)" // loadeddata事件示意media中的首帧曾经加载 class="content-video" :src="item.videoUrl" // 视频地址(能够是以后域下的,也能够是其余域下的) crossorigin="anonymous" // 容许跨域(因为浏览器的同源策略,如果视频是其余域,须要设置此属性) preload="auto" // 预加载(挪动端须要设置此属性,因为挪动端有很多播放限度,很多都不会主动加载)></video>其次,是javascript局部代码: createPreImg(event) { // event js原生事件 const videoEle = event.target; // 以后video dom节点 videoEle.currentTime = 1; // 设置视频开始播放工夫(因为有些手机第一帧显示黑屏,所以这里选取视频的第一秒作为封面) videoEle.addEventListener('canplay', function () { // 监听video的canplay事件 // 创立canvas元素 并设置canvas大小等于video节点的大小 const canvas = document.createElement('canvas'); const scale = 0.8; // 压缩系数 canvas.width = videoEle.videoWidth * scale; canvas.height = videoEle.videoHeight * scale; // canvas画图 canvas.getContext('2d').drawImage(videoEle, 0, 0, canvas.width, canvas.height); // 把canvas转成base64编码格局 const imgSrc = canvas.toDataURL('image/png'); // 创立img元素 插入到文档中 const img = document.createElement('img'); img.src = imgSrc; img.style.position = 'absolute'; img.style.left = '0'; img.style.top = '0'; img.style.objectFit = 'cover'; videoEle.parentNode && videoEle.parentNode.appendChild(img); }); }通过测试,在小米手机Mix2机型上,能够展现封面; ...

August 18, 2021 · 1 min · jiezi

关于vue.js:crudapi增删改查接口零代码产品成功案例之金茶王投票系统

crudapi增删改查接口零代码产品胜利案例之金茶王投票系统简介2020年因为疫情起因,金茶王投票流动改成线上云投票,所以须要一套投票系统进行较量。参赛选手包含两种类型,别离为餐厅和徒弟,投票通过微信公众号页面进行,为了避免舞弊,每人每天能够为3位徒弟和3个餐厅投票,投票持续时间为一个星期,最终依据票数进行排名。 UI界面原型 技术框架我的项目采纳前后端拆散的形式,数据库采纳MySql,后端API采纳Java+Spring boot,前端H5采纳Vue+Quasar, 因为该我的项目业务逻辑次要就是根本表单的crud增删改查,所以非常适合用crudapi进行二次开发,通过配置实现RESTful API和后盾治理Web,前端H5页面独自定制开发即可。 数据库表单次要业务表单包含候选人(包含徒弟和餐厅),赛区,投票流动,流动报名,投票记录等 不同表之间建设表关联 徒弟和餐厅共用候选人candidate表,依据类型type字段进行辨别,restaurant示意餐厅,chef示意徒弟。 投票记录voteLog表,通过唯一性索引uq_vote_log_token限度刷票 蕴含设计表单到配置,工作量大略一个小时左右。 后端API表单和表关系配置好了,对应的crud增删改查RESTful API也就主动生成了,后端根本实现了80%工作量,而后再集成微信主动登录和阿里云OSS图片上传,残余工作2天之内实现, 后盾治理Web用处次要是管理员编辑餐厅、徒弟信息、查看投票后果和导出数据,crudapi默认页面曾经根本满足需要。 前端H5定制开发,15个工作日实现开发和测试。 小结本文次要介绍了金茶王投票系统,利用了crudapi增删改查接口零代码产品进行二次开发,节约了大量工夫,总共开发工夫18人天。最终按时并高质量实现工作,2020国内金茶王大赛圆满成功。 名称采纳框架类型工夫Java APIcrudapiJava SDK集成3天后盾治理Webcrudapi-admin-web间接应用产品0天前端H5Vue + Quasar定制15天附crudapi产品简介crudapi是crud+api组合,示意增删改查接口,是一款零代码可配置的产品。应用crudapi能够辞别枯燥无味的增删改查代码,让您更加专一业务,节约大量老本,从而进步工作效率。crudapi的指标是让解决数据变得更简略,所有人都能够收费应用!无需编程,通过配置主动生成crud增删改查RESTful API,提供后盾UI治理业务数据。基于支流的开源框架,领有自主知识产权,反对二次开发。 demo演示crudapi属于产品级的零代码平台,不同于主动代码生成器,不须要生成Controller、Service、Repository、Entity等业务代码,程序运行起来就能够应用,真正0代码,能够笼罩根本的和业务无关的CRUD RESTful API。 官网地址:https://crudapi.cn 测试地址:https://demo.crudapi.cn/crudapi/login 源码地址GitHub地址 https://github.com/crudapi/crudapi-admin-webGitee地址 https://gitee.com/crudapi/crudapi-admin-web因为网络起因,GitHub可能速度慢,改成拜访Gitee即可,代码同步更新。

August 18, 2021 · 1 min · jiezi

关于vue.js:eltreeselect

<!-- /** * 树形下拉抉择组件,下拉框展现树形构造,提供抉择某节点性能,不便其余模块调用 * @author ljn * @date 2019-04-02 * 调用示例: * <tree-select :height="400" // 下拉框中树形高度 * :width="200" // 下拉框中树形宽度 * size="small" // 输入框的尺寸: medium/small/mini * :data="data" // 树结构的数据 * :defaultProps="defaultProps" // 树结构的props * multiple // 多选 * clearable // 可清空抉择 * collapseTags // 多选时将选中值按文字的模式展现 * checkStrictly // 多选时,严格遵循父子不相互关联 * :nodeKey="nodeKey" // 绑定nodeKey,默认绑定'id' * :checkedKeys="defaultCheckedKeys" // 传递默认选中的节点key组成的数组 * @popoverHide="popoverHide"> // 事件有两个参数:第一个是所有选中的节点ID,第二个是所有选中的节点数据 * </tree-select> */--><template> <div> <div class="mask" v-show="isShowSelect" @click="isShowSelect = !isShowSelect"></div> <el-popover placement="bottom-start" :width="width" trigger="manual" v-model="isShowSelect" @hide="popoverHide"> <el-tree class="common-tree" :style="style" ref="tree" :data="data" :props="defaultProps" :show-checkbox="multiple" :node-key="nodeKey" :check-strictly="checkStrictly" default-expand-all :expand-on-click-node="false" :check-on-click-node="multiple" :highlight-current="true" @node-click="handleNodeClick" @check-change="handleCheckChange" ></el-tree> <el-select :style="selectStyle" slot="reference" ref="select" :size="size" v-model="selectedData" :multiple="multiple" :clearable="clearable" :collapse-tags="collapseTags" @click.native="isShowSelect = !isShowSelect" @remove-tag="removeSelectedNodes" @clear="removeSelectedNode" @change="changeSelectedNodes" class="tree-select"> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option> </el-select> </el-popover> </div></template> <script>export default { name: 'tree-select', props: { // 树结构数据 data: { type: Array, default () { return []; } }, defaultProps: { type: Object, default () { return {}; } }, // 配置是否可多选 multiple: { type: Boolean, default () { return false; } }, // 配置是否可清空抉择 clearable: { type: Boolean, default () { return false; } }, // 配置多选时是否将选中值按文字的模式展现 collapseTags: { type: Boolean, default () { return false; } }, nodeKey: { type: String, default () { return 'id'; } }, // 显示复选框状况下,是否严格遵循父子不相互关联 checkStrictly: { type: Boolean, default () { return false; } }, // 默认选中的节点key数组 checkedKeys: { type: Array, default () { return []; } }, size: { type: String, default () { return 'small'; } }, width: { type: Number, default () { return 250; } }, height: { type: Number, default () { return 300; } } }, data () { return { isShowSelect: false, // 是否显示树状选择器 options: [], selectedData: [], // 选中的节点 style: 'width:' + this.width + 'px;' + 'height:' + this.height + 'px;', selectStyle: 'width:' + (this.width + 24) + 'px;', checkedIds: [], checkedData: [] }; }, mounted () { this.initCheckedData(); }, methods: { // 单选时点击tree节点,设置select选项 setSelectOption (node) { let tmpMap = {}; tmpMap.value = node.key; tmpMap.label = node.label; this.options = []; this.options.push(tmpMap); this.selectedData = node.key; }, // 单选,选中传进来的节点 checkSelectedNode (checkedKeys) { var item = checkedKeys[0]; this.$refs.tree.setCurrentKey(item); var node = this.$refs.tree.getNode(item); this.setSelectOption(node); }, // 多选,勾选上传进来的节点 checkSelectedNodes (checkedKeys) { this.$refs.tree.setCheckedKeys(checkedKeys); }, // 单选,清空选中 clearSelectedNode () { this.selectedData = ''; this.$refs.tree.setCurrentKey(null); }, // 多选,清空所有勾选 clearSelectedNodes () { var checkedKeys = this.$refs.tree.getCheckedKeys(); // 所有被选中的节点的 key 所组成的数组数据 for (let i = 0; i < checkedKeys.length; i++) { this.$refs.tree.setChecked(checkedKeys[i], false); } }, initCheckedData () { if (this.multiple) { // 多选 if (this.checkedKeys.length > 0) { this.checkSelectedNodes(this.checkedKeys); } else { this.clearSelectedNodes(); } } else { // 单选 if (this.checkedKeys.length > 0) { this.checkSelectedNode(this.checkedKeys); } else { this.clearSelectedNode(); } } }, popoverHide () { if (this.multiple) { this.checkedIds = this.$refs.tree.getCheckedKeys(); // 所有被选中的节点的 key 所组成的数组数据 this.checkedData = this.$refs.tree.getCheckedNodes(); // 所有被选中的节点所组成的数组数据 } else { this.checkedIds = this.$refs.tree.getCurrentKey(); this.checkedData = this.$refs.tree.getCurrentNode(); } this.$emit('popoverHide', this.checkedIds, this.checkedData); }, // 单选,节点被点击时的回调,返回被点击的节点数据 handleNodeClick (data, node) { if (!this.multiple) { this.setSelectOption(node); this.isShowSelect = !this.isShowSelect; this.$emit('change', this.selectedData); } }, // 多选,节点勾选状态发生变化时的回调 handleCheckChange () { var checkedKeys = this.$refs.tree.getCheckedKeys(); // 所有被选中的节点的 key 所组成的数组数据 this.options = checkedKeys.map((item) => { var node = this.$refs.tree.getNode(item); // 所有被选中的节点对应的node let tmpMap = {}; tmpMap.value = node.key; tmpMap.label = node.label; return tmpMap; }); this.selectedData = this.options.map((item) => { return item.value; }); this.$emit('change', this.selectedData); }, // 多选,删除任一select选项的回调 removeSelectedNodes (val) { this.$refs.tree.setChecked(val, false); var node = this.$refs.tree.getNode(val); if (!this.checkStrictly && node.childNodes.length > 0) { this.treeToList(node).map(item => { if (item.childNodes.length <= 0) { this.$refs.tree.setChecked(item, false); } }); this.handleCheckChange(); } this.$emit('change', this.selectedData); }, treeToList (tree) { var queen = []; var out = []; queen = queen.concat(tree); while (queen.length) { var first = queen.shift(); if (first.childNodes) { queen = queen.concat(first.childNodes); } out.push(first); } return out; }, // 单选,清空select输入框的回调 removeSelectedNode () { this.clearSelectedNode(); this.$emit('change', this.selectedData); }, // 选中的select选项扭转的回调 changeSelectedNodes (selectedData) { // 多选,清空select输入框时,革除树勾选 if (this.multiple && selectedData.length <= 0) { this.clearSelectedNodes(); } this.$emit('change', this.selectedData); } }, watch: { isShowSelect (val) { // 暗藏select自带的下拉框 this.$refs.select.blur(); }, checkedKeys (val) { if (!val) return; this.checkedKeys = val; this.initCheckedData(); } }};</script> <style scoped> .mask{ width: 100%; height: 100%; position: fixed; top: 0; left: 0; opacity: 0; /* z-index: 11; */ } .common-tree{ overflow: auto; } /* .tree-select{ z-index: 111; } */</style>调用 ...

August 18, 2021 · 4 min · jiezi

关于vue.js:饿了么UI中eltree中的树节点选中高亮的两种常用方式highlightcurrent属性

问题形容咱们晓得树节点经常须要抉择,为了看得更加直观显著,所以咱们须要设置选中的时候,让选中的那个树节点色彩高亮,本文记录一下罕用的三种形式,咱们先看一下效果图 效果图 形式一第一步:el-tree组件标签上增加高亮属性 highlight-current ,示意要开启高亮性能。 第二步:而后在css中深度作用域高亮款式代码即可 <style lang="less" scoped> /deep/ .el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content { // 设置色彩 background-color: #baf !important; }</style>留神这种形式是选中树节点高亮,即:树节点获取焦点是高亮,如果树节点失去焦点,也就是说点击了别的中央仍然是高亮状态,即还保留高亮状态形式二如果是想要那种,选中高亮,不选中就不高亮的成果,咱们独自应用css设置即可,这个时候就不必在树组件上加上highlight-current属性了,间接一句话获取焦点确定即可,如下语句: <style lang="less" scoped> /deep/ .el-tree-node:focus > .el-tree-node__content { background-color: #bfa !important; }</style>上述两种形式都是通过css形式去管制的,咱们也能够通过js形式去管制的,比方默认第一项高亮 指定默认高亮树节点应用el-tree组件的setCurrentKey办法,依据树组件的树节点的惟一id来制订某个树节点高亮。当然要搭配node-key="id"给树节点绑定惟一标识id,同时也要开启高亮模式(加上highlight-current属性),而后形式一设置高亮的色彩款式要加上。初始化加载默认高亮,所以在mounted钩子中书写代码即可。 残缺代码<template> <div class="box"> <el-tree ref="myTree" node-key="id" :data="data" :props="defaultProps" highlight-current > </el-tree> </div></template><script>export default { data() { return { data: [ { name: "西游记", id: "xiyouji", children: [ { name: "孙悟空", id: "sunwukong", children: [ { name: "大猴子", id: "dahouzi", children: [], }, { name: "二猴子", id: "erhouzi", children: [], }, ], }, { name: "猪八戒", id: "zhubajie", children: [], }, { name: "沙和尚", id: "shaheshang", children: [], }, ], }, { name: "水浒传", id: "shuihuzhuan", children: [ { name: "宋江", id: "songjiang", children: [], }, { name: "武松", id: "wusong", children: [], }, ], }, ], defaultProps: { children: "children", label: "name", }, }; }, mounted() { this.$nextTick(function () { this.$nextTick(() => { // myTree 数组件的ref 默认让第一项高亮 // data是树组件对应的数据 // 通过data中的第一项的id找到对应的节点,而后把这个节点设置为高亮 this.$refs.myTree.setCurrentKey(this.data[0].id); }); }); },};</script><style lang="less" scoped>// 设置高亮色彩/deep/ .el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content { background-color: #baf !important;}</style>setCurrentKey办法是通过 key 设置某个节点的以后选中状态,应用此办法必须设置 node-key 属性,因为要确定唯一性,node-key="id"因为个别都是id具备唯一性,所以绑定id。

August 18, 2021 · 1 min · jiezi

关于vue.js:端面试每日-31-第854天

明天的知识点 (2021.08.17) —— 第854天 (我也要出题)[html] html列表共有几种?有什么区别?[css] 应用css3画一个26个英文字母的旋转动画特效[js] JS如何设置获取盒模型的宽和高?[软技能] 你是如何定义程序员的?《论语》,曾子曰:“吾日三省吾身”(我每天屡次检查本人)。前端面试每日3+1题,以面试题来驱动学习,每天提高一点!让致力成为一种习惯,让奋斗成为一种享受!置信 保持 的力量!!! 欢送在 Issues 和敌人们一起探讨学习! 我的项目地址:前端面试每日3+1【举荐】欢送跟 jsliang 一起折腾前端,零碎整顿前端常识,目前正在折腾 LeetCode,打算买通算法与数据结构的任督二脉。GitHub 地址 微信公众号欢送大家前来探讨,如果感觉对你的学习有肯定的帮忙,欢送点个Star, 同时欢送微信扫码关注 前端剑解 公众号,并退出 “前端学习每日3+1” 微信群互相交换(点击公众号的菜单:交换)。 学习不打烊,充电加油只为遇到更好的本人,365天无节假日,每天早上5点纯手工公布面试题(死磕本人,愉悦大家)。心愿大家在这虚夸的前端圈里,放弃沉着,保持每天花20分钟来学习与思考。在这变幻无穷,类库层出不穷的前端,倡议大家不要等到找工作时,才狂刷题,提倡每日学习!(不忘初心,html、css、javascript才是基石!)欢送大家到Issues交换,激励PR,感激Star,大家有啥好的倡议能够加我微信一起交换探讨! 心愿大家每日去学习与思考,这才达到来这里的目标!!!(不要为了谁而来,要为本人而来!)交换探讨欢送大家前来探讨,如果感觉对你的学习有肯定的帮忙,欢送点个[Star]

August 17, 2021 · 1 min · jiezi

关于vue.js:activiti整合在现有系统业务绑定流程在线设计附源码

前言目前市场上有很多开源平台没有整合工作流,即便有,也是价格不菲的商业版,来看这篇文章的预计也理解了行情,必定不便宜。我这个疾速开发平台在零碎根底性能(用户治理,部门治理…)上整合了工作流,你能够间接用来开发ERP,OA,CRM等企业级利用,不必再放心如何再去花大量的工夫集成工作流进来。博主是集体开发者。钻研工作流有几年了,依稀记得第一次写工作流是用在江苏某省局的用车申请业务上,那时候年轻气盛,精力充沛可是能力无限,熬了几十个夜整进去了,即便进去了,也是代码很乱。前面也在好几个零碎参加了工作流的开发,目前是独自把这一套给抽取进去了,做成了可插拔的,能够十分不便的整合到你的程序中。上面咱们来摸索吧。 一、我的项目模式springboot+vue+activiti集成了activiti在线编辑器,疾速开发平台,可插拔工作流服务。 二、我的项目介绍本我的项目领有用户治理,部门治理,代码生成,零碎监管,报表,大屏展现,业务审批等性能。性能太强大,只能粗矿的介绍,所见即所得,体验一下吧。 三、工作流1.流程模型绘制进入流程模型菜单,创立流程模型,这里波及到网关流转,须要设置流转条件,咱们这里是三十岁以上的走上面分支,三十岁以下的走下面的分支。点击分支线,设置流转条件即可。${age<=30}。保留后咱们在列表中点击公布即可。 2.流程配置公布后,就到了已公布模型列表,在启用之前,咱们须要先对进行节点设置和关联具体单据。 审批人员能够依据角色,间接指定人,部门,部门负责人,发起人部门负责人来进行配置,基本上满足所有的流转需要,并且能够设置表单变量。 设置流程表单,目前就做了一个销假的测试表单,并且能够对相应角色受权,做到自定义权限。设置完后启动即可。 3.流程提交填写销假表单 提交单据,优先级分为一般,重要,紧急。音讯告诉能够抉择站内告诉,短信,邮件。 提交之后能够撤回单据。查看流程流转进度状况。 也能够挂起,删除流程。 4.流程审批办理人审批列表,能够解决单据(驳回或者通过),也能够委托别人待办。审批通过。委托别人待代。 审批通过后进入已办列表。 年龄大于30岁,进入上面分支流转。 审批通过。 5.待办信息推送站内音讯推送。 总结下面只是展现了平台的审批流性能,还有其余很多性能没展现进去,本人也写了一些十分好用的组件,做到零碎麻利疾速开发,大大减少开发工夫和老本,目前正在对接挪动端审批。之前因为没有工夫去部署线上测试环境,思考近期部署,目前能够独自找我,近程演示,有须要源码的分割我。q:2500564056。 鸣谢:jeecgboot开源版http://jeecg.com/咖啡兔activiti实战https://kafeitu.me/

August 17, 2021 · 1 min · jiezi

关于vue.js:网上商城从搭建到推广全流程细节注意点

本文重点阐明如何搭建好分销商城,如何经营分销商城网站,具体上面小编来介绍。1、做好市场考察剖析在搭建网上商城零碎的后期,就应该做好市场考察剖析工作,理解市场的发展趋势和用户真正需要的是什么,能力晓得本人要搭建一个什么样的商城网站。2、相熟网站产品要想经营好本人的网上商城,首先本人要对产品相熟,分明晓得产品的特点和用处,能力清晰的描绘出来。如果连本人都不分明,更谈不上给客户介绍产品,让客户信赖并购买了。所以,晋升本身的专业性是十分重要的。3、品牌建设倒退微信分销不仅是为了倒退新客户,同时也是为了留住老客户。此外,商城网站也须要留神品牌推广。一个好的口碑能够让更多的人所晓得,这不仅能够减少新客户的访问量,还能够让老客户留在商城生产。4、用户体验微信在商城的用户体验好坏将间接影响商城的营销。当用户体验度好的时候,能够给商家带来更多的消费者。因而,企业须要以“用户体验”为外围,理解客户的理论需要和想法,从而在肯定根底上与单方产生共鸣,进步企业竞争力。5、设计格调产品质量是顾客掂量的重要规范,因而,企业必须管制产品质量,取得肯定的知名度,能力实现高销量。不仅是平时的宣传和推广,微信商城的设计格调也须要丰富多彩和显明。6、营销推广在公布商城经营时,不要始终做广告,而是公布一些有价值的信息,一步一步地执行信息分享,并植入一些广告。只有这样能力吸引游客,尤其是潜在的顾客。此外,一些信息的公布必须是定期的,最好是找一个好的工夫发送信息,这样能够防止一些不必要的信息影响消费者的浏览状况,无效地减少粉丝的访问量,也能够排汇更多的客户起源。7、货源要短缺对于一个网上商城来说,优质的货源是商家胜利经营的要害。所以在货源方面肯定要多下功夫,寻找物美价廉的优质货源,来减低商城的老本。8、商城网站的推广不可少商城网站并不是只有搭建好了就能够了,如果想要吸引更多的用户,须要进步商城网站的知名度。通过对网站的无效推广,扩充货源,卖出产品获取利润。不过,在进行网站推广个别能够采纳的形式有百度推广、社群推广、朋友圈分享等形式。综上所述,网上商城零碎想要胜利经营能够参考以上几点,但商家在经营过程中要有久远的。做分销商城都是须要循序渐进的

August 17, 2021 · 1 min · jiezi

关于vue.js:vueeslint项目项目已开发使用prettier

1.开发环境 vue+eslint+prettier2.电脑系统 windows10专业版3.在应用vue+eslint我的项目开发的过程中,公司忽然加需要应用prettier做代码的格局,怎么搞呢?上面我来分享一下。4.废话不多说,间接上操作: npm i eslint-plugin-prettier@3.3.1 -Dnpm i @vue/eslint-config-prettier@6.0.0 -Dnpm i prettier@2.2.1 -D5.在.eslintrc.js中批改代码如下: // 原来配置extends: [ 'plugin:vue/essential', '@vue/standard' ],// 批改之后extends: ["plugin:vue/essential", "@vue/standard", "@vue/prettier"],6.在vue.config.js中增加如下代码: module.exports = { chainWebpack: (config) => { // 开启eslint主动修复,要害代码 config.module .rule('eslint') .use('eslint-loader') .loader('eslint-loader') .tap((options) => { options.fix = true return options }) }}// 在保留的时候,会主动格局代码构造7.本期的分享到了这里就完结啦,心愿对你有所帮忙,让咱们一起致力走向巅峰。

August 17, 2021 · 1 min · jiezi

关于vue.js:vuecli创建的项目引入图标字体有坑

第一步:找须要的去https://www.iconfont.cn/找到须要的图标下载到本地 第二步:增加下载好解压进去,增加到我的项目文件夹中 第三步:援用在路由文件中用import '../../font/iconfont.css'引入。我这里用router当作路由文件夹,所以router文件夹下的index.js就是路由文件,就没用src目录下的main.js当作路由文件在要应用图标的页面中援用 <i class="iconfont icon-zhuye"></i><i class="iconfont icon-dingdan"></i>我这里就用了下面两行就行了,看有的办法要在<style></style>里写@import url("../../font/iconfont.css");不晓得是不是我的我的项目进行到前面就要用到 四、留神:肯定要在<i></i>的class中退出iconfont(这是我踩的坑,小声bb)

August 17, 2021 · 1 min · jiezi

关于vue.js:vuecli创建的项目如何使用路由方式实现页面跳转重点

一、const routes = [// 上面两个花括号里因为创立我的项目自带没删,就正文掉 // { // path: '/', // name: 'Home', // component: Home // }, // { // path: '/about', // name: 'About', // // route level code-splitting // // this generates a separate chunk (about.[hash].js) for this route // // which is lazy-loaded when the route is visited. // component: () => import(/ webpackChunkName: "about" / '../views/About.vue') // }, // 上面两个花括号里用于通过名字点击跳转 { path: '/search', name: 'search', component: search}, { ...

August 16, 2021 · 1 min · jiezi

关于vue.js:用vue来写一个日历组件

我的项目要用到一个日历,然而css和性能比拟奇怪,就须要本人撸一个了原理一个日历以后月页面会显示3局部的日期天数上月的,本月的,下月的计算到这3局部组合起来的数组就是残缺的当月日历所以重点在于计算这三局部就实现了 1.上月的 new Date('2021-09-01').getDay() 2021年9月1号是星期3,这时候就失去上月的3天2.本月的new Date(year, month, 0).getDate()3.下月的7 - (preAndCenter.length % 7) 最初失去当前页所以日期数组后就能够随便扩大本人要的性能了<template> <div class="calendar_mod"> <div class="header_warp"> <div class="header_btn" @click="monthSwitch('prev')">上</div> <div class="header_center">{{headerData.year}} / {{headerData.month}}</div> <div class="header_btn" @click="monthSwitch('next')">下</div> </div> <div class="week_warp"> <div class="week_item" v-for='(item,index) in weeks' :key='index'>{{item}}</div> </div> <div class="cell_warp"> <div class="cell_box" v-for='(item,index) in allDays' :key='index'> <div :class="compDayClass(item)" >{{item.num}}</div> </div> </div> </div></template><script>export default { name: "my-calendar", props:{ marks:{ type:Array, default:()=>{ return [] } } }, data() { return { headerData: {}, weeks: ["日", "一", "二", "三", "四", "五", "六"], allDays: [], preMonthDay: [], // 上月 day 数组 }; }, created() { this.headerData = this.getCurrentDate(); // 获取以后年月 this.allDays = this.computer(this.headerData.year,this.headerData.month) this.$watch(()=>{ this.getMark(this.marks,this.headerData.year,this.headerData.month) }) }, computed:{ compDayClass(){ return function(item){ return `${item.type} ${item.mark?'marking':''}` } }, }, methods: { // 计算方法汇总 computer(year,month){ let cMonthWeek1 = this.getWeekInMonth( year,month ); let { preMonthNum ,cMonthNum} = this.getCurrentMonth(year,month); let preMonthDays = this.compedNextTr1(preMonthNum, cMonthWeek1); // 获取当前页上月arr return this.getAllDay(preMonthDays,cMonthNum,this.compDay) }, // 获取头部以后年月 getCurrentDate() { let currentDate = new Date(); let year = currentDate.getFullYear(); let month = currentDate.getMonth() + 1; return { year, month }; }, // 获取当月数据 getCurrentMonth(year, month) { // 获取月有多少天 let cMonthNum = new Date(year, month, 0).getDate(); let preMonthNum = new Date(year, month - 1, 0).getDate(); let nextMonthNum = new Date(year, month + 1, 0).getDate(); return { cMonthNum, preMonthNum, nextMonthNum }; }, // 计算某一月1号是星期几 getWeekInMonth(year, month) { return new Date(year + "/" + month + "/" + "01").getDay(); }, // 计算第一行 当月显示的日期 compedNextTr1(preMonthNum, cMonthWeek1) { var pre = [], temp = cMonthWeek1; for (var i = 0; i < cMonthWeek1; i++) { pre.push(preMonthNum - temp + 1); temp--; } return pre.map(item =>{ return { num:item,type:'prev'} }) }, //组成当月日期的数组 compDay(cMonthNum,typer) { var cDay = Array.from({ length: cMonthNum }, (v, k) =>{ return k + 1; }); return cDay.map(item =>{ return { num:item,type: typer=='next'?'next':'current'} }) }, // 获取所有的 getAllDay(preMonthDays,cMonthNum,compDay) { var preAndCenter = preMonthDays.concat(compDay(cMonthNum)); var lastDayNum = 7 - (preAndCenter.length % 7); var allDays = preAndCenter.concat(compDay(lastDayNum,'next')); return allDays }, monthSwitch(type){ let { year,month } = this.headerData if(type == 'prev'){ if(month == 1){ this.headerData.month =12 this.headerData.year = year - 1 this.allDays = this.computer(this.headerData.year,this.headerData.month) }else{ this.headerData.month = this.headerData.month -1 this.allDays = this.computer(year,month-1) } } if(type == 'next'){ if(month == 12){ this.headerData.month =1 this.headerData.year = year + 1 this.allDays = this.computer(this.headerData.year,this.headerData.month) }else{ this.headerData.month = this.headerData.month +1 this.allDays = this.computer(year,month+1) } } }, // 依据传入的日期标记 getMark(marks,currentYear,currentMonth){ const dayMarks = marks.filter(item=>{ let zday = (new Date(item)) if(zday.getMonth()+1 == currentMonth && zday.getFullYear() == currentYear){ return zday.getDate() } }) const matchDays = dayMarks.map(item => (new Date(item)).getDate()) this.allDays.forEach(item =>{ delete item.mark }) this.allDays.forEach(item=>{ matchDays.forEach(item2=>{ if(item.num == item2){ item.mark = true } }) }) this.$forceUpdate() }, },};</script><style scoped>.calendar_mod { border: 1px solid #333; user-select: none;}.header_warp,.week_warp,.cell_warp { display: flex;}.header_warp { height: 50px; border: 1px solid rgb(143, 53, 53); justify-content: space-between;}.header_btn{ width: 100px; text-align: center; background-color: #999; cursor: pointer;}.week_item { flex: 1; text-align: center; border: 1px solid rgb(94, 179, 119);}.cell_warp { flex-wrap: wrap;}.cell_box { height: 70px; flex: 0 0 14.285%; margin: 5px 0;}.cell_box div{ width: 50px; height: 100%; margin: 0 auto; display: flex; justify-content: center; align-items: center; cursor: pointer;}.cell_box .prev{ background-color: #f1b9b9;}.cell_box .next{ background-color: #b9f1c1;}.marking{ color:red;}</style>

August 16, 2021 · 3 min · jiezi

关于vue.js:vue3-的两种变量refreactive

应用 ref 定义根本数据类型的响应式变量, 应用reactive 定义数组或对象类型的响应式变量, 都是响应的 const count = ref(0)const obj = reactive({ count: 0 })vue3应用reactive包裹数组和对象不能间接赋值, 否则会失去响应性。 要用「响应式值援用」, 不必一般的根本类型值与对象,否则容易失去响应性如 const arry1 = reactive([1]) 在js 中间接赋值,将失去响应性: arry1 = [1,2,3] //arry1=[1] 能够这么定义 const data = reactive({arry1:[1]}) 在js 中应用 data.arry1 = [1,2,3] // arry1=[1,2,3]2.创立的响应式变量, 不能进行解构或开展, 否则变量将失去响应成果, 能够应用 toRefs API 如 const book = reactive({ author: 'Vue Team', year: '2020', title: 'Vue 3 Guide' }) let { author, title } = toRefs(book) title.value = 'Vue 3 Detailed Guide' // 咱们须要应用 .value 作为题目,当初是 ref console.log(book.title) // 'Vue 3 Detailed Guide' 而不能这么解构 let { author, title } = book 也不能应用开展: ...book总结一下,一共有两种变量格调: ...

August 16, 2021 · 1 min · jiezi

关于vue.js:vscode使用eslint自动保存格式化代码

1.开发环境 vue+eslint2.电脑系统 windows10专业版3.在应用vue开发我的项目的时候,咱们有的时候会抉择eslint来标准代码,于是开始本人配置保留依照eslint来格局代码,去网上找答案,后果什么样的说法都是有的(有的说在package.json配置/有的说去setting.json退出各种配置),要害是没有一个失效的,于是开启了本人钻研,找打了解决办法,上面我来分享一下。4.废话不多说,间接上操作: // 在vue.config.js退出上面配置module.exports = { chainWebpack: config => { // 开启eslint主动修复,要害代码 config.module .rule('eslint') .use('eslint-loader') .tap(options => { options.fix = true return options }) }}// 留神:前提是我的项目装置了eslint// 接下来就能够欢快的游玩了,就是这么的简略5.再次申明,没有配置settings.json6.本期的分享到了这里就完结啦,心愿对你有所帮忙,让咱们一一起致力走向巅峰。

August 14, 2021 · 1 min · jiezi

关于vue.js:为什么企业有必要搭建自己的微商城分销系统呢

微商城分销零碎对于一些电商商户来说并不生疏,那么为什么企业有必要搭建本人的微商城分销零碎呢?一、对于客户能够简化商品的购物流程咱们都晓得在实体店进行购买的时候,咱们能够间接看到商品,并且可能摸到产品的品质如何,并且在最初,如果并不适合的时候,是能够找商家进行退还的。然而网上购买就有所不同,有的时候还有些简单,所以微商城分销零碎也着力于这一点进行思考。适当的简化了商品的购物流程,让整个购物旅程更加美妙。二、对企业能通过微信吸引浩繁的粉丝在现在,咱们最罕用的聊天软件就是腾讯旗下的微信和qq。而在这里,企业就能够把握到这一点,并正当行使这一点进行最低老本的推广。企业将微商城分销零碎分享到微信群或朋友圈,让更多人晓得这个品牌,用最低的老本,做最合适的推广,这是每一个品牌的必要,毕竟品牌都是必要金钱的,利益是所寻求的一点。其实每一个新程序的倒退都是为了须要的程序进行考量的。不须要进行胆怯或是嫌疑,然而也要粗疏的一点是咱们必要重视微商城分销零碎中商品的品质,在正规的厂家进行抉择,不能随便筛选。三、微商城分销零碎多样的分销模式微商城分销零碎不仅反对各级分销商全局设置,还可设置商品的单级分销佣金比例。企业在分销商城能够招募分销商,次要对象就是在分销商城里进行生产的用户。商家要给每一位在商场里生产的用户发送邀请函,并且通知他们成为分销商的益处,当他们变成分销商之后就会为了佣金去营销产品。每位用户都会有本人的交际圈,当他们向本人的好友推销产品的时候必然又会有很多新用户成为微商城分销零碎的分销商,如此一来产品就会裂变流传,它的名气就会大很多。四、疾速搭建商城分销零碎微商城分销零碎能帮忙企业疾速建设属于本人的独立官网,并具备弱小经营治理性能,包含社会化分享、登录等性能,为企业提供稳固、高效的订单及商品治理服务。五、更无效地进步产品覆盖率产品覆盖率与产品分销效率分不开。在微商城分销零碎的分销模式下,针对产品市场笼罩渠道采取并行不悖的伎俩,一方面通过进步成员的积极性,依附渠道力量进行;另一方面利用企业分销商的协销制度、严格量化的市场治理考核制度进行管控,成果非常明显。

August 14, 2021 · 1 min · jiezi

关于vue.js:报错-vueelementadmin440-dev-vuecliservice-serve

问题:运行vue-element-admin时报vue-element-admin@4.4.0 dev: vue-cli-service serve谬误 解决:第一种方法 :删除node_modules 从新下载 第二种方法(第一种方法有效的状况下):1.零碎环境变量的path中增加C:\windows\system32(具体门路是:右击我的电脑=>属性=>高级零碎设置=>环境变量=>path)2.我的项目中的vue.config.js 中 open:true 正文掉或者 改成false,意思是运行完程序后,不主动启动浏览器

August 14, 2021 · 1 min · jiezi

关于vue.js:vue-routerview使用详解

一、介绍 router-view组件作为vue最外围的路由治理组件,在我的项目中作为路由治理常常被应用到。vue我的项目最外围的App.vue文件中即是通过router-view进行路由治理。 <template> <div id="app"> <router-view></router-view> </div></template>咱们在本人保护我的项目的时候,也能够应用router-view组件进行路由治理,对于页面部分刷新的场景,该组件能施展关键作用; 二、应用办法 咱们通过具体场景来介绍router-view组件用法: 1 实现成果通过切换底部导航栏进行页面内容区域切换:实现的性能是:点击音讯、联系人、动静;页面内容进行切换;页面题目以及底部导航栏不变; 2 代码最要害的是router.js配置: { path: "/routerViewPractice", name: "routerViewPractice", component: () => import("@/views/routerView/index.vue"), redirect: '/messagePage',//页面默认加载的路由 children: [ { path: "/messagePage", name: "messagePage", component: () => import("@/views/routerView/childPages/messagePage.vue") }, { path: "/contactPage", name: "contactPage", component: () => import("@/views/routerView/childPages/contactPage.vue") }, { path: "/dynamicPage", name: "dynamicPage", component: () => import("@/views/routerView/childPages/dynamicPage.vue") } ] }文件阐明: routerViewPractice:父路由path;redirect:页面router-view组件默认加载的路由;children:用于父页面进行切换的子路由;vue父页面代码: <template> <div> <title-bar :title="title" @goBack="goback"></title-bar> <router-view></router-view> <BottomBar @handleMsg='handleMsg' @lookContact='lookContact' @readDynamic='readDynamic' ></BottomBar> </div></template><script>import TitleBar from "@/components/TitleBar";import BottomBar from "@/components/BottomBar";export default { name: "", components: { TitleBar, BottomBar }, data() { return { title: "路由视图", }; }, methods: { // 返回办法 goback() { // this.$emit("GoBack"); }, handleMsg() { this.$router.push({path: '/messagePage'}) }, lookContact() { this.$router.push({path: '/contactPage'}) }, readDynamic() { this.$router.push({path: '/dynamicPage'}) } }};</script><style scoped>#page-title { width: 100%; background-color: #fff; display: flex; justify-content: center;}.backImg { width: 20px;}</style>应用this.$router.push进行页面上router-view组件的路由替换;实现点击底部导航栏页面切换性能; ...

August 14, 2021 · 1 min · jiezi

关于vue.js:如何引进-Typescript-到现存-Vuecli3项目中

前言在把我的项目革新反对 Typescript 之后, 跑了几个迭代,也踩了一些坑。还好这些坑总体可控, 没翻车, 所以就写篇文章分享一下, 如果想要体验 vue+typescript 的同学能够看看。之前配置的过程查找了很多材料,但大部分都是上面两种计划: 基于 vue-cli3+的全新的我的项目vue-cli2 的老我的项目引进 typescript然而咱们公司的我的项目在新建我的项目的时候并没有引入 typescript 的反对。如果前期想引入 typescript 呢,有没有一种向后兼容(backward compatibility)的形式整合到现有的我的项目中呢,既可反对 ts,也能够兼容 js,这样现有的代码就简直不必改变了。上面分三局部来形容 : 一个基于 vue-cli3+、反对 typescript 的新我的项目是怎么配置的?如何利用这些不同的配置到现存的我的项目中?因为子项目须要引入主模块的 app,还有 vue,element-ui 等等是以 extenal 引进来的,这些须要如何配置才不使 ts 报错?1. 一个基于 vue-cli3+、反对 typescript 的新我的项目是怎么配置的?开始之前,咱们先理解一下 Typescript 是什么?为什么须要它,能给我的项目带来什么?(如果相熟 typescript 的话,这部分能够跳过哈)Typescript 是 JavaScript 的超集正如官网说形容: "A superset of Javascript", Typescript 更靠近面对对象语言, 反对更多的 JS 不能反对的语法:例如,链式语法, js: res && res.data && res.data.name ; ts 的话: res?.data?.name  尽管 babel 也有相似的插件实现该语法 。而且 ts 是向后兼容的, 也就 js 的语法都能够间接在 ts 都能够使用。 ...

August 14, 2021 · 2 min · jiezi

关于vue.js:Vue实现数组四级联动

前言最近我的项目上有个需要就是做下拉列表的四级联动,应用的是vuejs + elementui,应用数组存储对象的模式做为列表渲染到页面上的数据,然而在下拉列表联动的时候发现几个问题,当初记录下解决办法,分享给大家。 批改对象数组后前端页面不从新渲染查看或者编辑回显数据时,联动数据渲染出错(只显示key,不显示name) 对于简单数据处理之前在写React的时候,简单一点的数据会通过Immutable.js来实现,通过get和set来实现数据的设置和读取,以及深层拷贝等性能,当初到了Vue发现数据简单一点就不晓得如何解决,第三方对于vue的immutable.js框架也没有理解过,前面有工夫能够关注并学习下(大家有应用过的能够分享给我)。 四级联动问题解决办法问题一:批改对象数组后前端页面不从新渲染这个问题其实Vue官网也阐明过对于数组变动不会从新渲染页面的问题。 Vue 不能检测以下数组的变动: 当你利用索引间接设置一个数组项时,例如:vm.items[indexOfItem] = newValue当你批改数组的长度时,例如:vm.items.length = newLength举个例子: var vm = new Vue({ data: { items: ['a', 'b', 'c'] } })vm.items[1] = 'x' // 不是响应性的vm.items.length = 2 // 不是响应性的为了解决第一类问题,以下两种形式都能够实现和 vm.items[indexOfItem] = newValue 雷同的成果,同时也将在响应式零碎内触发状态更新: // Vue.set Vue.set(vm.items, indexOfItem, newValue) // Array.prototype.splice vm.items.splice(indexOfItem, 1, newValue)你也能够应用 vm.$set 实例办法,该办法是全局办法 Vue.set 的一个别名: vm.$set(vm.items, indexOfItem, newValue)为了解决第二类问题,你能够应用 splice: vm.items.splice(newLength)因而解决办法就是代码里应用Vue.set(vm.items, indexOfItem, newValue),上面就演示个例子: export default { data(){ return { arrys :[ { one: '', oneList: Promise: getOneList(), two: '', twoList: Promise: getTwoList(one), three: '', threeList: Promise: getThreeList(two), four: '', fourList: Promise: getFourList(three), } ] } }, methods: { // one下拉列表change事件 oneChange(key, index){ this.getTwoList(key).then(res => { this.arrys.forEach((item, i) => { if (i === index) { // 因为是四级联动,所以change one之后,two、three和four都要置空 let newitem = { two: [], twoList: res, three: '', four: '', threeList: [], fourList: [] } // 阐明:批改arrys中第i个的数据,只有应用Vue.set页面才会从新渲染 // newitem会笼罩item中的数据,并生成一个新的援用指针 Vue.set(this.arrys, i, Object.assign({}, item, newitem)) } }) }); }, // two下拉列表change事件 twoChange(key, index){ }, // three下拉列表change事件 threeChange(key, index){ }, // four下拉列表change事件 fourChange(key, index){ }, // 获取one 列表 getOneList(){ }, // 获取two 列表 getTwoList(oneKey){ }, // 获取three 列表 getThreeList(twoKey){ }, // 获取four 列表 getFourList(threeKey){ } } }依照下面的代码就能够实现四级联动及change的时候页面可能动静渲染,这样就实现了联动成果以及批改对象数组后前端页面不从新渲染问题了。 ...

August 13, 2021 · 2 min · jiezi

关于vue.js:vue下载文件

通过url下载文件 downloadFile(dfile) { // dfile是文件地址 fetch(dfile).then(res => res.blob()).then(blob => { // 将链接地址字符内容转变成blob地址 const a = document.createElement('a') a.href = URL.createObjectURL(blob) console.log(a.href) //截取门路中的文件名 a.download = dfile.substring(dfile.lastIndexOf("/")+1,dfile.length ) // 下载文件的名字 document.body.appendChild(a) a.click()![] }) },

August 13, 2021 · 1 min · jiezi

关于vue.js:免费开源基于Vue和Quasar的前端SPA项目crudapi后台管理系统实战之EXCEL数据导出十三

基于Vue和Quasar的前端SPA我的项目实战之数据导出(十三)回顾通过之前一篇文章 基于Vue和Quasar的前端SPA我的项目实战之数据导入(九)的介绍,通过配置的形式能够零代码实现业务数据的批量导入性能,本文次要介绍业务数据批量导出相干内容。 简介针对每个业务表,有时须要导出数据到本地文件,用来备份或者剖析,这里采纳的文件格式为EXCEL,第一行为字段名称,从第二行开始为数据。 UI界面产品导出 API业务数据导出相干API,具体的通过swagger文档能够查看。通过axios封装api,名称为table import { axiosInstance } from "boot/axios";const table = { export: function(tableName) { return axiosInstance.get("/api/business/" + tableName + "/export", { params: { } } ); }};export { table };外围代码阐明export胜利之后返回文件URL,间接下载即可! 代码async onExportClickAction() { this.$q.loading.show({ message: "生成中" }); try { const url = await tableService.export(this.tableName); this.$q.notify("数据导出胜利,请期待下载实现后查看!"); window.open(url, "_blank"); this.$q.loading.hide(); } catch (error) { this.$q.loading.hide(); console.error(error); }}产品为例点击“批量导出”按钮,胜利之后主动下载文件到本地,关上EXCEL查看发现3条数据曾经生成,和零碎中数据统一。 小结本文次要介绍了介绍业务数据批量导出性能,不同的业务表单操作相似,通过配置的形式能够零代码实现业务数据的批量导出性能。 crudapi简介crudapi是crud+api组合,示意增删改查接口,是一款零代码可配置的产品。应用crudapi能够辞别枯燥无味的增删改查代码,让您更加专一业务,节约大量老本,从而进步工作效率。crudapi的指标是让解决数据变得更简略,所有人都能够收费应用!无需编程,通过配置主动生成crud增删改查RESTful API,提供后盾UI治理业务数据。基于支流的开源框架,领有自主知识产权,反对二次开发。 demo演示crudapi属于产品级的零代码平台,不同于主动代码生成器,不须要生成Controller、Service、Repository、Entity等业务代码,程序运行起来就能够应用,真正0代码,能够笼罩根本的和业务无关的CRUD RESTful API。 官网地址:https://crudapi.cn 测试地址:https://demo.crudapi.cn/crudapi/login 附源码地址GitHub地址https://github.com/crudapi/crudapi-admin-web Gitee地址https://gitee.com/crudapi/crudapi-admin-web 因为网络起因,GitHub可能速度慢,改成拜访Gitee即可,代码同步更新。 ...

August 13, 2021 · 1 min · jiezi

关于vue.js:详解vuediff算法

详解vue-diff算法

August 12, 2021 · 1 min · jiezi

关于vue.js:伪类伪元素的区别和应用场景

每次被他人闻到伪类和伪元素有什么区别的时候,都是傻傻分不清楚,答复的也不尽人意;所以伪类和伪元素的区别是什么呢?作用是什么呢?本文将从区别与作用两方面来学习伪类和伪元素的常识。 伪类与伪元素的区别 伪类:w3c的规范定义是:CSS伪类是用来增加一些选择器的特殊效果。 顾名思义,是一个类,类是什么是css选择器呀,所以css选择器不会存在于dom元素中,所以想想咱们罕用的那些是伪类 (不存在与dom构造中,还能管制款式的)第一个想到的应该是a标签的哪几种状态伪类了吧,比方a:link {color:#FF0000;} /* 未拜访的链接 */a:visited {color:#00FF00;} /* 已拜访的链接 */a:hover {color:#FF00FF;} /* 鼠标划过链接 */a:active {color:#0000FF;} /* 已选中的链接 */还有一些比方咱们罕用的:first-child,:last-child :lang :checked :empty,以下为全副 咱们先来总结一些伪类: 1、伪类是类,所以跟css选择器无关,不存在与dom中 2、CSS伪类是用来增加一些选择器的特殊效果的 3、伪类后面之后一个冒号:first-child 伪元素: 伪元素是发明文档树之外的对象。伪元素也是元素,只不过不存在与dom对象中,然而浏览器审查元素的时候能看失去的,比方::before ::after咱们总结一下伪元素: 伪元素是两个冒号伪元素能够被审查元素看到以上总结辨别一下两者的区别相同点: 伪类和伪元素都不呈现在源文件和文档树中。也就是说在html源文件中是看不到伪类和伪元素的。不同点:伪类实质上是为了补救惯例CSS选择器的有余,以便获取到更多信息;伪元素实质上是创立了一个有内容的虚构容器;CSS3中伪类和伪元素的语法不同;能够同时应用多个伪类,而只能同时应用一个伪元素;一句话是伪元素产生新对象,在DOM树中看不到(审查元素的时候能够看到),然而能够操作;伪类不产生新的对象,仅是DOM中一个元素的不同状态;

August 12, 2021 · 1 min · jiezi

关于vue.js:vue3vue2区别之vfor和vif

vue2:不倡议在同一元素应用v-for和v-if,v-for优先级比v-if高文档地址:https://cn.vuejs.org/v2/guide...vue3:同样不倡议在同一元素应用v-for和v-if,然而v-if优先级比v-for高,某些场景会报错文档地址:https://v3.cn.vuejs.org/guide...

August 12, 2021 · 1 min · jiezi

关于vue.js:Vue-移动端的长按与触摸事件

Vue 挪动端的长按与触摸事件博客阐明 文章所波及的材料来自互联网整顿和集体总结,意在于集体学习和教训汇总,如有什么中央侵权,请分割自己删除,谢谢!阐明在手机端的需要难免会遇到与手势相干的,比方div的长按和单击事件,长按可能是分享或者删除等操作,个别的模式是通过弹窗来展示。 实现其实次要是利用dom的触摸事件,touchstart,touchmove,touchend 代码<template> <div> <div class="btn-long" @touchstart="handlerTouchstart" @touchmove="handlerTouchmove" @touchend="handlerTouchend">长按我</div> <div v-if="clickShow">单击</div> <div v-if="longClickShow">双击</div> </div></template><script>export default { name: 'LongTouch', data () { return { // 定时器 loop: 0, clickShow: false, longClickShow: false } }, methods: { handlerTouchstart () { this.loop = setTimeout(() => { this.loop = 0 // 执行长按要执行的内容 this.clickShow = false this.longClickShow = true }, 500) // 定时的工夫 return false }, handlerTouchmove () { // 革除定时器 clearTimeout(this.loop) this.loop = 0 }, handlerTouchend () { // 革除定时器 clearTimeout(this.loop) if (this.loop !== 0) { // 单击操作 this.clickShow = true this.longClickShow = false } } }}</script><style scoped>.btn-long { width: 200px; height: 30px; background-color: red;}</style>演示 ...

August 12, 2021 · 1 min · jiezi

关于vue.js:sublime-text-3中添加vue高亮插件

去https://packagecontrol.io/ins...下载 Package Control.sublime-package 文件,点击下方圈起来的链接即可下载到本地点击 preferencees->package setting->package control->setting default 查看channel_v3.json文件的门路不能拜访不能拜访就网上找channel_v3.json文件,下载到本地,用绝对路径引入通过上面步骤Ctrl+Shift+P - 输出install - 选中install package - 输出vue - 点击Syntax Highlight这样下载好Syntax Highlight这个vue高亮插件后,右下角要选中vue的语法(搞了一个半小时才发现我是这种问题)

August 11, 2021 · 1 min · jiezi

关于vue.js:vue3-中使用emits

emits: 列表申明从父组件继承来的事件$emit: 抛出事件, 告诉父组件解决子组件中: export default { name: "MyXgPlayer", //申明从父组件继承来的事件:能够是简略数组, 也能够是对象(加了校验函数) emits: ['just-one-player'], props:{ domId: String, previewVideoUrl: String, }, setup(props, context){ //获取以后实例(包含从父组件传过来的props数据, 实例办法($watch,$emit, $forceUpdate,$nextTick, 定义的全局的$addHost // vue 内含的$alert,$message,$messageBox, $store,$router, $refs ...)) const {proxy} = getCurrentInstance() let player = ref(null) onMounted(()=>{ //new 数据 player.value = new Player ({ id: props.domId, url: props.previewVideoUrl, }); //监听play 事件 player.value.on('play', ()=>{ console.log("start $emit") //给父组件抛事件 proxy.$emit("just-one-player", props.domId, player) }) }) }, }父组件中 <my-xg-player :dom-id="'xgplayer_test_'+file.collection_id" :preview-video-url="file.file_path" @justOnePlayer="justOnePlayer" /><!--script中-->import {ref} from "vue"setup(props, context){ const xgplayers = ref({}) const justOnePlayer = (domId, player)=>{ console.log("receive $emit") for(let item_key in state.xgplayers){ if(item_key !== domId){ state.xgplayers[item_key].pause() } } state.xgplayers[domId] = player } return { xgplayers, justOnePlayer } }}点击子组件中的播放,打印的log ...

August 11, 2021 · 1 min · jiezi

关于vue.js:5-个可以加速开发的-VueUse-函数库

VueUse 是 Anthony Fu 的一个开源我的项目,它为 Vue 开发人员提供了大量实用于 Vue 2 和 Vue 3 的根本 Composition API 实用程序函数。它有几十个解决方案,实用于常见的开发者用例,如跟踪Ref变动、检测元素可见性、简化常见的Vue模式、键盘/鼠标输出等。这是一个真正节俭开发工夫的好办法,因为你不用本人增加所有这些规范性能。我喜爱VueUse库,因为它在决定提供哪些实用工具时真正把开发者放在第一位,而且它是一个保护良好的库,因为它与Vue的以后版本放弃同步。VueUse 有哪些实用程序?如果你想看到每一个实用程序的残缺列表,我相对倡议你去看看官网文档。但总结一下,VueUse中有9种类型的函数。 Animation——蕴含易于应用的过渡、超时和计时性能。Browser——可用于不同的屏幕管制、剪贴板、偏好等。Component——提供了不同组件办法的简写。Formatters——提供响应工夫格式化性能。Sensors——用来监听不同的DOM事件、输出事件和网络事件。State——治理用户状态(全局、本地存储、会话存储)。Utility——不同的实用函数,如 getter、条件、援用同步等。Watch——更多高级类型的观察器,如可暂停的观察器、退却的观察器和条件观察器。Misc——不同类型的事件、WebSockets和web workers 的性能 这些类别中的大多数都蕴含几个不同的性能,所以VueUse对于你的应用状况来说是很灵便的,能够作为一个很好的中央来疾速开始构建Vue应用程序。在本教程中,咱们将看一下5个不同的VueUse函数,这样你就能够理解在这个库中工作是如许容易。但首先,让咱们将其增加到Vue我的项目中!将 VueUse 装置到你的 Vue 我的项目中VueUse的最大特点之一是,它只用一个软件包就能同时兼容Vue 2和Vue 3!装置VueUse有两种抉择npm或CDNnpm i @vueuse/core # yarn add @vueuse/core复制代码<script src="https://unpkg.com/@vueuse/shared"></script><script src="https://unpkg.com/@vueuse/core"></script>复制代码我倡议应用NPM,因为它应用法更容易了解,但如果咱们应用CDN,VueUse将在应用程序中通过 window.VueUse 拜访。对于NPM的装置,所有的性能都能够通过应用规范的对象重构从 @vueuse/core 中导入,像这样拜访。import { useRefHistory } from '@vueuse/core'复制代码好了,当初咱们曾经装置了VueUse,让咱们在应用程序中应用它!useRefHistory 跟踪响应式数据的更改useRefHistory 跟踪对Ref所做的每一个扭转,并将其存储在一个数组中。这使咱们可能轻松地为咱们的应用程序提供撤销和重做性能。让咱们看一个示例,其中咱们正在构建一个咱们心愿可能吊销的文本区域。第一步是在不应用 VueUse 的状况下创立咱们的根本组件——应用 ref、textarea 和用于吊销和重做的按钮。<template> <p> <button> Undo </button><button> Redo </button></p> <textarea v-model="text"/></template> <script setup>import { ref } from 'vue'const text = ref('')</script> <style scoped> button { ...

August 11, 2021 · 4 min · jiezi

关于vue.js:Vue3头像选择器

应用场景: pc端设置头像:抉择图片后,可自行截取图片,并预览方形和圆形解决问题: el-upload自定义上传;vue3基于cropper.js的裁切性能;axios发送文件流申请;实现思路:el-upload勾销自定义上传性能,将属性accept=".jpg, .png"设置默认显示的文件类型,在on-change钩子中获取所选中的图片。在on-change事件中,获取返回的file类型图片,因为vue-picture-cropper组件承受blob类型的图片,所以通过URL.createObjectURL(file类型图片)给cropper组件赋值,显示图片;在显示时,会有两个div用于显示图片,一个方形,一个圆形,组件会主动将图片的值传递到div中显示进去 <div class=" square"></div><div class="circular"></div>在提交时,获取cropper组件显示的图片的base64值,通过base64值转文件,获取文件流: function dataURLtoFile (dataURL, fileName) { let asd = dataURL; let arr = dataURL.split(','), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } return new File([u8arr], fileName, { type: mime })}将获取到的文件流增加到申请体外面, let formData = new FormData();formData.append('file', file);let resUpload = await axiosApi.postFileApi(`/file/upload/simpleUpload`, formData);这样,就实现了对上传接口增加文件流的操作,成果展现:

August 11, 2021 · 1 min · jiezi

关于vue.js:map遍历数组时正确使用async与await

1.开发环境 vue2.电脑系统 windows10专业版3.在开发的过程中,咱们常常会解决一些数据,须要拿到一个xxx在去申请另外一个接口,然而数据是异步操作,所以赋值的时候始终是空,上面我来分享一下。4.废话不多说,间接上效果图:5.上面我来分享 // 残缺代码this.list = this.list.map(async (item) => { let a = await this.$Cmethods.getfilesimg(item.fileKey); item.img = a[0]; return item;});this.list = await Promise.all(this.list);6.剖析与解决 1.别离打印item和this.list,发现item外面有值,然而this.list外面没有,狐疑是异步2.因为async函数返回的是一个Promise,所以map返回的是Promise数组.必须等到所以Promise失去解决之后再进行赋值3.通过await Promise.all(xxx);//解决7.本期的分享到了这里就完结啦,心愿对你有所帮忙,让咱们一起致力走向巅峰。

August 11, 2021 · 1 min · jiezi

关于vue.js:前端面试每日-31-第848天

明天的知识点 (2021.08.11) —— 第848天 (我也要出题)[html] 前端如何在h5页面调用微信领取?[css] 应用CSS3实现电影投影仪动画[js] 写一个避免反复申请接口的办法[软技能] 在公司加班,你感觉公司应该给予什么样的福利?《论语》,曾子曰:“吾日三省吾身”(我每天屡次检查本人)。前端面试每日3+1题,以面试题来驱动学习,每天提高一点!让致力成为一种习惯,让奋斗成为一种享受!置信 保持 的力量!!! 欢送在 Issues 和敌人们一起探讨学习! 我的项目地址:前端面试每日3+1【举荐】欢送跟 jsliang 一起折腾前端,零碎整顿前端常识,目前正在折腾 LeetCode,打算买通算法与数据结构的任督二脉。GitHub 地址 微信公众号欢送大家前来探讨,如果感觉对你的学习有肯定的帮忙,欢送点个Star, 同时欢送微信扫码关注 前端剑解 公众号,并退出 “前端学习每日3+1” 微信群互相交换(点击公众号的菜单:交换)。 学习不打烊,充电加油只为遇到更好的本人,365天无节假日,每天早上5点纯手工公布面试题(死磕本人,愉悦大家)。心愿大家在这虚夸的前端圈里,放弃沉着,保持每天花20分钟来学习与思考。在这变幻无穷,类库层出不穷的前端,倡议大家不要等到找工作时,才狂刷题,提倡每日学习!(不忘初心,html、css、javascript才是基石!)欢送大家到Issues交换,激励PR,感激Star,大家有啥好的倡议能够加我微信一起交换探讨! 心愿大家每日去学习与思考,这才达到来这里的目标!!!(不要为了谁而来,要为本人而来!)交换探讨欢送大家前来探讨,如果感觉对你的学习有肯定的帮忙,欢送点个[Star]

August 11, 2021 · 1 min · jiezi

关于vue.js:小程序-canvas-画名片

用cancas画名片 波及到技术 原型头像、文字超出换行、字体大小色彩、背景图wxml 页面内容 <view class="pages"> <canvas canvas-id="shareKapian" style="width:{{width}}px;height:{{height}}px;"></canvas></view>wxjs内容线上图片须要通过localImge 函数将线上门路转为本地门路方可。步骤 先开机相机权限canvasKapian---->而后开始绘制名片canvasClick---->最初下载名片downFn Page({ data: { width: 320, height: 300, isDisable: false,//避免屡次点击 }, onLoad: function (options) { this.canvasKapian(); }, //绘制名片 canvasKapian() { wx.getSetting({ success: res => { console.log(res); if (!res.authSetting['scope.writePhotosAlbum']) { wx.authorize({ scope: 'scope.writePhotosAlbum', success: res => { this.canvasClick(); }, fail: err => { wx.showModal({ title: "提醒", content: '图片保留失败,您须要开启相册权限并且从新保留,是否开启?', success: res => { if (res.confirm) { wx.openSetting({ success: (res) => { if (res.authSetting['scope.writePhotosAlbum']) { this.canvasClick(); } else { wx.showToast({ title: '获取权限失败,无奈应用保留图片或视频到您的相册', icon: 'none' }) } }, }) } } }) } }) } else { this.canvasClick(); } } }) }, canvasClick() { this.setData({ isDisable: true }) wx.showLoading({ title: '名片生成中...', }) // let image1 = this.localImge(this.data.background); // let image2 = this.localImge(this.data.wxCode); // let image3 = this.localImge(this.data.headerImg); // Promise.all([image1, image2, image3]).then(res => { // let background1 = res[0]; // let wxCode1 = res[1]; // let headerImg1 = res[2]; const ctx = wx.createCanvasContext("shareKapian"); ctx.setFillStyle("#22DDB8"); //背景色 // 背景图 ctx.drawImage('../../image/bc.jpg', 0, 0, this.data.width, this.data.height); ctx.fillRect(0, 0, this.data.width, this.data.height); let top = 30; let left = 30; // 头像 this.circleImg(ctx, '../../image/bc.jpg', left, top, 20) //流动 ctx.fillStyle="#9B712E"; ctx.setFontSize(18); ctx.font = 'bold'; ctx.fillText('bingxiaoxiao', left + 50, top); // 介绍 ctx.setFontSize(14); this.drawText(ctx, '2020年7月24日上午,中国外交部告诉美国驻华使馆,中方决定撤销对美国驻成都总领事馆的设立和运行许可,并对该总领事馆进行所有业务和流动提出具体要求。', left + 50, top + 25 , 0, 135) ctx.draw(false, () => { wx.canvasToTempFilePath({ canvasId: "shareKapian", success: res => { wx.hideLoading(); this.setData({ catShopUrl: res.tempFilePath }); this.downFn(); }, fail: err => { console.log('生成失败', err); } }); }); // }).catch(err => { // console.log(err); // wx.hideLoading(); // wx.showToast({ // title: '图片加载失败,请返回重试', // icon: 'none' // }) // }) }, //保留图片 downFn() { let imgurl = ''; wx.showLoading({ title: '保留中...', }) imgurl = this.data.catShopUrl; wx.saveImageToPhotosAlbum({ filePath: imgurl, success: res => { wx.hideLoading() wx.showToast({ title: "保留胜利,从相册中分享到朋友圈吧", icon: "none", duration: 4000 }); this.setData({ isDisable: false }) }, fail: function (err) { console.log(err) if (err.errMsg === "saveImageToPhotosAlbum:fail:auth denied" || err.errMsg === "saveImageToPhotosAlbum:fail auth deny") { wx.hideLoading(); wx.showModal({ title: "提醒", content: '图片保留失败,您须要开启相册权限并且从新保留,是否开启?', success: res => { if (res.confirm) { wx.openSetting({ complete: (res) => { console.log(res); }, }) } } }) } } }); }, //生成本地图片 localImge: function (src) { console.log('src', src); return new Promise(function (resolve, reject) { wx.downloadFile({ url: src, success: function (res) { resolve(res.tempFilePath); }, fail: err => { reject(err) } }); }); }, // 超出换行 drawText: function (ctx, str, leftWidth, initHeight, titleHeight, canvasWidth) { var lineWidth = 0; var lastSubStrIndex = 0; //每次开始截取的字符串的索引 for (let i = 0; i < str.length; i++) { lineWidth += ctx.measureText(str[i]).width; if (lineWidth > canvasWidth) { ctx.fillText(str.substring(lastSubStrIndex, i), leftWidth, initHeight); //绘制截取局部 initHeight += 16; //16为字体的高度避免文字重叠 lineWidth = 0; lastSubStrIndex = i; titleHeight += 30; } if (i == str.length - 1) { //绘制残余局部 ctx.fillText(str.substring(lastSubStrIndex, i + 1), leftWidth, initHeight); } } // 题目border-bottom 线距顶部间隔 titleHeight = titleHeight + 10; return titleHeight }, // 圆形图片 circleImg: function (ctx, img, x, y, r) { ctx.save() ctx.beginPath() var d = 2 * r; var cx = x + r; var cy = y + r; ctx.arc(cx, cy, r, 0, 2 * Math.PI); ctx.clip(); ctx.drawImage(img, x, y, d, d); ctx.restore() },})

August 10, 2021 · 3 min · jiezi

关于vue.js:前端Vue框架在PostCSS怎样使用sass

为什么要应用PostCss家喻户晓转换 px 单位的插件有很多,出名的有 postcss-px-to-viewport 和 postcss-pxtorem,前者是将 px 转成 vw,后者是将 px 转成 rem,精简了不罕用的配置。将成为vw优先单位应用,以rem作为回退模式。思考到vw在挪动设施的反对度不如rem,这款插件很好的解决了该问题。而后简略的介绍下。 装置指令 $ npm install @ moohng / postcss-px2vw --save-dev复制代码应用办法首先创立一个.postcssrc.js文件,而后配置 module.exports = { plugins: { '@moohng/postcss-px2vw': {}}}复制代码例子: 应用前: .box { border: 1px solid black; margin-bottom: 1px; font-size: 20px; line-height: 30px;}复制代码应用后: .box{ border: 1px solid black; margin-bottom: 1px; font-size: 0.625rem; font-size: 6.25vw; line-height: 0.9375rem; line-height: 9.375vw;}复制代码配置方面viewportWidth:对应设计图的宽度,用于计算 vw。默认 750,指定 0 或 false 时禁用 rootValue:根字体大小,用于计算 rem。默认 75,指定 0 或 false 时禁用 unitPrecision:计算结果的精度,默认 5 minPixelValue:小于等于该值的 px 单位不作解决,默认 1 留神:该插件只会转换 px 单位。rootValue 个别倡议设置成 viewportWidth / 10 的大小,将设计图分成10等分。因为浏览器有最小字体限度,如果设置得过小,页面可能跟预期不统一 ...

August 10, 2021 · 2 min · jiezi

关于vue.js:尤雨溪凌晨官宣Vue-32-已发布

今日凌晨,尤雨溪在微博平台官宣 Vue 3.2 已公布,并示意: <script setup> + TS + Volar = 真香 Vue 3.2 版本包含许多重要的新性能和性能改良,但并不蕴含重大更改。 新的单文件组件性能:<script setup> 是一种编译时语法糖,可在 SFC 内应用 Composition API 时极大地晋升工作效率。 <style> v-bind 在 SFC 标签中启用组件状态驱动的动静 CSS 值。<style> 一起应用这两个新性能的示例组件: <script setup>import { ref } from 'vue'const color = ref('red')</script><template> <button @click="color = color === 'red' ? 'green' : 'red'"> Color is: {{ color }} </button></template><style scoped>button { color: v-bind(color);}</style>网络组件Vue 3.2 引入了一种应用 Vue 组件 API 轻松创立原生自定义元素的新办法:defineCustomElement import { defineCustomElement } from 'vue'const MyVueElement = defineCustomElement({ // normal Vue component options here})// Register the custom element.// After registration, all `<my-vue-element>` tags// on the page will be upgraded.customElements.define('my-vue-element', MyVueElement)这个 API 容许开发者创立 Vue 驱动的 UI 组件库,这些库能够与任何框架一起应用,或者基本没有框架。咱们还在文档中增加了一个对于在 Vue 中应用和创立 Web 组件的新局部。 ...

August 10, 2021 · 1 min · jiezi

关于vue.js:Web3vueclipluginweb3modal-快速来创建你的第一个以太坊-dAPP

Web3是为让互联网更去中心化、可验证、平安而发动的一组宽泛的静止和协定;Web3愿景是实现无服务器、去中心化的互联网,即用户把握本人身份、数据和命运的互联网;Web3将启动新寰球数字经济零碎,发明新业务模式和新市场,突破平台垄断,推动宽泛的、自下而上的翻新。 从Web2.0到Web3.0常识储备 web3.jsDApp 的 Solidity 合约IPFS + DAPP 真正的WEB3.0的时代到来 前言在工作中,每天都会反复昨天的工作(复制粘贴), 因为从事区块链的工作,必不可少的就是写DAPP了。 对于web端DAPP实现,利用web3js和以太坊网络的上的节点合约交互。DAPP次要公布在 Imtoken 和Metamask等等钱包上当然也有pc端的。业界ETH上的Dapp比拟有名的就是:uniswap。 思考 : 它是怎么做到能够连贯这个多的钱包的? 而后连夜翻导它的源码,惋惜人家是react写的(想拷贝人家的代码 本人用的想法幻灭了!”狗头“),我的dapp用的vuejs写的。苦逼 要不颠覆了用react在从新写吧,不行呀,那就照抄吧... 既然这种代码常常用 那就写个vue-cli-plugin-web3modal 这样就可插拔了,美滋滋 那为什么不自定义cli呢?应用vue add vue-cli-plugin-web3modal 或者 npm install --save-dev vue-cli-plugin-web3modalyarn add vue-cli-plugin-web3modal --dev依提醒能够依据本人的状况一步步的来配置,期待下载依赖(可能会等很久,因为要下载钱包节点提供者SDK) 目录构造src│ ├── App.vue│ ├── assets│ │ └── logo.png│ ├── components│ │ ├── ConnectWallteExample.vue│ │ └── HelloWorld.vue│ ├── hooks│ │ └── useWallte.js // 外围逻辑│ ├── main.js│ ├── registerServiceWorker.js│ └── web3│ ├── abis.js // 提供abis│ ├── chains.js│ ├── config.js // 配置项│ ├── constants.dev.js│ ├── constants.js│ └── tools.jssrc/web3/config.js, 默认应用Metamask的web3提供者 ,providerOptions 配置能够参考 https://github.com/Web3Modal/..., ...

August 9, 2021 · 2 min · jiezi

关于vue.js:路由刷新数据丢失-vuex数据读取的问题

低级路由依据传递的参数申请数据,渲染到页面后刷新后页面空白排查了很久,总感觉是携带的参数的问题,最初发现是申请的数据没有正确的读取,用计算属性解决了路由跳转传参 <li v-for="nav in leftNav" :key="nav.id"> <router-link class="homeLink" active-class="homeActive" :to="{ name: nav.tab, params: { tab: nav.tab } }" >{{ nav.title }}</router-link > </li>路由配置const homeRouter = { path: '/home', component: Home, meta: { title: "主页" }, children: [ { name: "all", path: "all/:tab", component: All }, ]}子路由发送申请子路由 activated() { console.log(this); this.$store.dispatch("getTopic", this.$route.params.tab); },vuex import axios from 'axios';const topicData = { actions: { getTopic(context, value) { axios.get(`https://cnodejs.org/api/v1/topics?tab=${value}`).then(res => { context.commit('GETTOPIC', res.data) console.log("依据" + value + "申请的数据", context.state) }).catch(err => { console.log(err.message) }) } }, mutations: { GETTOPIC(state, value) { state.topic = value.data } }, state: { topic: [] },}export default topicData子路由读取申请的数据起初读取失败的写法 ...

August 9, 2021 · 1 min · jiezi

关于vue.js:Vue表单设计器的终极解决方案

VForm是一个基于Vue 2.0和Element UI的高级表单组件,定位为前端开发人员提供疾速搭建表单、实现表单交互和数据收集的性能。 VForm全称为Variant Form,寓意为灵便的、动静的、多样化的Vue表单组件。VForm提供了丰盛的组件属性设置、表单交互事件和API办法,点此体验:VForm体验 VForm性能一览:====================================================== 拖拽式可视化表单设计,所见即所得;丰盛的表单组件反对,蕴含20多种表单根底组件和高级组件;反对多种布局容器,蕴含栅格、表格、页签、子表单;裸露组件交互事件,可解决简单交互逻辑;提供丰盛的组件API办法;提供丰盛的组件属性设置;组件反对自定义CSS款式;组件反对自定义校验;反对多语言国际化,内置中英文两种语言;反对PC/H5两种表单设计模式;表单设计反对撤销、重做历史性能;良好的开放性,反对扩大组件API办法;反对Chrome、FireFox、Safari、Edge等风行浏览器,兼容IE 11浏览器;反对浏览器缓存性能,主动保留表单最新状态,毋庸放心工作成绩失落;可导出Vue组件或HTML源码,不便在历史我的项目中集成;VForm高级交互示例——实现子表单的小计和累计自动更新: ======================================================技术交换:WX搜寻“vformAdmin” 开源仓库:https://gitee.com/vdpadmin/VFormRender 语雀文档:https://www.yuque.com/variantdev/vform

August 9, 2021 · 1 min · jiezi

关于vue.js:vue-eslint报错解决

vue我的项目执行 npm run serve 启动时报以下谬误(理论谬误很多,仅复制两个) error in ./src/router/index.jsModule Error (from ./node_modules/eslint-loader/index.js):error: Parsing error: Unexpected token import at src\router\index.js:11:26: 9 | path: '/', 10 | name: 'home',> 11 | component: () => import('@/views/home/Index'), | ^ 12 | redirect: '/subscribe', 13 | children: [ 14 | {1 error found. error in ./src/mixins/logoTitle.jsModule Error (from ./node_modules/eslint-loader/index.js):error: Parsing error: Unexpected token getLogoTitle at src\mixins\logoTitle.js:3:15: 1 | export default { 2 | methods: {> 3 | async getLogoTitle() { | ^ 4 | this.setLogoAndTitle(this.$localstore.get('logoTitle')); 5 | await this.setLogoTitle(); 6 | },1 error found.起因是eslint校验代码时babel还未解决代码,在.eslintrc.js中 extends: [], 删掉所有,只保留'plugin:vue/essential' 一项 ...

August 9, 2021 · 1 min · jiezi

关于vue.js:连尤雨溪都没实现用-babel-编译-vuejs-template-支持-Optional-Chaining

GitHub Repo: vue-template-babel-compiler应用 Babel 为 Vue.js SFC 启用 Optional Chaining(?.), Nullish Coalescing(??) 等诸多 ES 新语法。 示例 个性vue-template-compiler && vue-template-es2015-compiler 的所有性能新语法: Optional Chaining, Bigint, nullish coalescing and more自定义语法、babel 插件等等...用法1. 装置npm install vue-template-babel-compiler --save-dev2. 配置1. Vue-CLIVue-CLI 配置演示我的项目 // vue.config.jsmodule.exports = { chainWebpack: config => { config.module .rule('vue') .use('vue-loader') .tap(options => { options.compiler = require('vue-template-babel-compiler') return options }) }}2. Nuxt.jsNuxt.js 配置演示我的项目 // nuxt.config.jsexport default { // Build Configuration: https://go.nuxtjs.dev/config-build build: { loaders: { vue: { compiler: require('vue-template-babel-compiler') } }, }, // ...}3. Webpack// your webpack.config.js where config vue-loadermodule.exports = { // ... module: { rules: [ { test: /\.vue$/, loader: 'vue-loader', options: { compiler: require('vue-template-babel-compiler') } } ] }}欢送 Issues && PR.

August 8, 2021 · 1 min · jiezi

关于vue.js:100行代码理解vue中的depwatchcomputed机制

const data = { flag: false, firstName: 'Zheng', lastName: 'Yimeng'}const computed = { name() { if (!data.flag) { return '你拿不到' } return data.firstName + ' ' + data.lastName },}function observe(obj) { const keys = Object.keys(obj) /** 须要留神这里,我并没有对传入的 obj 自身做响应式解决,是为了简化代码 (vue 源代码对传入的对象也做了解决) */ keys.forEach(key => { observer(obj, key) })}function observer(obj, key) { let value = obj[key] //?1 为什么须要这个货色 let dep = new Dep() // 每个属性都有一个本身的 dep。 Object.defineProperty(obj, key, { get() { if (Dep.target) { console.log(`收集依赖 ${key}`) Dep.target.addDep(dep) } return value //?1 因为在这里写 obj[key] 的时候相当于从新拜访这个 key,会再次触发 get 办法,进入死循环 }, set(newVal) { if (value === newVal) return value = newVal if (dep.subs.length) { console.log(`${key} 扭转了,我要更新它记录的 watcher 了`) dep.notify() } } })}function initComputed(computed) { /** 留神我这里搞 computed 从新拆来搞只是为了让大家看明确,vue 源代码和我不一样,然而原理相似 */ const watchers = {} const keys = Object.keys(computed) keys.forEach(key => { watchers[key] = new Watcher(computed[key]) }) return watchers}function Dep () { this.subs = []}Dep.prototype.notify = function() { this.subs.forEach(watcher => watcher.update())}function Watcher(func) { this.get = func this.deps = [] Dep.target = this this.value = this.get() // 函数体是 { return data.firstName + ' ' + data.lastName },所以会调用 data.firstName 和 data.lastName 的 get 办法 Dep.target = null}Watcher.prototype.addDep = function(dep) { // 这里为什么须要记录 dep? 因为:假如当初 flag 为 true,那么咱们的 computed.name 收集依赖的时候收集到了 data.flag, data.firstName, data.lastName,这三个属性每个都有一个 dep,批改其中一个都会从新调用 dep.notify() 从而更新 name 值, 然而当咱们批改其中的一个属性的时候,这个收集的依赖其实就曾经扭转了,比方批改了 flag = false,再批改 data.firstName 和 data.lastName 的时候,就不应该再从新求 computed.name 值了,因为走不到那一步,那么 data.firstName 和 data.lastName 的 dep 就应该为空,这样在批改 data.firstName 和 data.lastName 的时候因为他们的 dep 为空就不会从新求 computed.name 值了 this.deps.push(dep) dep.subs.push(this) // 到这里的时候,还记得吗?本身属性的 watcher 就被记录下来了}Watcher.prototype.update = function() { this.deps.forEach(dep => dep.subs = []) // 在这里把该 计算属性 对应的每个 依赖属性 的 dep 都清空 Dep.target = this let value = this.get() // 这里调用 get 后从新收集依赖 Dep.target = null if (this.value !== value) { this.value = value // value扭转,渲染页面 }}function MyVue({data, computed}) { observe(data) this.watchers = initComputed(computed) // 这里把属性简略地绑给实例自身 Object.keys(this.watchers).forEach(key => { // 这里 computed 我假如不让手动批改它,所以不作解决 Object.defineProperty(this, key, { get() { return this.watchers[key].value } }) }) Object.keys(data).forEach(key => { Object.defineProperty(this, key, { get() { return data[key] }, set(newVal) { data[key] = newVal } }) })}window.vm = new MyVue({data, computed})初始化dataobserve(data)function observe(obj) { const keys = Object.keys(obj) /** 须要留神这里,我并没有对传入的 obj 自身做响应式解决,是为了简化代码 (vue 源代码对传入的对象也做了解决) */ keys.forEach(key => { observer(obj, key) })}function observer(obj, key) { let value = obj[key] //存储旧值 let dep = new Dep() // 每个属性都有一个本身的 dep。 Object.defineProperty(obj, key, { get() { if (Dep.target) { console.log(`收集依赖 ${key}`) Dep.target.addDep(dep) } return value //?1 因为在这里写 obj[key] 的时候相当于从新拜访这个 key,会再次触发 get 办法,进入死循环 }, set(newVal) { if (value === newVal) return value = newVal if (dep.subs.length) { console.log(`${key} 扭转了,我要更新它记录的 watcher 了`) dep.notify() } } })}为每个data属性生成一个dep对象,在属性的get办法中,触发watch.addDep办法实现dep和watch的互相收集。在set办法中告诉watch ...

August 8, 2021 · 3 min · jiezi

关于vue.js:vue-获取-url-参数以及直接向对象写属性自动转换为-url

import { reactive, computed } from "vue";/** 返回一个 params对象 与 href 字符串computed ,href 依赖于 params * @example * ```js * const [AppOptions, href] = useParamsObj(undefined, {}); * // 将基于 AppOptions 计算得来的 href 设置到 history * watchEffect(() => history.replaceState("", "", href.value)); * ``` */export function useParamsObj<T extends object>( urlStr = document.location.toString(), defaultParams: T) { const url = new URL(urlStr); const searchParams = url.searchParams; const params = reactive(defaultParams); searchParams.forEach((v, k) => { try { (params as any)[k] = atob(v); } catch (error) { // 兼容间接输出的状况 (params as any)[k] = v; } }); const href = computed(() => { Object.keys(params).forEach((k) => { const v = btoa((params as any)[k] || ""); searchParams.set(k, v); }); return url.href; }); return [params, href] as const;}应用实例 ...

August 8, 2021 · 1 min · jiezi

关于vue.js:vuecomputed-的源码解析

带着问题开始咱们重点阐明,几个问题的源码实现 1、computed 的 月老身份的起源2、computed 怎么计算3、computed 的缓存是怎么做的4、computed 什么时候初始化5、computed 是怎么能够间接应用实例拜访到的问题不会按程序解析,因为这些问题会相互关联,在摸索源码的过程中,你天然会失去答案 初始化过程function Vue(){ ... 其余解决 initState(this) ...解析模板,生成DOM 插入页面}function initState(vm) { var opts = vm.$options; if (opts.computed) { initComputed(vm, opts.computed); } .....}没错,当你调用 Vue 创立实例过程中,会去解决各种选项,其中包含解决 computed 解决 computed 的办法是 initComputed,上面就呈上 源码 initComputedfunction initComputed(vm, computed) { var watchers = vm._computedWatchers = Object.create(null); for (var key in computed) { var userDef = computed[key]; var getter = typeof userDef === 'function' ? userDef: userDef.get; // 每个 computed 都创立一个 watcher // watcher 用来存储计算值,判断是否须要从新计算 watchers[key] = new Watcher(vm, getter, { lazy: true }); // 判断是否有重名的属性 if (! (key in vm)) { defineComputed(vm, key, userDef); } }}initComputed 这段代码做了几件事 ...

August 7, 2021 · 3 min · jiezi

关于vue.js:vueelement上传文件图片使用和解析后端返回二进制文件图片视频

1.开发环境 vue2.电脑系统 windows10专业版3.在开发的过程中,咱们常常会应用到element进行文件的上传和二进制文件的解析,上面我来分享一下。4.element图片上传,代码如下: // template中代码如下:<el-upload list-type="picture-card" action="" :limit="1" :auto-upload="false" //要害 代码 :on-change="onchangeMainpicture" //文件上传时触发函数 > <i slot="default" class="el-icon-plus"></i> <div slot="file" slot-scope="{ file }"> <img class="el-upload-list__item-thumbnail" :src="file.url" alt="" /> <span class="el-upload-list__item-actions"> <span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)" > <i class="el-icon-zoom-in"></i> </span> <span v-if="!disabled" class="el-upload-list__item-delete" @click="handleDownload(file)"> <i class="el-icon-download"></i> </span> <span v-if="!disabled" class="el-upload-list__item-delete" @click="handleRemove(file)"> <i class="el-icon-delete"></i> </span></span> </div></el-upload>return 中代码如下:uploadimgurl: { // 主图 Mainpictureurl: "", // 主题内容 Mainimagecontenturl: "", // 视频 videourl: "",},// methods中增加如下代码onchangeMainpicture(file, fileList) { console.log(file); this.uploadimgurl.Mainpictureurl = file.raw;},5.视频上传 // template代码<el-upload list-type="picture-card" :on-change="onchangevideo" action="" :limit="1" :auto-upload="false"> <i slot="default" class="el-icon-plus"></i> <div slot="file" slot-scope="{ file }"> <video :src="file.url" class="avatar" controls="controls"> </video> </div></el-upload>// return 代码如上// methods办法 如下:onchangevideo(file, fileList) { // console.log(event); // console.log(file); // console.log(fileList); this.uploadimgurl.videourl = file.raw;},6.提交代码 ...

August 6, 2021 · 3 min · jiezi

关于vue.js:毕设项目VueGo前端后端一体化-企业级微服务网关项目

download:(毕设我的项目)Vue+Go前端后端一体化 企业级微服务网关我的项目服务器端代码,server_tcp.py !/usr/bin/env python-- coding:utf-8 --执行客户端发送过去的命令,并把执行后果返回给客户端import socket, traceback, subprocess host = ''port = 51888 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((host, port))s.listen(1) while 1: try: client_socket, client_addr = s.accept()except Exception, e: traceback.print_exc() continuetry: print 'From host:', client_socket.getpeername() while 1: command = client_socket.recv(4096) if not len(command): break print client_socket.getpeername()[0] + ':' + str(command) # 执行客户端传递过去的命令 handler = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE) output = handler.stdout.readlines() if output is None: output = [] for one_line in output: client_socket.sendall(one_line) client_socket.sendall("\n") client_socket.sendall("ok")except Exception, e: traceback.print_exc()try: client_socket.close()except Exception, e: traceback.print_exc()2.客户端代码 client_tcp.py ...

August 5, 2021 · 1 min · jiezi

关于vue.js:vue使用sass中deep报错

1.开发环境 vue2.电脑系统 windows10专业版3.在应用vue开发的过程中,咱们常常会应用到css的预处理器,我应用的是sass,然而在最新的版本中,应用 /deep/ 报错了 ,上面让咱们来看一下。4.废话不多说,间接来看 // 去网上看了很多材料,而后最多的答案无非就是应用::v-/deep/ 来替换/deep/,的确无效,然而会不能应用scss嵌套写法的问题,5.解决办法如下: // 装置 sass-loader7.0.0 版本npm install sass-loader@7.0.0 -D// 装置 node-sass npm i node-sass -D6.再次应用 .cupload { width: 100%; &/deep/ .el-upload--picture-card { width: 100%; }}// 当初应用 /deep/ 就没有报错了7.本期的分享到了这里就完结啦,心愿对你有所帮忙,让咱们一起致力走向巅峰。

August 5, 2021 · 1 min · jiezi

关于vue.js:封装h5-video-视频播放器vue-组件弹框的形式弹出子组件video

h5 video 标签只能播放三种视频格式:MP4 = MPEG 4文件应用 H264 视频编解码器和AAC音频编解码器WebM = WebM 文件应用 VP8 视频编解码器和 Vorbis 音频编解码器Ogg = Ogg 文件应用 Theora 视频编解码器和 Vorbis音频编解码器* *通过下面的信息咱们会发现只有h264编码的MP4视频(MPEG-LA公司)、VP8编码的webm格局的视频(Google公司)和Theora编码的ogg格局的视频(iTouch开发)能够反对html5的<video>标签。**1.封装的子组件: <template> <div style="width:100%;height: 300px;"> <!-- MP4 WebM Ogg --> <video controls style="width:100%;height:100%;" v-if="okPlay"> <source :src="previewVideoUrl" @error="loadError" /> 您的浏览器不反对播放。 </video> <div v-else style="width:100%;height:100%;"> <p><a :href="previewVideoUrl">点击查看</a></p> <!-- <div class="player-error"></div> --> <el-image style="width:100%;height:90%;overflow-x:scroll" src="@assets/images/player-error.png" fit="contain" > </el-image> </div> </div></template><script>import { ref } from "vue";export default { name: "HyVideoPlayer", props:{ previewVideoUrl: String }, setup(props, context){ const okPlay = ref(true) const loadError = ()=>{ //管制加载失败时, 显示默认图片 console.log("load audio error") okPlay.value = false } return { okPlay, loadError } }, </script>当浏览器不反对video 时,会提醒"您的浏览器不反对播放。"当视频文件不存在或不反对播放时(如flv格局), 在@error 事件上抓取到 ...

August 5, 2021 · 1 min · jiezi

关于vue.js:CRMEB知识付费系统优势及常见问题解答

很多小伙伴会在理解或者应用的时候会很有的疑难,比方CRMEB常识付费零碎为什么没有小程序?这个零碎有什么劣势?为什么用OSS贮存?等等,明天小编把这些常见的问题收集整理了一下。 一、常识付费零碎装置必备: 装置配置h5端: 服务器、域名、阿里云开明对象存储oss(必须)、阿里云视频点播(抉择)、阿里云视频直播(须要直播开明)、短信(阿里云短信、crmeb短信平台二选一) 装置配置公众号端: 服务器、域名、阿里云开明对象存储oss(必须)、阿里云视频点播(抉择)、阿里云视频直播(须要直播开明)、短信(阿里云短信、crmeb短信平台二选一)、微信公众号(服务号) 二、常识付费为什么没有小程序? 1.常识付费小程序审核难度大,门槛高 2.公众号小程序优劣比照 公众号:公众号次要是进行营销工作,而且也是进行企业一些新闻、推广信息的传递工作,个别都是会进行信息内容的流传。微信公众号次要是借助于H5技术来进行交互,营销和信息传递等服务项目还是通过微信公众号来进行确认。而且微信公众号是反对朋友圈、微信群之间的互相交换和分享等,也能够长期叠加来增长粉丝量,对于用户留存、公域流量转私域流量很敌对。 小程序: 小程序次要是面向产品,更多还是提供根底的服务。是属于微信的云端利用,不必装置APP,不是原生APP,通过了双向通信的形式,来提供更加靠近于原生APP的体验。然而小程序即用即走的个性,不可转发朋友圈,也无奈向公众号一样长期经营积攒粉丝,用户留存。 3.saas版的为什么能够用小程序?saas和独立部署的区别? 什么是saas? SaaS是一种软件交付形式,它能够通过Internet连贯和Web浏览器从任何设施拜访数据。 软件即服务(SaaS)也是一种软件散发模型,其中第三方提供商托管应用程序,并通过Internet将其提供给客户。 总结:saas就是第三方给您开明了一个账号,实现店铺经营,数据信息都在第三方服务器,本人无奈把握。 本地独立部署 自建服务器环境数据存储在一个集中的数据中心,所有的分支机构通过浏览器共享软件零碎平台,实现企业合规治理,实时数据分析 劣势: 从平安方面来讲:本地部署是基于客户本身的服务器部署,数据无需上传至第三方服务器或云端,私密数据的安全性更有保障; 从技术方面来讲:所有数据均在本地,更不便于二次整顿和开发。从资源方面来讲:无形可见的硬件资产,资源可控及灵便调配。另外,因为是通过内联网,集成绝对容易。数据在零碎之间的传输会更快。 三、常识付费直播费用计算 常识付费直播调用的是阿里云直播,视频直播的计费形式分为3种,您采纳不同的计费形式,计算是不同的。 按日峰值带宽 按月95峰值带宽 按流量 直播服务费用您能够参考一下:https://help.aliyun.com/docum... 阿里云视频直播资源包: https://www.aliyun.com/produc... 四、常识付费零碎为什么要用对象贮存OSS? 1.什么是对象贮存OSS? 阿里云对象存储OSS(Object Storage Service)是一款海量、平安、低成本、高牢靠的云存储服务,提供99.9999999999%(12个9)的数据持久性,99.995%的数据可用性。多种存储类型供选择,全面优化存储老本。 2.应用对象贮存OSS的益处 常识付费零碎个别波及的内容量比拟微小,因为蕴含音频、图文、视屏等等素材,都须要比拟大、更平安的贮存形式,阿里云对象贮存OSS是个比拟好得多抉择。 缓解服务器压力对象贮存OSS,更平安、牢靠、稳固、智能 详情参考:https://www.aliyun.com/produc... 常识付费零碎对象贮存OSS配置教程: https://www.kancloud.cn/crmeb... 四、常识付费挪动端首页排版能够自定义编辑吗? 能够,常识付费v1.4.4版本曾经全面实现首页自定义,客户可依据需要,自在布局首页排版,实现一套零碎多种场景模式。 常识付费挪动端首页设置教程: https://www.kancloud.cn/crmeb... 如果你感觉这篇文章对你有点用的话,麻烦请给咱们的开源我的项目点点star:http://github.crmeb.net/u/defu 不胜感激 !

August 5, 2021 · 1 min · jiezi

关于vue.js:vue解析后端返回的二进制图片

1.开发环境 vue2.电脑系统 windows10专业版3.在开发的过程中,咱们在数据交互的过程中,后端返回的图片是一个二进制的模式,前端vue怎么解析呢?上面我来分享一下。4.废话不多说,后端返回的二进制是乱码: 很显著,后端返回的是一个 二进制的模式,那么咱们如何解析呢?办法如下5.vue解析后端返回二进制,代码如下: export const badlisttabledetailsfiles = (value) => { return http1({ url: "/api/sys/image", method: "post", data: value, responseType: 'blob', // 要害代码 });}; badlisttabledetailsfiles({ fileId: key,}).then((res) => { console.log("我是详情外面files接口"); console.log(res); let reader = new FileReader(); //要害代码 reader.readAsDataURL(res); // 要害代码 console.log(res); this.filesimgs = window.URL.createObjectURL(res); // 要害代码 console.log(this.filesimgs); this.filesimgsarr.push(this.filesimgs);});6.成果如下: // 通过一顿操作之后,后端返回的图片失常展现了7.本期的分享到了这里就完结啦,心愿对你有所帮忙,让咱们一起致力走向巅峰。

August 4, 2021 · 1 min · jiezi

关于vue.js:CRMEB多商户二开流程介绍

本文介绍一下CRMEB多商户二次开发的操作流程,从创立数据库,到实现一个残缺增加数据的过程,其余更多办法实现只是路由和办法名的差别,也就不过多赘述。一、创立数据库例如数据库名为:eb_is_test字段为:id,nameSQL:CREATE TABLE eb_is_test (id int(11) unsigned NOT NULL AUTO_INCREMENT,name varchar(111) DEFAULT NULL, PRIMARY KEY (id)) ENGINE=InnoDB DEFAULT CHARSET=utf8; 二、创立必要文件,为了更好的治理我给这个模块独自减少一个test文件目录。1.首创立model :门路:app/common/moel/test/IsTest.php代码如下:<?phpnamespace app\common\model\test; use app\common\model\BaseModel; class IsTest extends BaseModel{ public static function tablePk(): ?string{ return 'id';}public static function tableName(): string{ return 'is_test';}}2.创立dao文件:门路 :app/common/dao/test/IsTestDao.php代码如下:<?phpnamespace app\common\dao\test; use app\common\dao\BaseDao;use app\common\model\test\IsTest; class IsTestDao extends BaseDao{ /** * @return string * @author Qinii */protected function getModel(): string{ return IsTest::class;}} 3.创立repoository文件门路:app/common/repoository/test/IsTestRepoository.php代码如下:<?phpnamespace app\common\repositories\test; use app\common\dao\test\IsTestDao;use app\common\repositories\BaseRepository; class IsTestRepository extends BaseRepository{ ...

August 4, 2021 · 1 min · jiezi

关于vue.js:RSA分段解密-Vue

前言上一篇文章实现了 Java RSA的分段加解密 ,这里咱们介绍在 Vue 我的项目中如何应用 RSA 分段解密,这里的加解密场景是: 后端私钥分段加密 - 前端公钥分段解密前端如何应用公钥解密这里不做反复叙述,重视点是分段解密,有须要的参考之前的文章:RSA加密 - Vue 具体实现src/libs/jsencrypt/lib/JSEncrypt.js中增加新的解密办法decryptLong /*** 分段解密* @param string* @returns {string|boolean}*/ JSEncrypt.prototype.decryptLong = function (string) { let k = this.getKey(); let MAX_DECRYPT_BLOCK = 128;//分段解密最大长度限度为128字节 try { let ct = ""; let t1; let bufTmp; let hexTmp; let str = bytesToHex(string); let buf = hexToBytes(str); let inputLen = buf.length; //开始长度 let offSet = 0; //完结长度 let endOffSet = MAX_DECRYPT_BLOCK; //分段解密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_DECRYPT_BLOCK) { bufTmp = buf.slice(offSet, endOffSet); hexTmp = bytesToHex(bufTmp); t1 = k.decrypt(hexTmp); ct += t1; } else { bufTmp = buf.slice(offSet, inputLen); hexTmp = bytesToHex(bufTmp); t1 = k.decrypt(hexTmp); ct += t1; } offSet += MAX_DECRYPT_BLOCK; endOffSet += MAX_DECRYPT_BLOCK; } return ct; } catch (ex) { console.log("RSA分段解密失败", ex) return false; } };增加JSEncryptRSAassist.js到src/libs/jsencrypt/lib/目录下 ...

August 3, 2021 · 2 min · jiezi

关于vue.js:RSA加密-Vue

前言上一篇博客RSA加密 - Java实现了Java版的RSA公钥加密-私钥解密,私钥加密-公钥解密,这篇博客实现Vue下的加解密,记录两种前后端下加解密的场景: 前端公钥加密 - 后端私钥解密后端私钥加密 - 前端公钥解密附上其它链接:RSA加密 - JavaRSA分段加密 - JavaRSA分段解密 - Vue 前端公钥加密-后端私钥解密这种状况较为简单,是通用的做法 装置jsencrypt npm install jsencryptRSAEncryption.js /** * 非对称加密-RSA * 前端公钥加密 - 后端私钥解密 * */import { JSEncrypt } from 'jsencrypt/lib/JSEncrypt'// 这里的公钥在Java端生成const PUBLIC_KEY = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCaaI4MBywkCjIppZnraqN3pbrcZTq/t0+aMBo8K3pK9BDD6XkM6N2Yfcva7BSFbUWuAcI7piXak0UKn9CElDuhNzUSgQn4IXKxIt3Iva5cV83qYumj+0yRjjLT8Muu1Y1rgBZjY9oBwhVoV+Twg25+UJ+6Q6HM4xTwQQJDoyy4jwIDAQAB';// 注:失常状况下私钥并不会记录在前端,这里应用私钥解密只是记录私钥解密办法const PRIVATE_KEY = 'MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJpojgwHLCQKMimlmetqo3elutxlOr+3T5owGjwrekr0EMPpeQzo3Zh9y9rsFIVtRa4BwjumJdqTRQqf0ISUO6E3NRKBCfghcrEi3ci9rlxXzepi6aP7TJGOMtPwy67VjWuAFmNj2gHCFWhX5PCDbn5Qn7pDoczjFPBBAkOjLLiPAgMBAAECgYBnBBKhG7frY5IMDxwd4Euna767hB4qAlbte+JE+ozgrOzyiDXm0wXk0yjKqm8WhczTRwEbYsImjdKmP/GSQoN1AU7yEzM8j0Jgq46m9ZVrHhu2NpuZpr+XueWnA6FNz6tybBgcCwA4t8dvfbOrvjqhrCu01O1xWIpjronyFBN4IQJBAPGuF58xjXyANnp5YU8NhUQ73tTIveRlOpMXDSYkf9lWG26XIGUIsTe0f5jssiNmYtxG+lUm9LLfZgOLcrVkDZ0CQQCjjrBNMXub49efVTCg+nCGT2QXW2BHg/qs5vu8Y34LUHoD/hoEJ+AOWOdnhpRoYOpBwJAm3Gu4a1VmZGGafp0bAkAdfY3aWhSWtZpwNXF/UPoLCnc1Zc1uGkAchLqRBfEn1w7/3qcQTRA66OaNBYzzLuIvWOXhECDZ1tK+6fw0UCItAkAOLibW6n1fDKf7JnWq30u2OVfiNofoa2bmarhUowOgk3+grP0wcwyX8dlOPnrLeeuVe86DsASe3p9u2zEjJesVAkEAhkLiv4TXrC1QlJl7ghksUfFmdT7M4Zxlzj10ConMgq68HkLdmn2nNLsjhUHGwJe3EqM6aozn4zw/Z7uPIT9Fsw==';export const RSAENCRY = { /** * 公钥加密 * @param val 须要加密的字符串 * @return string 返回加密后果 */ encryptByPublicKey: function (val = '') { if(val === ''){ return ''; } let encryptor = new JSEncrypt() // 新建JSEncrypt对象 encryptor.setPublicKey(PUBLIC_KEY) // 设置公钥 return encryptor.encrypt(val) // 对须要加密的数据进行加密 }, /** * 私钥解密 * @param val * @returns {string|false|null|PromiseLike<ArrayBuffer>} */ decryptByPrivateKey: function (val = '') { if(val === ''){ return ''; } let decrypt = new JSEncrypt() // 新建JSEncrypt对象 decrypt.setPrivateKey(PRIVATE_KEY) // 设置私钥 return decrypt.decrypt(val) // 对须要解密的数据进行解密 }}验证加解密 ...

August 3, 2021 · 2 min · jiezi

关于vue.js:excel流文件的前端展示显示表格

装置和引入xlsx依赖包npm install -S xlsximport XLSX from 'xlsx' excel表格显示<div class="tableItem"> <el-table :data="tableData.slice((currpage - 1) * pagesize , currpage * pagesize)" :row-class-name="tableRowClassName" :cell-style="columnStyle" border> <el-table-column v-for="(value,key,index) in tableData[0]" :key="index" :prop="key" :label="key" min-width="160px" align="left" :render-header="renderHeader">> <template slot-scope="scope"> {{tableData.slice((currpage - 1) * pagesize , currpage * pagesize)[scope.$index][key]}} </template> </el-table-column> </el-table></div>//不须要分页的话 这段和下面 "tableData.slice..." 间接换成tableData即可<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currpage" :page-sizes="[20, 40, 60, 80]" :page-size="pagesize" layout="total, sizes, prev, pager, next, jumper" :total="totalNum"></el-pagination>import XLSX from 'xlsx'import axios from 'axios'export default { data() { return { currpage:1, pagesize:20, totalNum:0, tableData: [], card: [], // excel表格sheet的数组 cardActive: '', // excel表格以后显示的sheet workbook: {}, }; }, mounted () { this.showStandard('Doc/code.xlsx'); //通过服务器获取流 // this.readFile('code.xlsx') //获取前端public下的excel文件 },}获取excel的流文件因为后盾获取文件流是 .net core异步获取,所以这里用async 和 await 解决// 获取后盾的流文件async showStandard(excelUrl){ var type = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" var filePaths = [] filePaths.push(excelUrl) let res = await this.$axios.post("/api/Base/DownFileZip",filePaths,{ responseType: 'arraybuffer' }) var data = new Uint8Array(res) var workbook = XLSX.read(data, {type:"array"}) var sheetNames = workbook.SheetNames // 工作表名称汇合 this.workbook = workbook this.card = sheetNames this.cardActive = sheetNames[0] this.getTable(sheetNames[0])},// 获取前端的流文件readFile(url) { axios.get(url, {responseType:'arraybuffer'}).then((res) => { var data = new Uint8Array(res) var workbook = XLSX.read(data, {type:"array"}) var sheetNames = workbook.SheetNames // 工作表名称汇合 this.workbook = workbook this.card = sheetNames this.cardActive = sheetNames[0] this.getTable(sheetNames[0]) }) },getTable (sheetName) { this.Matches = [] this.currpage = 1 var worksheet = this.workbook.Sheets[sheetName] this.tableData = XLSX.utils.sheet_to_json(worksheet) //获取第一行(即表头) var header = XLSX.utils.sheet_to_json(worksheet,{header:1})[0] var tableTitle = this.tableData[0] var table0 = {} //这里对表头进行解决,因为获取的数据渲染表头是依据第一条数据, //当excel文件中第一条数据有为空时,第一条数据没有此属性,数据就不渲染,所以把为空的属性设置成“” for(var i=0;i<header.length;i++){ if(tableTitle.hasOwnProperty(header[i])){ table0[header[i]] = tableTitle[header[i]] }else{ table0[header[i]] = "" } } this.tableData[0] = table0 this.totalNum = this.tableData.length},设置表格款式//给表头增加标识renderHeader(h,{column,$index}){ return h( 'div',{style:'width:100%'},[ h('span', column.label), h('span', { class: "floatCR", style:'color:#0094CE;margin-left:15px;font-family:Eurostile Bold' },1==$index?'C':(3==$index?'R':'')) ], );},//给列设置背景色columnStyle({ row, column, rowIndex, columnIndex }) { if (columnIndex ==1||columnIndex ==3) { return 'background:rgba(147, 195, 235,0.05);' }},表格分页handleSizeChange(val) { this.pagesize = val},handleCurrentChange(val) { this.currpage = val},第一次写,就是想记录一下,有不标准的中央还请各位大哥赐教,谢谢! ...

August 3, 2021 · 2 min · jiezi

关于vue.js:vue提示报错vmodel

1.开发环境 vue2.电脑系统 windows10专业版3.在开发的过程中,咱们常常会应用到过滤器来解决一些问题,上面我来分享一下。4.废话不多说,间接上成果: 为什么调用过滤总是提醒这个错呢?5.解决办法 // v-model的值只能是一个变量,是无奈利用filter的,如果利用到filter能够应用 computed 计算属性来解决6.本期的分享到了这里就完结啦,心愿对你有所帮忙,让咱们一起致力走向巅峰。

August 3, 2021 · 1 min · jiezi

关于vue.js:vue使用antdesignvue中TreeSelect树选择异步加载数据

1.开发环境 vue2.电脑系统 windows10专业版3.在应用ant-design-vue开发的过程中,咱们在应用树形抉择的时候,因为数据量过大,咱们个别会点击父节点来申请子节点的数据,上面我来分享一下办法.4.废话不多说,间接上代码: <a-tree-select v-model="ruleForm.StoreCategoryobj.value2" tree-data-simple-mode style="width: 100%" :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }" :tree-data="ruleForm.StoreCategoryobj.options" placeholder="Please select" :load-data="StoreCategoryload" //异步加载数据的办法 @focus="StoreCategoryobjfocus" // 获取焦点的办法 :showSearch="true" //显示搜寻框 />StoreCategoryobj: { value2: "", options: [ { id: 1, pId: 0, value: "1", title: "Expand to load" }, { id: 2, pId: 0, value: "2", title: "Expand to load" }, { id: 3, pId: 0, value: "3", title: "Tree Node", isLeaf: true }, ], id: "",},5.在methods中增加如下代码: //获取焦点的时候,把绑定的值赋值为后端获取的数据StoreCategoryobjfocus() { console.log("获取焦点事件"); treetable({ pid: this.account.rootTypeId, storeId: this.account.storeId, }).then((res) => { console.log("我是树形构造的表格接口"); console.log(res); console.log(this.$Cmethods.treelist(res.result)); this.ruleForm.StoreCategoryobj.options = this.$Cmethods.treelist( res.result ); // this.ruleForm.StoreCategoryobj.options = this.$Cmethods.treelist( // res.result // ); // console.log(this.$Cmethods.treelist(res.result)); // this.ruleForm.StoreCategoryobj.options = this.$Cmethods.treelist( // res.result // ); });// 点击父节点的时候,申请子节点的数据StoreCategoryload(treeNode) { console.log(treeNode); console.log(treeNode.dataRef); return treetable({ pid: treeNode.dataRef.id, storeId: this.account.storeId, }).then((res) => { console.log("我是树形构造的表格接口"); console.log(res); console.log(res.result); console.log(this.$Cmethods.treelist(res.result)); console.log(this.ruleForm.StoreCategoryobj.options); treeNode.dataRef.children = this.$Cmethods.treelist(res.result); //把获取的子节点的数据,赋值为父节点中children });},6.全局树形过滤办法: ...

August 3, 2021 · 1 min · jiezi

关于vue.js:Vuejs-被选作维基百科的前端框架

昨日,维基媒体基金会 (Wikimedia Foundation) 发表正式采纳 Vue.js 作为将来的 JavaScript 框架 —— 用于维基百科的底层引擎 MediaWiki。 作为Platform Evolution 打算的一部分,维基媒体基金会对前端框架的评估于2019年年中开始,该打算旨在变革维基百科的技术栈平台和开发流程。 因为此我的项目的长期性和广泛性,维基媒体基金会示意他们为此成立了专门的前端架构工作小组,抉择了局部我的项目进行试点工作,并收到了踊跃的用户反馈,实现了最终的开发者满意度考察以进一步理解了无关开发人员的体验感。 反馈中大部分开发者示意“对与 Vue.js单干的前景示意必定”,而且“有信念在外部团队推广应用 Vue.js”。 试点让基金会对采纳 Vue.js 的倡议充满信心,其正在进一步施行 Vue.js 工具和产品迁徙布局,为此基金会还建设了维基媒体设计零碎团队,其持续工作和行将到来的优先事项包含: 筹备一个共享的 Vue.js 用户界面组件库决定 Vue 2 或 Vue 3,包含转换门路弄清楚如何构建组件库以及如何在MediaWiki 进行内外散发Vue.js 的作者尤雨溪也曾经在推特上分享了这一音讯:

August 3, 2021 · 1 min · jiezi

关于vue.js:elautocomplete的使用及clearable清除按钮功能失效及fetchsuggestions传递多个参数问题

本文记录一下el-autocomplete的应用和两个常见的问题需要剖析假如咱们有这样的一个需要: 当用户在输入框中输出内容后,出现关联倡议可选项信息,以供用户抉择.比方用户输出了“王”这个字,那么要出现对于“王”的所有的信息,什么“老王”、“王老吉"都进去了,用户点关联的倡议可选项,从而不便用户疾速输出。初始状况下,当用户的input输入框取得焦点的时候,与此同时,input输入框中的内容也是没有的时候,就出现用户之前搜寻过得历史记录。当用户输出了一些文字然而又backspace一个个删除掉了的时候,即当用户把输入框中的文字删除完当前的时候,也就是input输入框的内容为空的时候,再次出现历史记录这个时候应用el-autocomplete组件就能够疾速解决咱们的问题了el-autocomplete属性介绍fetch-suggestions属性绑定的是函数,函数的触发条件是当input输出的时候,或者用户在进入框键入字当前都会触发的,失常状况下回调函数的参数有两个,别离是queryString、和cb。queryString参数代表的值是用户填写到input输入框中的数据值,而cb指的又是一个函数,这里是高阶函数(柯里化)的用法,这里不赘述。cb函数接管的是一个数组,数组里是啥,input输入框关联呈现的下拉框就是啥,一一对应的。不过有固定格局要求。因为在el-autocomplete的底层代码里,是有着v-for循环指令的,至于循环的数组就是cb函数传递过去的数组,所以cb函数中的数组内容,也就是输出倡议的下拉框的内容 // html局部:fetch-suggestions="querySearch"// js局部querySearch(queryString, cb) {    cb([       {value:"老王"},       {value:"王老吉"} // 数组中的每一项都是一个对象,对象中必须要有value属性,否则不能显示,有没有别的属性不影响。起因是因为源码中定义的就是value字段   ])}// 如果后端给的数据结构不是这种的构造的话,能够应用数组的filter或者map办法本人组装一下数据结构格局图示如下: fetch-suggestions也能够传递多个数据,不过要应用闭包的模式才能够,这个后文会举例子再说的。fetch-suggestions,是用来做关联的数据搜寻,用户输出“王”字,获取关联的“老王”、“王老吉”选项值,当用户选中王老吉的时候,如果是一个搜寻性能,就须要搜寻王老吉的具体材料了,所以这个时候就须要应用el-autocomplete的select属性了 select属性select绑定的也是一个函数办法,当咱们点击抉择input输入框关联下拉框某个选项的时候,会拿到下拉框对应项的值。这个值能够传递给后端,用于向后端发申请查问选中的某一条数据的具体信息。 // html局部@select="handleSelect"// js局部handleSelect(item) { // 参数-选中的某一项 console.log("拿到数据作为参数去向后端发申请",item);}trigger-on-focus属性这个属性的作用是,管制fetch-suggestions是否在el-input获取焦点的时候触发。只有fetch-suggestions触发,就会向后端发申请,就会呈现input输入框关联下拉框(输出倡议列表),官网定义的是默认为:trigger-on-focus=true,就是输入框输入框一获取焦点,就呈现输出倡议列表,trigger-on-focus="true"这种形式能够用在获取历史搜寻数据场景,毕竟初始状况下能够让后端提供一下历史数据以供用户抉择。 当然如果是设置trigger-on-focus="false"的话,这样就不会在初始状况获取焦点的时候呈现输出倡议列表,在用户输出文字当前才去拿着用户在输入框输出的货色去发申请,问后端要数据。 具体用那种看具体需要。 咱们先看一下效果图,再看一下代码效果图 代码附上<template> <div id="box"> <el-autocomplete :fetch-suggestions="querySearch" v-model="inputValue" @select="handleSelect" :debounce="0" :trigger-on-focus="true" clearable @clear="blurForBug()" ></el-autocomplete> </div></template><script>export default { data() { return { inputValue: "", }; }, methods: { //输入框获取焦点时调用的办法 querySearch(queryString, cb) { // queryString是用户输出的想要查问的内容,cb是回调函数(能够发申请获取数据) console.log("如何触发", queryString, cb); if (queryString == "") { cb([{ value: "历史记录一" }, { value: "历史记录二" }]); // 当然这里的历史记录是后端返给咱们的,应该为接口返回的数据 } else { let apiResult = [ { value: "老王", }, { value: "王老吉", }, ]; // 这里咱们模仿从后端的接口异步获取的数据 setTimeout(() => { // cb([]) cb函数如果返回一个空数组的话,那个含糊搜寻输出倡议的下拉选项因为length为0就会隐没了 cb(apiResult); }, 500); } }, // 选中输入框举荐的值的时候触发 handleSelect(item) { // 参数 console.log("拿到数据", item); }, // 点击clearable清空小图标按钮当前,持续从新在输入框中输出数据,querySearch会触发,然而cb函数不会触发 // 这样的话就会呈现发申请了,也获取数据了,然而input框的输出倡议下拉框不出现在页面上的问题,所以解决办法就是 // 只有用户点击了 blurForBug(){ document.activeElement.blur() } },};</script><style lang="less" scoped>#box { width: 100%; height: 600px; box-sizing: border-box; padding: 50px;}</style>常见问题点击 clearable革除按钮输出倡议生效咱们会发现,如果给el-autocomplete组件标签加上clearable属性当前,那么,当咱们输出内容当前,再点击clearable清空按钮清空输入框中输出的数据当前,当咱们再从新输出文字的时候,申请会触发,后端返给咱们的数据也获取到了,然而后端返回给咱们的数据却没有渲染到页面上。就好像输出没反馈了。解决方案比拟间接的就是,当用户点击了clearable清空按钮当前,就让以后获取焦点的输入框失去焦点,回到最后状态,所有从新开始 ...

August 3, 2021 · 1 min · jiezi

关于vue.js:开源了一个uniapp组件库-这里有你想要的

介绍cc-ui是uni-app生态组件库, 主旨是所有为了简略。 因为作者儿子名字叫岑岑, 所以为组件库名字取名为cc, 算是送给儿子的礼物。 本组件库应用与uni-app开发, 目前适配了全副h5和微信小程序端, 大部分的app端, 后续会陆续适配所有端。在保护此组件库的同时, 作者也会陆续推出vue3版本和react版本, 敬请期待。 在线文档cc-ui在线文档 在线预览你能够通过手机浏览器拜访: cc-ui, 如是用电脑浏览器拜访, 请将浏览器设置为手机模式。微信小程序请扫码预览或者间接在小程序市场搜寻ccccccui组件库 <img src='https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e574d4477d9b4f3aaecc98b47ca4ed20~tplv-k3u1fbpfcp-zoom-1.image' width='300' height='300'>初衷原本并没有想做成组件库的,一开始是作者为了写vue3 + ts的组件, 而后模拟vant组件库写了很多组件, 写着写着不经意写了20多个了,前面转念一想, 原本当初工作中用uni-app用的比拟多,何不做成一个组件库,毕竟当初uni-app组件毕竟少,而后一发不可收拾,间接写了60多个组件。 借鉴该组件库的api和款式次要借鉴了uview和vant, 但在编写组件的过程中, 发现这两个组件库的个别api设计的不是很合乎我的预期,我的预期是每个组件要有高度的扩展性和自定义性, 于是在编写的过程当中从新设计了很多api, 所以可能大家第一次用的时候可能不太习惯, 但为了更好的扩大, 我也只能这样。在此, 特别感谢uview和vant这两个组件库的作者, 这两个组件库真的很优良, 我也只能缓缓追赶他们, 当然只借鉴了款式, 但组件代码还是本人辛辛苦苦设计编写的。 劣势cc-ui次要集成了uview和vant的大部分组件, 包含vant独有的业务组件, 因为之前看到很多同学吐槽, 用惯了vant, 发现其余组件库没有vant的一些组件, 我就在想, 何不把vant的组件搬过去呢, 在此再次申明, 只借鉴了款式和个别api, 因为vant是用jsx编写的, 所以对我的代码没有意义。所以咱们的劣势就是这里有你想要的组件。 收货vue的常识倒没多少提高, 只能说更相熟了, 倒是css提高一大截, 特地是动画成果, 还学会了应用vuepress部署文档。 布局作者接下来的大部分工夫会投入到组件库的保护和更新下面, 并且会陆续推出vue3的版本(曾经编写了一半的组件)和react版本, 我还在思考是编写纯react的还是taro的, 心愿各位同学给我一点倡议。 心愿因为所有的组件和文档都是我一个人编写的, 作者一个人精力切实无限, 而且又要带孩子, 常常爆肝到凌晨两三点, 所以我心愿有更多的同学可能退出进来, 欢送大家参加开源我的项目的为何和更新, 更加欢送大家pr。 cc-ui交换群: 868811435请备注: cc-ui 最初我只是一个一般的码农, 写组件库也只是本人的趣味和情怀, 心愿大家给与更多的宽容和了解, 写的代码必定问题还很多, 心愿和大家一起提高, 共同努力, 欢送大家pr和star。 ...

August 3, 2021 · 1 min · jiezi

关于vue.js:vue按需导入antdesignofvue

1.开发环境 vuecli42.电脑系统 windows10专业版3.在应用ant-design-vue的时候,咱们开发的时候,不肯定会应用到所有的组件,为了缩小我的项目的体积,咱们要按需导入,上面我来分享一下办法。4.废话不多说,间接上操作: npm i ant-design-vue -D5.在babel.config.js中增加如下代码: plugins: [ ['import', { libraryName: 'ant-design-vue', libraryDirectory: 'es', style: 'css' }] // `style: true` 会加载 less 文件 ]6.如果报错 // 解决办法:npm i babel-plugin-import -D7.在main.js中增加如下代码: // 导入antdesignvueimport { Button } from 'ant-design-vue'Vue.use(Button)8.本期的分享到了这里就完结啦,心愿对你有所帮忙,让咱们一起致力走向巅峰。

August 2, 2021 · 1 min · jiezi

关于vue.js:Vue封装Echarts图表

筹备工作在开始之前,咱们先依照失常的组件注册流程,在我的项目 components 目录中新建一个名为 radar-chart 的组件,而后在一个 Demo 页面引入该组件应用。 新建的 radar-chart 组件内容: // radar-chart.vue (子组件)<template> <div style="width: 100%; height: 100%;"></div></template><script>export default { name: 'radar-chart'};</script><style scoped></style>Demo 页面代码: // demo.vue (父组件)<template> <div style="border: 1px solid black; width: 400px; height: 300px; margin: 5px;"> <radar-chart></radar-chart> </div></template><script>import radarChart from '@/components/proj-components/echarts/radar-chart';export default { name: 'radar-chart-demo', components: { radarChart, },};</script><style scoped></style>Demo 页面效果图一: 初始化图表 筹备工作实现之后,咱们要做的是引入 ECharts,并在组件中初始化一个 ECharts 的实例,这里能够先照搬官网的实例和数据。 (1)在 radar-chart.vue 引入 ECharts : // radar-chart.vue (子组件)import echarts from 'echarts';(2)在 methods 中创立图表配置数据的办法,数据格式参考 Echarts 官网: ...

August 2, 2021 · 4 min · jiezi

关于vue.js:Vue源码解析二

二、响应式原理initState(vm)1.inState响应式入口initState在import { initState } from './state'同级目录下找到state.jsexport function initState (vm: Component) { vm._watchers = [] const opts = vm.$options // 解决props对象 为每一个props对象下面设置响应式,并将其代理到vm的实例上 if (opts.props) initProps(vm, opts.props) 解决methods 校验每个属性的值是否为函数 和props属性比对进行判重解决,并将其代理到vm的实例上 if (opts.methods) initMethods(vm, opts.methods) 1.判重解决,data对象上的属性不能和props、methods对象上的属性雷同 2.代理data到vm实例上的 3.为data对象上的数据设置响应式 if (opts.data) { initData(vm) } else { observe(vm._data = {}, true /* asRootData */) } 解决conputed 1.为computed【key】 创立 watcher 实例 默认是懒执行 也就是有缓存 2.代理computed【key】,到vm实例 3.判重,computed中的key不能和data,props中的属性反复 if (opts.computed) initComputed(vm, opts.computed) 解决watch 1.解决watch对象 2.为每一watch.key 创立watcher实例,key和watcher 实例可能是一对多的关系 3.如果设置了 immediate,则立刻执行 回调函数 if (opts.watch && opts.watch !== nativeWatch) { initWatch(vm, opts.watch) } computed和watch 在实质上是没有区别的,都是通过 watcher 去实现的响应式 1.watch 实用于当数据变动时执行异步函数或者开销比拟大的操作应用 须要长时间期待操作能够放在watch 2. computed 其中能够应用异步函数,computed更适宜做一些同步计算。 }2.initProps办法次要解决父组件传入props/src/core/instance/state.js为props对象的每一个属性设置响应式,并代理到vm上function initProps (vm: Component, propsOptions: Object) { // 写法一 props: ['name'] // 写法二 props: { name: String, // [String, Number] } // 写法三 props: { name:{ type: String } } propsData:父组件传入的实在props数据。 const propsData = vm.$options.propsData || {} props:指向vm._props的指针,所有设置到props变量中的属性都会保留到vm._props中。 const props = vm._props = {} // cache prop keys so that future props updates can iterate using Array // instead of dynamic object key enumeration. 缓存props 的每个key,做性能优化 const keys = vm.$options._propKeys = [] isRoot:以后组件是否为根组件 const isRoot = !vm.$parent // root instance props should be converted if (!isRoot) { toggleObserving(false) } // 遍历props 对象 for (const key in propsOptions) { // key 是props的key keys.push(key) // 收集所有的key,存到空数组外面 const value = validateProp(key, propsOptions, propsData, vm) /* istanbul ignore else */ if (process.env.NODE_ENV !== 'production') { const hyphenatedKey = hyphenate(key) if (isReservedAttribute(hyphenatedKey) || config.isReservedAttr(hyphenatedKey)) { warn( `"${hyphenatedKey}" is a reserved attribute and cannot be used as component prop.`, vm ) } // 为props的每一个key是设置数据响应式 defineReactive(props, key, value, () => { if (!isRoot && !isUpdatingChildComponent) { warn( `Avoid mutating a prop directly since the value will be ` + `overwritten whenever the parent component re-renders. ` + `Instead, use a data or computed property based on the prop's ` + `value. Prop being mutated: "${key}"`, vm ) } }) } else { // 对props数据做响应式解决 defineReactive(props, key, value) } // static props are already proxied on the component's prototype // during Vue.extend(). We only need to proxy props defined at // instantiation here. // 做代理,将props上的key代理到this下面 if (!(key in vm)) { proxy(vm, `_props`, key) } } toggleObserving(true)}3.proxy 代理办法设置代理,将key代理到target上/src/core/instance/state.jsexport function proxy (target: Object, sourceKey: string, key: string) { 定义设置属性相干的设定 sharedPropertyDefinition.get = function proxyGetter () { return this[sourceKey][key] } sharedPropertyDefinition.set = function proxySetter (val) { this[sourceKey][key] = val } 次要应用defineproperty 对每一个key进行代理设置 Object.defineProperty(target, key, sharedPropertyDefinition)}4.initMethods初始化代理办法methods代理到vm实例function initMethods (vm: Component, methods: Object) { 获取 props 配置项 const props = vm.$options.props 遍历 methods 对象 for (const key in methods) { if (process.env.NODE_ENV !== 'production') { if (typeof methods[key] !== 'function') { 断定methods【key】中必须是一个函数 在非生产环境下判断如果methods中某个办法只有key而没有value, 即只有办法名没有办法体时,抛出异样:提醒用户办法未定义。 warn( `Method "${key}" has type "${typeof methods[key]}" in the component definition. ` + `Did you reference the function correctly?`, vm ) } 断定 methods 的 key 和 props 不能反复 判断如果methods中某个办法名与props中某个属性名反复了,就抛出异样:提醒用户办法名反复了。 if (props && hasOwn(props, key)) { warn( `Method "${key}" has already been defined as a prop.`, vm ) } 判断如果methods中某个办法名如果在实例vm中曾经存在并且办法名是以_或$结尾的, 就抛出异样:提醒用户办法名命名不标准。 if ((key in vm) && isReserved(key)) { warn( `Method "${key}" conflicts with an existing Vue instance method. ` + `Avoid defining component methods that start with _ or $.` ) } } vm[key] = typeof methods[key] !== 'function' ? noop : bind(methods[key], vm) }}5.initDatasrc/core/instance/state.js初始化data1.判重解决,data对象上属性和props、methods对象上的属性雷同2.代理 data 对象上的属性到 vm 实例3.为data对象上的数据设置响应式function initData (vm: Component) { let data = vm.$options.data 获取到用户传入的data选项,赋给变量data data = vm._data = typeof data === 'function' ? getData(data, vm) : data || {} 将变量data作为指针指向vm。data,判断data是不是一个函数 如果是,执行getData函数获取其返回值 如果不是,就将其自身保留到vmdata中 就是传入data选项是不是一个函数,他就应该是个函数 if (!isPlainObject(data)) { data = {} process.env.NODE_ENV !== 'production' && warn( 'data functions should return an object:\n' + 'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function', vm ) } // proxy data on instance const keys = Object.keys(data) const props = vm.$options.props const methods = vm.$options.methods 做判重解决,data对象上的属性不能和props、methods对象上的属性雷同 代理data对象上的属性到vm实例 let i = keys.length while (i--) { const key = keys[i] if (process.env.NODE_ENV !== 'production') { if (methods && hasOwn(methods, key)) { 反复提醒 warn( `Method "${key}" has already been defined as a data property.`, vm ) } } if (props && hasOwn(props, key)) { process.env.NODE_ENV !== 'production' && warn( `The data property "${key}" is already declared as a prop. ` + `Use prop default value instead.`, vm ) } else if (!isReserved(key)) { proxy(vm, `_data`, key) } } // observe data // 为 data 对象上的数据设置响应式 observe(data, true /* asRootData */)}6.initComputed初始化computed为computed【key】创立wathcer,默认是懒执行代理到vm实例上计算属性的后果会被缓存,除非依赖的响应式属性变动才会从新计算。function initComputed (vm: Component, computed: Object) { // $flow-disable-line 定义了一个watchers,赋值给空对象,同时将其作为指针指向vm._computedWatchers const watchers = vm._computedWatchers = Object.create(null) // computed properties are just getters during SSR const isSSR = isServerRendering() 遍历computed for (const key in computed) { const userDef = computed[key] 判断userDef是不是一个函数 是函数 默认赋值给getter的取值器 不是函数 就是个对象,取对象的get属性作为取值器赋值给变量getter const getter = typeof userDef === 'function' ? userDef : userDef.get 判断环境 if (process.env.NODE_ENV !== 'production' && getter == null) { 如果取值器getter没有取到值,则正告 提醒用户计算属性必须有取值器。 warn( `Getter is missing for computed property "${key}".`, vm ) } 判断是不是服务器渲染 if (!isSSR) { 创立一个watcher实例 创立的实例作为值存入watchers对象中 // create internal watcher for the computed property. watchers[key] = new Watcher( vm, getter || noop, noop, computedWatcherOptions ) } // component-defined computed properties are already defined on the // component prototype. We only need to define computed properties defined // at instantiation here. 判断以后的值是否存在vm的实例上 放弃key的唯一性 if (!(key in vm)) { 不存在 调用函数 defineComputed(vm, key, userDef) } else if (process.env.NODE_ENV !== 'production') { 则在非生产环境下抛出正告 if (key in vm.$data) { warn(`The computed property "${key}" is already defined in data.`, vm) } else if (vm.$options.props && key in vm.$options.props) { warn(`The computed property "${key}" is already defined as a prop.`, vm) } else if (vm.$options.methods && key in vm.$options.methods) { warn(`The computed property "${key}" is already defined as a method.`, vm) } } }}7.defineComputedcomputed中的key如果不存在vm的整个实例中(也就是这个key是惟一的)执行defineComputed 办法属性描述符const sharedPropertyDefinition = { enumerable: true, configurable: true, get: noop, set: noop}该办法承受三个参数 target、key和userDef为target上定义一个属性key,并且属性key的getter和setter依据userDef的值来设置export function defineComputed ( target: any, key: string, userDef: Object | Function) { 标识计算属性是否该有缓存 判断是否是服务器渲染 true 非服务器渲染 false 服务器渲染 const shouldCache = !isServerRendering() 判断userDef是否函数,就是判断getter的取值 if (typeof userDef === 'function') { 判断是否是服务器渲染 非服务端渲染环境下并没有间接应用userDef作为getter,而是调用createComputedGetter函数 userDef只是一个一般的getter,它并没有缓存性能,所以咱们须要额定创立一个具备缓存性能的getter 服务端渲染环境不须要缓存 然而服务器渲染没有setter,所以将sharedPropertyDefinition.set设置为noop。 设置getter和setter sharedPropertyDefinition.get = shouldCache ? createComputedGetter(key) : createGetterInvoker(userDef) sharedPropertyDefinition.set = noop } else { sharedPropertyDefinition.get = userDef.get ? shouldCache && userDef.cache !== false ? createComputedGetter(key) : createGetterInvoker(userDef.get) : noop sharedPropertyDefinition.set = userDef.set || noop } if (process.env.NODE_ENV !== 'production' && sharedPropertyDefinition.set === noop) { sharedPropertyDefinition.set = function () { warn( `Computed property "${key}" was assigned to but it has no setter.`, this ) } } 调用Object.defineProperty办法将属性key绑定到target上 次要描述性就是sharedPropertyDefinition Object.defineProperty(target, key, sharedPropertyDefinition)}createComputedGetter()function createComputedGetter (key) { 返回一个computedGetter return function computedGetter () { 存储在以后实例上key所对应watcher实例 const watcher = this._computedWatchers && this._computedWatchers[key] // 执行watcher.evalute 办法 // 执行computed.key的办法,失去函数的执行后果,赋值给watcher.value // 将watcher.dirty 赋值为false 如果watcher存在,判断dirty是否为true 这个watcher只是会在数据变动后,才会变为true if (watcher) { if (watcher.dirty) { watcher.evaluate() } if (Dep.target) { watcher.depend() } return watcher.value } }}在实例化Watcher类的时候,第四个参数传入了一个对象computedWatcherOptions = { computed: true },该对象中的computed属性标记着这个watcher实例是计算属性的watcher实例,即Watcher类中的this.computed属性,同时类中还定义了this.dirty属性用于标记计算属性的返回值是否有变动,计算属性的缓存就是通过这个属性来判断的,每当计算属性依赖的数据发生变化时,会将this.dirty属性设置为true,这样下一次读取计算属性时,会从新计算结果返回,否则间接返回之前的计算结果。 ...

August 2, 2021 · 7 min · jiezi

关于vue.js:axios请求报错timeout-of-5000ms-exceeded

1.开发环境 vue2.电脑系统 windows10专业版3.在开发的过程中,咱们须要想后端发送数据申请,咱们个别会须要响应拦截器,咱们在交互的过程中,可能会遇到申请胜利,响应失败的状况,上面我来分享一下我的教训。4.废话不多说,间接看报错信息:![上传中...]() //可能有时候,后端是承受到前端传递的参数,后端没有报错5.分享报错起因: // 依据报错信息咱们晓得,咱们设定的响应工夫是10秒,意思是如果10秒中后端没有返回数据就会报错,个别状况下10秒中的确没有问题,然而在本地开发/测试的时候,的确有点少6.解决办法: //批改响应工夫为100秒,当初再次发送申请,数据胜利传递到后端,也没有报错7.本期的分享到了这里就完结啦,心愿对你有所帮忙,让咱们一起致力走向巅峰。

August 2, 2021 · 1 min · jiezi

关于vue.js:vue-history模式build页面显示空白处理

vue history模式build页面显示空白解决,要解决以下几个中央:1.build文件夹下prod文件output中退出:publicPath:'./'2.config文件夹下index.js中assetsPublicPath: '/',斜杠后面没有'.'。这样build下history模式失常显示了(后端要增加:显示目录下index.html的代码)

August 2, 2021 · 1 min · jiezi

关于vue.js:36-vue实战

一、应用VueCli创立我的项目vue create edu-boss-fedimage-20200926080833055image-20200926082611688 cd edu-boss-fedyarn serve二、退出Git版本治理创立一个GitHub空仓库,将本地我的项目同步到GitHub上 git initgit add .git commit -m"vue2+ts我的项目初始化"git remote add origin git@github.com:2604150210/edu-boss-fed.gitgit branch -M mastergit push -u origin master三、初始目录构造阐明 main.ts 入口文件App.vue 我的项目根组件shims-tsx.d.ts 和 shims-vue.d.ts TypeScript配置文件view/Home.vue 首页组件view/About.vue about页面组件store/index.ts 容器模块router/index.ts 路由模块,配置了路由表components文件夹,放公共组件.browserslistrc 浏览器兼容配置.editorconfig 编辑器配置.eslintrc.js ESLint的配置.gitignore Git疏忽文件babel.config.js Babel配置文件package.json 依赖清单package-lock.json 第三方包具体版本号tsconfig.json TS相干配置文件四、调整初始目录构造 删除默认示例文件App.vue 文件删除款式内容,删除路由链接,然而不能删除vue-router组件router/index.ts 清空路由表数组删除views文件夹里的Home.vue和About.vue,删除components文件里的HelloWorld.vue,删除assets里的logo.png新增一些文件或目录在src外面创立文件夹utils(放工具函数)、styles(放全局款式)、services(放申请接口)五、TS相干配置TS 相干依赖vue-class-component 提供应用 class 语法写Vue组件vue-property-decorator 在 Class 语法根底之上提供了一些辅助装璜器@typescript-eslint/eslint-plugin 应用 ESLint 校验TS代码@typescript-eslint/parser 将 TS 转为 AST 供 ESLint 校验应用@vue/cli-plugin-typescript 应用 TS + ts-loader-fork-ts-checker-webpack-plugin 进行更快的类型查看@vue/eslint-config-typescript 兼容 ESLint 的 TS 校验规定typescript TS 编译器,提供类型校验和转换 JavaScript 性能TS 相干配置文件ts.config.js{ "compilerOptions": { "target": "esnext", "module": "esnext", "strict": true, "jsx": "preserve", "importHelpers": true, "moduleResolution": "node", "experimentalDecorators": true, "skipLibCheck": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "sourceMap": true, "baseUrl": ".", "types": [ "webpack-env" ], "paths": { "@/*": [ "src/*" ] }, "lib": [ "esnext", "dom", "dom.iterable", "scripthost" ] }, "include": [ "src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "tests/**/*.ts", "tests/**/*.tsx" ], "exclude": [ "node_modules" ]}Shims-vue.d.tsts辨认不了.vue结尾的文件,所以申明它的类型为Vue构造函数,在这个文件中做了适配。declare module '*.vue' { import Vue from 'vue' export default Vue} ...

August 1, 2021 · 13 min · jiezi

关于vue.js:vueelement中table树形结构懒加载

1.开发环境 vue+element2.电脑系统 windows10专业版3.在开发的过程中,咱们会遇到树形构造的表格,因为数据量十分的多,所以咱们须要点击父元素把对应的id传给后端,那到子元素的数据,造成树形,上面我来分享一下如何实现。4.废话不多说,间接上效果图:5.第一次申请后端返回的数据结构: // isParent :是否有子节点6.需要: // 点击父节点,把父节点的pid传给后端,后端返回子节点的数据7.实现办法,应用element的table的懒加载解决,代码如下: <el-table ref="multipleTable" :data="tableData" tooltip-effect="dark" style="width: 100%" @selection-change="handleSelectionChange" border :tree-props="{ children: 'children', hasChildren: 'isParent' }" //要害代码 row-key="id" lazy :load="load" //要害代码 > <el-table-column type="selection" width="55" fixed align="center"></el-table-column> <el-table-column prop="name" :label="$t('table.level')" align="center"></el-table-column> <el-table-column prop="isLeaf" :label="$t('table.upperlevel')" align="center" > <template slot-scope="scope"> <p v-if="!scope.row.isLeaf">111</p> </template> </el-table-column> <el-table-column prop="Upperlevelpro" :label="$t('table.Upperlevelpro')" align="center" ></el-table-column> <el-table-column prop="show" :label="$t('table.Whetherenable')" align="center" > <template slot-scope="scope"> <el-switch v-model="scope.row.show" active-color="#13ce66" inactive-color="#ff4949" active-value="0" inactive-value="1" ></el-switch> <!-- <el-button size="mini" @click="handleEdit(scope)">Edit</el-button> --> </template> </el-table-column> <el-table-column prop="Sort" :label="$t('table.Sort')" align="center"></el-table-column> <el-table-column prop="picture" :label="$t('table.picture')" align="center" > <template slot-scope="scope"> <img :src="scope.row.picture" alt="" class="picture" /> <!-- <el-button size="mini" @click="handleEdit(scope)">Edit</el-button> --> </template> </el-table-column> <el-table-column prop="name" :label="$t('table.operate')" width="220" align="center" > <template slot-scope="scope"> <el-button size="mini" @click="tableadd(scope)">{{ $t("tablebtn.add") }}</el-button> <el-button size="mini" @click="handleEdit(scope)">{{ $t("tablebtn.edit") }}</el-button> <el-button size="mini" type="danger" @click="handleDelete(scope)">{{ $t("tablebtn.delete") }}</el-button> </template> </el-table-column></el-table>load(row, treeNode, resolve) { console.log(row); treetable({ pid: row.id, storeId: this.account.storeId, }).then((res) => { console.log("我是树形构造的表格接口"); console.log(res); resolve(res.result); //应用懒加载的resolve办法 });},8.本期的分享到了这里就完结啦,心愿对你有所帮忙,让咱们一起致力走向巅峰。 ...

July 31, 2021 · 1 min · jiezi

关于vue.js:vueawesomeswiper使用

vue-awesome-swiper我喜爱的一款轮播插件,他有多个抉择!而且反对手持滑动所以我用到了明天。 装置自己阐明一点:为什么不必4.1.1 答:vue-awesome-swiper v4.1.1版 autoplay、effect等有效问题至今未解决 cnpm i vue-awesome-swiper@3.1.3 -S 引入全局引入 import VueAwesomeSwiper from 'vue-awesome-swiper' import 'swiper/dist/css/swiper.css' Vue.use(VueAwesomeSwiper) 独自引入 import Vue from 'vue'import { swiper, swiperSlide } from 'vue-awesome-swiper'import "swiper/dist/css/swiper.css"//或者require('swiper/dist/css/swiper.css')测试 <template> <swiper class="swiper"> <swiper-slide>Slide 1</swiper-slide> <swiper-slide>Slide 2</swiper-slide> <swiper-slide>Slide 3</swiper-slide> <swiper-slide>Slide 4</swiper-slide> <swiper-slide>Slide 5</swiper-slide> <swiper-slide>Slide 6</swiper-slide> <swiper-slide>Slide 7</swiper-slide> <swiper-slide>Slide 8</swiper-slide> <swiper-slide>Slide 9</swiper-slide> <swiper-slide>Slide 10</swiper-slide> </swiper></template>A组我最喜爱的轮播这款,在我的MXLOGO保留至今!然而很快辞别了因为我要更新MXLOGO 8. <swiper :options="swiperOption"> <swiper-slide> <a href="XXXXXX" target="_blank"> <img src="./assets/1.jpg"> </a> </swiper-slide> <swiper-slide> <a href="XXXXXX" target="_blank"> <img src="./assets/1.jpg"> </a> </swiper-slide> <swiper-slide> <a href="XXXXXX" target="_blank"> <img src="./assets/1.jpg"> </a> </swiper-slide> </swiper>

July 30, 2021 · 1 min · jiezi

关于vue.js:vuecli4项目打包之后文件大

1.开发环境 vuecli42.电脑系统 windows10专业版3.在开发的过程中,咱们最初都会进行打包,然而会发现打包之后的文件夹有点大。4.失常打包之后文件的大小 其实是因为因为打包时生成了.map文件,因为我的项目打包后,代码都是通过压缩加密的,如果运行时报错,输入的错误信息无奈精确得悉是哪里的代码报错。而.map文件就能够像未加密的代码一样,精确的输入是哪一行那一列有错。然而去掉 .map文件能够缩小打包之后文件的大小,能够晋升 build速度,也能够爱护源码。5.打包的时候去掉.map文件,在vue.config.js增加如下代码: productionSourceMap: false, 去掉.map文件,打包进去的文件显著小了很多6.本期的分享到了这里就完结啦,心愿对你有所帮忙,让咱们一起致力走向巅峰。

July 30, 2021 · 1 min · jiezi

关于vue.js:midway-跨域

midway 跨域最近筹备上手midway.js来开发点货色。开发的API,在前端(vue+axios)调用时总是提醒跨域,但ajax又能调用。节约了很多工夫,在此记录一下。 midway 配置:之前搜寻过跨域问题解决办法:csrf 配置//在”src/config/config.default.ts”,增加代码如下export default (appInfo: EggAppInfo) => { const config = <DefaultConfig> {}; …… // 跨域 @midwayjs/web 默认增加了此项配置的 config.security = { csrf: { enable: false, }, domainWhiteList: ['http://127.0.0.1:9384'], // 容许跨域的域名 }; ……}<font color=red>提醒:很多文档说的解决跨域,这样一设置就OK了,实际通知我关这个配置还是不行的!!</font> security 配置项是eggjs中对平安的一项配置,详见: 平安威逼 CSRF 的防备 CORS 配置装置 egg-cors $ npm i egg-cors --save 配置插件启用 // src/config/plugin.tsexports.cors = { enable: true, package: 'egg-cors',}配置 cors 插件 // src/config/config.default.tsexport const cors = { // {string|Function} origin: '*', // {string|Array} allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH'};如果这个中央设置了origin: '*',那么在security下设置的domainWhiteList无用了 ...

July 30, 2021 · 1 min · jiezi

关于vue.js:vue使用tinymce和tinymcevue实现富文本

1.开发环境 vue2.电脑系统 windows10专业版3.在开发的过程中,咱们常常会应用到富文本性能,上面我来分享一下。4.富文本比拟: UEditor:百度前端的开源我的项目,功能强大,基于 jQuery,但曾经没有再保护,而且限定了后端代码,批改起来比拟吃力bootstrap-wysiwyg:微型,易用,小而美,只是 Bootstrap + jQuery...kindEditor:功能强大,代码简洁,须要配置后盾,而且好久没见更新了wangEditor:轻量、简洁、易用,然而降级到 3.x 之后,不便于定制化开发。不过作者很怠惰,狭义上和我是一家人,打个callquill:自身性能不多,不过能够自行扩大,api 也很好懂,如果能看懂英文的话...summernote:没深入研究,UI挺丑陋,也是一款小而美的编辑器,可是我须要大的在有这么参考的状况下,我最终还是抉择了 tinymce 1. GitHub 上星星很多,性能也齐全;2. 惟一一个从 word 粘贴过去还能放弃绝大部分格局的编辑器;3. 不须要找后端人员扫码改接口,前后端拆散;5.我应用的版本6.Vue引入TinyMCE富文本组件时遇到的问题 版本兼容问题因为 @tinymce/tinymce-vue@4.0.0 仅针对Vue@3.x版本,须要降级。7.装置 npm install @tinymce/tinymce-vue@3 -Dnpm install tinymce@5.7.0 -D8.去官网下载语言包: (https://www.tiny.cloud/get-tiny/language-packages/)https://www.tiny.cloud/get-ti...[语言包]9.下载语言包之后,复制到我的项目中,我放在了assets上面:10.在对应的.vue文件中应用 //导入// 导入富文本import tinymce from "tinymce/tinymce";import Editor from "@tinymce/tinymce-vue";import "tinymce/skins/ui/oxide/skin.min.css"; //富文本款式import "tinymce/icons/default"; //富文本款式// 配置富文本import "tinymce/themes/silver/theme.min.js"; //引入富文本的次要脚本//注册components: { Editor },// template<editor id="tinymce" v-model="tinymceHtml" :init="einit"></editor><div v-html="tinymceHtml"></div>// return tinymceHtml: "请输出内容", einit: { skin_url: require("@/assets/skins/ui/oxide/skin.min.css"), language_url: require("@/assets/langs/zh_CN.js"), language: "zh_CN", height: 300, },// mountedtinymce.init({});11.举例无成果配置: <editor id="tinymce" v-model="tinymceHtml" :init="einit"></editor><div v-html="tinymceHtml"></div>tinymceHtml: "请输出内容",einit: {},tinymce.init({ skin_url: require("@/assets/skins/ui/oxide/skin.min.css"), language_url: require("@/assets/langs/zh_CN.js"), language: "zh_CN", height: 300,});//这样配置是没有成果的,请小伙伴们留神了12.胜利配置成果如下:13.本期的分享到了这里就完结啦,心愿对你有所帮忙,让咱们一起致力走向巅峰。 ...

July 30, 2021 · 1 min · jiezi

关于vue.js:在-Vue-框架中集成纯前端报表设计器

创立 Vue利用创立 Vue 利用的最简略的办法是应用Vue CLI vue create -p default arjs-vue-designer-app 装置 ActiveReportsJS 相干文件Web 报表设计器性能是放在@grapecity/activereports-vue NPM 包中,@grapecity/activereports npm 包中寄存外围性能。在应用 ActiveReportsJS 时,能够执行以下命令来装置在利用根目录下: npm install @grapecity/activereports-vue @grapecity/activereports或者应用yarn命令 yarn add @grapecity/activereports-vue @grapecity/activereports如果您应用的是 Vue 2.0, 须要装置@vue/composition-api 包:npm install @vue/composition-api或yarn add @vue/composition-api 将 ActiveReportsJS报表增加到应用程序ActiveReportsJS 应用 JSON格局和rdlx-json扩大用于报表模板文件。在应用程序的public文件夹下,创立名为report.rdlx-json的新文件,并在该文件中插入以下JSON内容。 { "Name": "Report", "Body": { "ReportItems": [ { "Type": "textbox", "Name": "TextBox1", "Value": "Hello, ActiveReportsJS Designer", "Style": { "FontSize": "18pt" }, "Width": "8.5in", "Height": "0.5in" } ] }}增加设计器宿主元素关上 src\App.vue 文件,增加代码如下,单文件组件 调用 Vue 报表设计器来加载上一步骤创立的报表模板 ...

July 30, 2021 · 1 min · jiezi

关于vue.js:VUE基础组件的自动化全局注册

可能你的许多组件只是包裹了一个输入框或按钮之类的元素,是绝对通用的。咱们有时候会把它们称为根底组件,它们会在各个组件中被频繁的用到。所以会导致很多组件里都会有一个蕴含根底组件的长列表: import BaseButton from './BaseButton.vue'import BaseIcon from './BaseIcon.vue'import BaseInput from './BaseInput.vue'export default { components: { BaseButton, BaseIcon, BaseInput }}而只是用于模板中的一小部分: <BaseInput v-model="searchText" @keydown.enter="search"/><BaseButton @click="search"> <BaseIcon name="search"/></BaseButton>如果你恰好应用了 webpack (或在外部应用了 webpack 的 Vue CLI 3+),那么就能够应用 require.context 只全局注册这些十分通用的根底组件。这里有一份能够让你在利用入口文件 (比方 src/main.js) 中全局导入根底组件的示例代码: import Vue from 'vue'import upperFirst from 'lodash/upperFirst'import camelCase from 'lodash/camelCase'const requireComponent = require.context( // 其组件目录的相对路径 './components', // 是否查问其子目录 false, // 匹配根底组件文件名的正则表达式 /Base[A-Z]\w+\.(vue|js)$/)requireComponent.keys().forEach(fileName => { // 获取组件配置 const componentConfig = requireComponent(fileName) // 获取组件的 PascalCase 命名 const componentName = upperFirst( camelCase( // 获取和目录深度无关的文件名 fileName .split('/') .pop() .replace(/\.\w+$/, '') ) ) // 全局注册组件 Vue.component( componentName, // 如果这个组件选项是通过 `export default` 导出的, // 那么就会优先应用 `.default`, // 否则回退到应用模块的根。 componentConfig.default || componentConfig )})记住全局注册的行为必须在根 Vue 实例 (通过 new Vue) 创立之前产生。 ...

July 30, 2021 · 1 min · jiezi

关于vue.js:关于VUE开发过程中的一些注意点及建议

不要在选项 property 或回调上应用箭头函数,比方:created: () => console.log(this.a) 或vm.$watch('a', newValue => this.myMethod())。因为箭头函数并没有 this,this 会作为变量始终向下级词法作用域查找,直至找到为止,常常导致 Uncaught TypeError: Cannot read property of undefined 或Uncaught TypeError: this.myMethod is not a function 之类的谬误。你的站点上动静渲染的任意 HTML 可能会十分危险,因为它很容易导致 XSS 攻打。请只对可信内容应用 HTML 插值,绝不要对用户提供的内容应用插值。模板表达式都被放在沙盒中,只能拜访全局变量的一个白名单,如 Math 和 Date 。你不应该在模板表达式中试图拜访用户定义的全局变量。在 DOM 中应用模板时 (间接在一个 HTML 文件里撰写模板),还须要防止应用大写字符来命名键名,因为浏览器会把 attribute 名全副强制转为小写:<!--在 DOM 中应用模板时这段代码会被转换为 `v-bind:[someattr]`。除非在实例中有一个名为“someattr”的 property,否则代码不会工作。--><a v-bind:[someAttr]="value"> ... </a>留神,v-show 不反对 <template> 元素,也不反对 v-else。v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。相比之下,v-show 就简略得多——不论初始条件是什么,元素总是会被渲染,并且只是简略地基于 CSS 进行切换。一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因而,如果须要十分频繁地切换,则应用 v-show 较好;如果在运行时条件很少扭转,则应用 v-if 较好。防止 v-if 和 v-for 用在一起 当它们处于同一节点,v-for 的优先级比 v-if 更高,这意味着 v-if 将别离反复运行于每个 v-for 循环中。当你只想为局部项渲染节点时,这种优先级的机制会非常有用,如下: ...

July 29, 2021 · 3 min · jiezi

关于vue.js:Vue组件间的传值五大场景你造吗

摘要:组件是 vue.js最弱小的性能之一,这五个组件间传值场景你理解吗?本文分享自华为云社区《你理解Vue组件间传值五大场景吗?》,作者:北极光之夜。 。 父组件向子组件传值:比方有一个 Father.vue 的父组件要传值给 Children.vue 的子组件,实现共需四步: 父组件 Father.vue 内容,留神外面的操作步骤: <template> <div> <h2>父组件区域</h2> <hr /> <!-- 第二步:在援用的子组件标签里定义 :num="num" , num就是要传递的变量--> <Children :num="num"></Children> </div></template><script>// 引入子组件import Children from "./Children.vue";export default { data() { return { // 第一步:咱们将要把变量 num 的值传给子组件Children num: 666, }; }, components: { Children, },};</script>子组件 Children.vue 内容,留神外面的操作步骤: <template> <div> <h2>子组件区域</h2> <!-- 第四步:在子组件显示父组件传过来的值 --> <i>父组件传递过了的值:{{ num }}</i> </div></template><script>export default { //第三步: 子组件能够通过定义的props就能够接管来自父组件的变量值 num props: ["num"], data() { return {}; },};</script>运行成果: ...

July 29, 2021 · 2 min · jiezi

关于vue.js:基于-vue3-webpack-5-sass-vw-适配方案axios-封装从0构建手机端模板脚手架

Webpack5正式公布也有很长长长一段时间了,上手了一段时候后发现真香。webpack5的新个性使得咱们在配置上比以往版本更加不便了,构建速度也有了质的飞跃。本文着重为大家解说从 0 到 1 搭建 vue3 + webpack 5开发环境的过程中遇到的疑难。 我的项目地址: webpack5-vue3 demo地址: https://zhouyupeng.github.io/webpack5-vue3/#/ 先看一下配置好的我的项目目录构造 ├─build│ ├─webpack.base.conf.js │ ├─webpack.dev.conf.js │ ├─webpack.prod.conf.js │ ├─webpack.rules.conf.js ├─node_modules├─public| |-index.html└─src| ├─api| ├─assets| ├─components| ├─filters| ├─plugins| ├─router| ├─store| ├─style| ├─utils| ├─views| |-App.vue| |-main.ts|-.env.dev|-.env.test|-.env.prod|-.gitigore|-babel.config.js|-package.json|-postcss.config.js接下来,咱们应用 Webpack5 从0搭建一个残缺的 Vue3 的开发环境! 环境(environment) webpack 5 运行于 Node.js v10.13.0+ 的版本。本文波及到依赖的版本号 ├── webpack 5.43├── webpack-cli 4.7.2├── node 14.17.0初始化目录第一步: 创立目录并且初始化 package.json mkdir webpack5-vue3 && cd webpack5-vue3yarn init -y第二步: 装置webpack三件套 yarn add webpack webpack-cli webpack-dev-server -D留神: ...

July 28, 2021 · 5 min · jiezi

关于vue.js:Activiti工作流引擎驱动业务实例代码整合

前言目前市场上有很多开源平台没有整合工作流,即便有,也是价格不菲的商业版,来看这篇文章的预计也理解了行情,必定不便宜。我这个疾速开发平台在零碎根底性能(用户治理,部门治理…)上整合了工作流,你能够间接用来开发ERP,OA,CRM等企业级利用,不必再放心如何再去花大量的工夫集成工作流进来。博主是集体开发者。钻研工作流有几年了,依稀记得第一次写工作流是用在江苏某省局的用车申请业务上,那时候年轻气盛,精力充沛可是能力无限,熬了几十个夜整进去了,即便进去了,也是代码很乱。前面也在好几个零碎参加了工作流的开发,目前是独自把这一套给抽取进去了,做成了可插拔的,能够十分不便的整合到你的程序中。上面咱们来摸索吧。</font> 一、我的项目模式springboot+vue+activiti集成了activiti在线编辑器,疾速开发平台,可插拔工作流服务。 二、我的项目介绍本我的项目领有用户治理,部门治理,代码生成,零碎监管,报表,大屏展现,业务审批等性能。性能太强大,只能粗矿的介绍,所见即所得,体验一下吧。 三、工作流1.流程模型绘制进入流程模型菜单,创立流程模型,这里波及到网关流转,须要设置流转条件,咱们这里是三十岁以上的走上面分支,三十岁以下的走下面的分支。点击分支线,设置流转条件即可。${age<=30}。保留后咱们在列表中点击公布即可。 2.流程配置公布后,就到了已公布模型列表,在启用之前,咱们须要先对进行节点设置和关联具体单据。 审批人员能够依据角色,间接指定人,部门,部门负责人,发起人部门负责人来进行配置,基本上满足所有的流转需要,并且能够设置表单变量。 设置流程表单,目前就做了一个销假的测试表单,并且能够对相应角色受权,做到自定义权限。设置完后启动即可。 3.流程提交填写销假表单 提交单据,优先级分为一般,重要,紧急。音讯告诉能够抉择站内告诉,短信,邮件。 提交之后能够撤回单据。查看流程流转进度状况。 也能够挂起,删除流程。 4.流程审批办理人审批列表,能够解决单据(驳回或者通过),也能够委托别人待办。审批通过。委托别人待代。 审批通过后进入已办列表。 年龄大于30岁,进入上面分支流转。 审批通过。 5.待办信息推送站内音讯推送。 总结下面只是展现了平台的审批流性能,还有其余很多性能没展现进去,本人也写了一些十分好用的组件,做到零碎麻利疾速开发,大大减少开发工夫和老本,目前正在对接挪动端审批。之前因为没有工夫去部署线上测试环境,思考近期部署,目前能够独自找我,近程演示,有须要源码的分割我。q:2500564056。 鸣谢:jeecgboot开源版http://jeecg.com/咖啡兔activiti实战https://kafeitu.me/

July 28, 2021 · 1 min · jiezi

关于vue.js:vue

B站 - Vue 学习笔记0 课程介绍邂逅Vue.jsVue根底语法组件化开发Vue CLI详解vue-routervuex详解网络封装我的项目实战1 邂逅Vue.jsVue (读音 /vju/,相似于 view) 是一套用于构建用户界面的渐进式框架。1.1 MVVM架构MVVM架构 MVC与MVP MVVM Vue.js的定位 Vue.js在MVVM架构中的定位 Vue.js的功能定位 Vue.js的核心思想与特点 Reactive Components for Modern Web Interfaces(数据驱动的组件,为古代的 Web 界面而生) 数据驱动组件化特点:侵入性低、激励模块化、轻量、高性能数据驱动的 Web 开发 Vue.js 装置 下载Vue.js,通过<script>标签引入CDN <!-- 开发环境版本,蕴含了有帮忙的命令行正告 --> <script class="lazy" referrerpolicy="no-referrer" data-src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!-- 生产环境版本,优化了尺寸和速度 --><script src="https://cdn.jsdelivr.net/npm/vue"></script>NPM装置vue-cli:配套路由等灵便的命令行框架传统视图驱动 Web 开发:通过原生js/jquery操作DOM元素 数据驱动的 Web 开发:将Vue实例中数据和办法等,通过Vue指令的形式绑定到html中 1.2 Vue初体验HelloVue.html <!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <title>TestVue</title> </head> <body> <div id="app">{{message}}</div> <script class="lazy" referrerpolicy="no-referrer" data-src="../js/vue.js"></script> <script> // 一、一般js写法(编程范式:命令式编程) //1. 创立div元素,设置id属性 //2. 定义一个变量叫message //3. 将message变量放在后面的div元素中显示 //4. 批改message数据 //5. 将message数据替换原数据 // 二、Vue写法(编程范式:申明式编程) // let变量、const常量 // new Vue()就是ViewModel const app = new Vue({ //el、data属于Vue的options el: '#app', //挂载治理的元素 data: { // 定义数据 message: 'zfcer' } }) // Vue能够间接在浏览器中批改message:app.message = 'hello' </script> </body></html>Vue列表展现 ...

July 28, 2021 · 27 min · jiezi

关于vue.js:vue过滤树形结构

1.开发环境 vue2.电脑系统 windows10专业版3.在开发的过程中,咱们常常会应用到树形数据,然而后端返回给咱们的数据不是树形构造,咱们须要把后端的数据转换为树形构造,上面我来分享一下如何实现。4.后端返回的数据结构:5.然而咱们应用树形组件的时候,用这样的数据是不行的,咱们须要把后端返回的数据进行过滤一下: function treelist(tree, arr = []) { if (!tree.length) return [] for (let item of tree) { // 循环数组,而后过滤数据 // 如果该条数据type不为0时,跳出本次循环 // if (item.type !== 0) continue // 如果满足条件时,用新node代替,而后把chilren清空 // console.log(item[name]); // 在原来的对象下面增加一个 label 属性 item.label = item.name; // let node = { ...item, children: [] } let node = { ...item, children: [] } // 而后增加到新数组中 arr.push(node) // 如果有子节点,调用递归函数,并把空数组传给下一个函数 // 利用援用数据类型的个性,实现浅拷贝 // 递归函数过滤时会扭转这个空数组数据,从而实现层级构造过滤 if (item.children && item.children.length) { filterTree(item.children, node.children) } } return arr}6.应用办法为: ...

July 28, 2021 · 1 min · jiezi

关于vue.js:使用-React-Hooks-时需要注意过时的闭包

作者:Shadeed译者:前端小智起源:dmitripavlutin有幻想,有干货,微信搜寻 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。 本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试残缺考点、材料以及我的系列文章。 Hooks 简化了 React 组件外部状态和副作用的治理。 此外,能够将反复的逻辑提取到自定义 Hooks 中,以在整个应用程序中重复使用。 Hooks 重大依赖于 JS 闭包。这就是为什么 Hooks 如此具备表现力和简略,然而闭包有时很辣手。 应用 Hooks 时可能遇到的一个问题就是过期的闭包,这可能很难解决。 让咱们从过期的装璜开始。 而后,看看到过期的闭包如何影响 React Hooks,以及如何解决该问题。 1.过期的闭包工厂函数 createIncrement(incBy) 返回一个increment和log函数的元组。 调用时,increment()函数将外部value减少incBy,而log()仅打印一条音讯,其中蕴含无关以后value的信息: function createIncrement(incBy) { let value = 0; function increment() { value += incBy; console.log(value); } const message = `Current value is ${value}`; function log() { console.log(message); } return [increment, log];}const [increment, log] = createIncrement(1);increment(); // 1increment(); // 2increment(); // 3// 不能正确工作!log(); // "Current value is 0"[increment, log] = createIncrement(1)返回一个函数元组:一个函数减少外部值,另一个函数记录以后值。 ...

July 28, 2021 · 2 min · jiezi

关于vue.js:Vue深入学习3数据响应式原理

1、数据响应式原理 1.1、MVVM是什么? 简略来说,就是数据变了,视图也会跟着变,首先你得定义一个带有{{ }}的模板Model,当数据中的值变动了,视图View就会跟着变动;视图模型View-model是模板Model和视图View之间的桥梁,Vue属于非侵入式,React和小程序就是侵入式(数据变动的时候须要调用提前写好的API) // Vue数据变动,非侵入式this.a ++// React、小程序数据变动,侵入式this.setState({ a: this.state.a + 1});1.2、数据响应式的中心思想?通过重写数据的get和set属性办法,让数据在被渲染时,把所有用到本人的订阅者,寄存在本人的订阅者列表中;当数据产生扭转时,该办法告诉所有订阅了本人的订阅者,达到从新渲染的目标。 是不是有点懵了?没关系,举个简略的栗子: 《西游记》中的妖怪(Watcher)时刻惦记(订阅)着唐僧(Data),想吃唐僧肉,孙悟空(Component)在听到(get收集依赖)唐僧被抓的音讯后,做出反馈(set触发依赖),筹备救出徒弟。于是来到了妖怪(Watcher)的老巢,跟它大战几个回合后,胜利救出唐僧(Data),达到从新踏上(渲染)西天取经(Vittual DOM Tree)的目标!2、尤大找到了一把”上帝的钥匙“ Object.defineProperty()办法:数据劫持、数据代理,MDN这样形容的:间接在一个对象上定义一个新属性,或者批改一个对象的现有属性,并返回此对象。 Object.defineProperty(obj(定义那个对象),'a(定义这个对象的什么属性)',{ //属性值定义为多少 value : 3})//-----------------------------------栗子-------------------------------------------var obj = {};Object.defineProperty(obj, 'a', { get(){ console.log('拜访obj的a属性!'); return 7; }, set(){ console.log('扭转obj的a属性', newValue); temp = newValue; }})console.log(obj.a); // 7obj.a = 9; //批改a的值console.log(obj.a); // 73、补救这把钥匙的有余 defineReactive函数:为了解决defineProperty()办法存在的问题,get中并不能返回set刚刚批改过的值,再次调用会显示批改前的值,怎么解决这个问题?在里面定义一个全局变量,用来周转变量值。 // 解决defineProperty存在到的问题defineProperty(data(数据对象),key(键名),val(值)){ }//-----------------------------------栗子-------------------------------------------var obj = {};var temp; //在里面定义一个全局变量,用来周转变量值。function defineProperty(data, key, val) { Object.defineProperty(data, key, { // 可枚举 enumerable: true, // 可被配置,比方被delete configurable: true, get(){ console.log('拜访obj的'+ key +'属性!'); return temp; }, set(){ console.log('扭转obj的'+ key +'属性!', newValue); if(val == newValue){ return; } temp = newValue; } });}defineReactive(obj, 'a',10) console.log(obj.a); // 拜访obj的a属性! 10obj.a = 69; //批改a的值obj.a ++;console.log(obj.a); // 批改obj的a属性!70// definReactive 实现 // 简化后的版本 function defineReactive( target, key, value, enumerable ) { // 折中解决后, this 就是 Vue 实例 let that = this; // 函数外部就是一个部分作用域, 这个 value 就只在函数内应用的变量 ( 闭包 ) if ( typeof value === 'object' && value != null && !Array.isArray( value ) ) { // 是非数组的援用类型 reactify( value ); // 递归 } Object.defineProperty( target, key, { configurable: true, enumerable: !!enumerable, get () { console.log( `读取 ${key} 属性` ); // 额定 return value; }, set ( newVal ) { console.log( `设置 ${key} 属性为: ${newVal}` ); // 额定 value = reactify( newVal ); } } ); }4、数组的响应式解决改写了7个属性,push(数组尾部推入)、pop(数组尾部移除)、shift(数组头部插入)、unshift(数组尾部移出)、splice(切割)、sort(就地排序)、reverse(排序地位颠倒); ...

July 27, 2021 · 2 min · jiezi

关于vue.js:vuecorevideoplayer播放器

视频官网:https://core-player.github.io... 装置第一步:装置cnpm i vue-core-video-player -S 第二步:main全局引入 import VueCoreVideoPlayer from 'vue-core-video-player'Vue.use(VueCoreVideoPlayer)第三步:HTML <vue-core-video-player src="门路"></vue-core-video-player>解决门路问题内部门路:非常简单!就是间接上! <vue-core-video-player src="http://link.mxlogo.com/vide003.mp4"> </vue-core-video-player>本地门路:不能间接./assets/1.mp4,有效的。须要应用require("...") <template> <div id="app"> <vue-core-video-player :src="a"></vue-core-video-player> </div></template><script> export default{ data(){ return{ a:require("./assets/1.mp4") } } }</script>

July 26, 2021 · 1 min · jiezi

关于vue.js:VUE30

Vue.js 3.0 Composition APIs 及 3.0 原理分析Vue.js 3.0 介绍一、Vue.js 源码组织形式1. 源码采纳TypeScript重写进步了代码的可维护性。大型项目的开发都举荐应用类型化的语言,在编码的过程中查看类型的问题。 2. 应用Monorepo治理我的项目构造应用一个项目管理多个包,把不同性能的代码放到不同的package中治理,每个功能模块都能够独自公布,独自测试,独自应用。 3. 不同构建版本Vue3中不再构建UMD模块化的形式,因为UMD会让代码有更多的冗余,它要反对多种模块化的形式。Vue3中将CJS、ESModule和自执行函数的形式别离打包到了不同的文件中。在packages/vue中有Vue3的不同构建版本。 cjs(两个版本都是完整版,蕴含编译器) vue.cjs.jsvue.cjs.prod.js(开发版,代码进行了压缩)global(这四个版本都能够在浏览器中间接通过scripts标签导入,导入之后会减少一个全局的Vue对象) vue.global.js(完整版,蕴含编译器和运行时)vue.global.prod.js(完整版,蕴含编译器和运行时,这是开发版本,代码进行了压缩)vue.runtime.global.jsvue.runtime.global.prod.jsbrowser(四个版本都蕴含esm,浏览器的原生模块化形式,能够间接通过<script type="module" />的形式来导入模块) vue.esm-browser.jsvue.esm-browser.prod.jsvue.runtime.esm-browser.jsvue.runtime.esm-browser.prod.jsbundler(这两个版本没有打包所有的代码,只会打包应用的代码,须要配合打包工具来应用,会让Vue体积更小) vue.esm-bundler.jsbue.runtime.esm-bundler.js二、Composition APIRFC (Request For Coments) Https://github.com/vuejs/rfcsComposition API RFC Https://composition-api.vuejs.org1. 设计动机Options API 蕴含一个形容组件选项(data、methods、props等)的对象Options API 开发简单组件,同一个性能逻辑的代码被拆分到不同选项Composition API Vue.js 3.0 新增的一组API一组基于函数的API能够更灵便的组织组件的逻辑三、性能晋升1. 响应式系统升级Vue3应用Proxy对象重写了响应式零碎。 Vue.js 2.x中响应式零碎的外围 defineProperty,初始化的时候递归遍历所有的属性,转化为getter、setterVue.js 3.0中应用Proxy对象重写响应式零碎 可监听动静新增的属性能够监听删除的属性能够监听数组的索引和length属性2. 编译优化重写了DOM进步渲染的性能。 Vue.js 2.x中通过标记动态根节点,优化diff的过程Vue.js 3.0 中标记和晋升所有的动态根节点,diff的时候只须要比照动静节点内容 Fragments(降级vetur插件)动态晋升Patch flag缓存事件处理函数3.源码体积的优化通过优化源码的体积和更好的TreeShaking的反对,缩小大打包的体积 Vue.js 3.0中移除了一些不罕用的API 例如:inline-template、filter等Tree-shaking 例如:Vue3中的没用到的模块不会被打包,然而外围模块会打包。Keep-Alive、transition等都是按需引入的。四、ViteVue的打包工具。Vite是法语中的"快"的意思 1. ES Module古代浏览器都反对ES Module(IE不反对)通过上面的形式加载模块<script type="module" src="..."></script>反对模块的script默认提早加载有了type="module"的模块是提早加载的,相似于script标签设置defer 在文档解析实现后,也就是DOM树生成之后,触发DOMContentLoaded事件前执行2. Vite as Vue-CLIVite 在开发模式下不须要打包能够间接运行Vue-CLI开发模式下必须对我的项目打包才能够运行Vite在生产环境下应用Rollup打包 基于ES Module的形式打包Vue-CLI应用Webpack打包3. Vite特点疾速冷启动按需编译模块热更新4. Vite创立我的项目Vite创立我的项目 npm init vite-app <project-name>cd <project-name>npm installnpm run dev基于模板创立我的项目 ...

July 25, 2021 · 13 min · jiezi

关于vue.js:vueelement上传图片

1.开发环境 vue+element2.电脑系统 windows10专业版3.在开发的过程中,咱们会遇到上传文件的操作,上面我来分享一下vue+element怎么实现,心愿对你有所帮忙。4.废话不多说,间接上代码: <el-upload list-type="picture-card" :on-success="uploadsuccess" :action="uploadurl"> <i slot="default" class="el-icon-plus"> </i> <div slot="file" slot-scope="{ file }"> <img class="el-upload-list__item-thumbnail" :src="file.url" alt="" /> <span class="el-upload-list__item-actions"> <span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)"> <i class="el-icon-zoom-in"> </i> </span> <span v-if="!disabled" class="el-upload-list__item-delete" @click="handleDownload(file)"> <i class="el-icon-download"> </i> </span> <span v-if="!disabled" class="el-upload-list__item-delete" @click="handleRemove(file)"> <i class="el-icon-delete"> </i> </span> </span> </div></el-upload>5.在return中增加: // 头像上传文件 files: "", // 图片上传地址 uploadurl: process.env.VUE_APP_BASE_URL + "/api/account/coconfig", dialogImageUrl: "", dialogVisible: false, disabled: false,6.在methods中增加如下代码: handleRemove(file) { console.log(file);},handlePictureCardPreview(file) { this.dialogImageUrl = file.url; this.dialogVisible = true;},handleDownload(file) { console.log(file);},// 图片上传胜利的回调函数 uploadsuccess(response, file, fileList) { // console.log(response); console.log(file); // console.log(fileList); // 存储 上传图片的url // this.files = file; this.files = file.raw; },7.数据申请代码: ...

July 23, 2021 · 1 min · jiezi

关于vue.js:axios发送multipartformdata请求

1.开发环境 vue2.电脑系统 windows10专业版3.在数据申请的过程中,咱们可能会遇到后端须要multipart/form-data这样的格局,那么前端如何实现呢?4.废话不多说,办法如下: let formData = new FormData(); const param = { account: this.$store.state.account, nickname: this.form.Yournickname, remark: this.form.Introductiontothe, }; formData.append("param", JSON.stringify(param)); console.log(formData); accountconfig(formData).then((res) => { console.log(res); });// 留神:后端须要的参数格局5.应用这种办法,想后端传递的成果为:6.本期的分享到了这里就完结了,心愿对你有所帮忙,让咱们一起致力走向巅峰。

July 23, 2021 · 1 min · jiezi

关于vue.js:vue解析后端base64图片

1.开发环境 vue2.电脑系统 windows10专业版3.在开发的过程中,咱们有时候拿到后端返回的图片是base64的模式,上面我来分享一下应用办法4.废话不多说,间接上代码: <img src="data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAAHgAAAAoCAIAAAC6iKlyAAAFL0lEQVR42u3Zb2hXVRgH8EsbGoNe%0D%0ABJWmKeGcL1TajKGbmlGjjAWDRstQ7IWoc%2BALw6SgF669iWqRYKUuCWJtGDrDSCgkN6SUEnHG1PbC%0D%0AgVgJib5okkZ%2F7IEnHp7Ouee5zzn33LsJHb778dv9nXt%2Fd5%2Ffw3PP%2FS25dduO6rH%2Bp4%2F9UeY7ftva%0D%0AjAnYN4Gfrp0vQm5H65Kh84gn9Ay5MSvrL1AmrfLiXRsAGh6NNOzrN7ZMyOl98MwUCD7%2F%2FLXLSeok%0D%0AEofnHL04%2BrXDVa1nTsMjJH9Fg3Xq9g0...">5.后端返回的是以一个base64的模式 iVBORw0KGgoAAAANSUhEUgAAAFAAAABQAQAAAACmas8AAAAAsUlEQVR42rXTuw0DIQwGYFsUlCxgiTXSZaWwwF0mCCvRscZJLBC6K1CIOSlcg0mT/NVXIPxAQO2B3xJAFxcARdoaycWaRRJGMhHcjDV/IeCMXA3WXnhA7pfO1gfk2HP4AZUPBQMZkcXtye/Vi0x33Y4bkXwN3fSGEwb1AJtFcmi52iqyTQyQvEjeWVlgQ5G89fS8HAOJVC+t8ozFBHIi27th/RQesPW77sfWx/zXZ+h5A2F/B1jnhCpjAAAAAElFTkSuQmCC6.本期的分享到了这里就完结啦,心愿对你有所帮忙,让咱们一起致力走向巅峰。

July 22, 2021 · 1 min · jiezi

关于vue.js:svgjs-实现echarts仪表盘统计图

emmmmm,svg也能像canvas一样绘制图像,两者的区别,大家能够本人去查一下,接下来我来给大家分享一下怎么用svg绘制echarts的仪表盘,次要应用path门路中的弧形命令A加stroke来实现的,后续会学习更多svg绘制图形,再分享给大家。 <template> <svg class="time-circle" xmlns="http://www.w3.org/2000/svg" height="120" width="120" viewBox="0 0 120 120" > <path v-for="(item, index) in pointArray" :key="index" :d="getPathByIndex(index)" :stroke="colors[index]" stroke-width="13" fill="none" stroke-dasharray="3,2" transform="translate(10,10)" ></path> </svg></template><script>export default { props: { nums: { type: Array, default: () => [10, 10, 20] }, colors: { type: Array, default: () => ['#FBBC00', '#00A8FF', '#07FE82'] } }, data() { return {}; }, computed: { pathStr() { const r = this.radius; return `M${r} 0 M@1 @2 A${r} ${r} 0 @5 1 @3 @4`; /** A命令的参数:A rx ry x-axis-rotation large-arc-flag sweep-flag x y 弧形命令A的前两个参数别离是x轴半径和y轴半径,弧形命令A的第三个参数示意弧形的旋转状况,large-arc-flag(角度大小) 和sweep-flag(弧线方向), large-arc-flag决定弧线是大于还是小于180度,0示意小角度弧,1示意大角度弧。sweep-flag示意弧线的方向,0示意从终点到起点沿逆时针画弧, 1示意从终点到起点沿顺时针画弧 path门路,@1 @2以后终点坐标,@5决定弧线是大于还是小于180度,0示意小角度弧,1示意大角度弧 */ }, radius() { // 圆的半径 return 50; }, totalNum() { // 总数,依据总数算出1对应的角度数 return this.nums.reduce((total, curValue) => total + curValue); }, pointArray() { const r = this.radius; // 每个数字对应的角度 const deg = 360 / this.totalNum; // 第三位示意弧度 0是小圆,1是大圆 const pAarray = []; let total = 0; this.nums.forEach((item, index) => { // 以后数字之前的角度,算出起始角度 const preDeg = deg * total; // 之前存在的弧度 const preRad = (preDeg / 180) * Math.PI; //依据三角函数算出坐标点 const sx = r + r * Math.sin(preRad); const sy = r - r * Math.cos(preRad); // 依据本人的角度,计算是大圆还是小圆 const dmax = deg * item <= 180 ? 0 : 1; pAarray.push([sx, sy, dmax]); total += item; }); return pAarray; } }, methods: { getPathByIndex(index) { // 终点 const sp = this.pointArray[index]; // 起点 const ep = this.pointArray[ index + 1 === this.nums.length ? 0 : index + 1 ]; return this.pathStr .replace('@1', sp[0]) .replace('@2', sp[1]) .replace('@3', ep[0]) .replace('@4', ep[1]) .replace('@5', sp[2]); } }};</script>

July 22, 2021 · 2 min · jiezi

关于vue.js:vue引入webp格式图片报错解决

July 22, 2021 · 0 min · jiezi

关于vue.js:vue中引入高德地图

vue低版本脚手架引入1、在index.html文件中引入高德相干链接,如下所示:2、在eslintrc.js中批改,引入amap3、在main.js中引入: vue3.0脚手架引入1、在index.html中引入高德相干链接,如上所示;2、在main.js中引入3、在vue.config.js中批改:

July 22, 2021 · 1 min · jiezi

关于vue.js:elementui的表格正确使用骨架屏vueelementuiskeleton

1、装置npm i vue-elementui-skeleton 2、引入import Vue from 'vue';import VueElementUISkeleton from 'vue-elementui-skeleton';Vue.use(VueElementUISkeleton, { directiveName: 'skeleton', rows: 10, radius: 3, bg: 'red'});// 能够设置选项的全局默认值和指令名称/*Vue.use(VueElementUISkeleton, { directiveName: 'skeleton', rows: 10, radius: 3, bg: 'red'});*/3、援用<template> <el-table v-skeleton="{loading: loading, rows: 10}" :data="tableData" style="width: 100%" > <el-table-column prop="date" label="日期" width="180" /> <el-table-column prop="name" label="姓名" width="180" /> <el-table-column prop="address" label="地址" /> </el-table></template><script> export default { data() { return { loading: false, tableData: [] }; }, mounted() { // 模仿申请耗时2s let that = this; that.loading = true; setTimeout(function () { that.loading = false; that.tableData = [{ date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄' }, { date: '2016-05-04', name: '王小虎', address: '上海市普陀区金沙江路 1517 弄' }, { date: '2016-05-01', name: '王小虎', address: '上海市普陀区金沙江路 1519 弄' }, { date: '2016-05-03', name: '王小虎', address: '上海市普陀区金沙江路 1516 弄' }]; }, 2000); } };</script>

July 22, 2021 · 1 min · jiezi

关于vue.js:vue源码解析一

vue源码解析一、初始化1.new Vue()当咱们new Vue({el:'#app',data:{}}) 时候,这是就要找到Vue的构造函数该文件的门路为src\core\instance\index.jsVue的构造函数 判断环境并且 立刻调用this._init()办法,并把参数传入。function Vue (options) { 判断是否为生产环境并且 查看vue是否在this的prototype的原型上 // if (process.env.NODE_ENV !== 'production' && // !(this instanceof Vue) // ) { // warn('Vue is a constructor and should be called with the `new` keyword') // } this._init(options)}合并配置initMixin(Vue)定义$data,props,set,delete,watch,并且$data和$props是只读属性。stateMixin(Vue)初始化事件核心eventsMixin(Vue)初始化生命周期lifecycleMixin(Vue)初始化渲染函数renderMixin(Vue)export default VueVue就是一个Function实现的类,应用必须是new实例,而后调用this._init办法构造函数下方执行了很多办法(***MIixin(Vue)),这些办法的作用就是给Vue的prototype下面增加一些办法,这些办法是依照性能去定义的,别离在多个模块去实现。2.this._init()的过程this._init(options) 该办法是在initMixin(Vue)外面实现的。门路 src\core\instance\init.jsVue: Class<Component> 指定传入参数为class类export function initMixin (Vue: Class<Component>) { 在Vue的原型下面增加_init()办法 负责vue的初始化过程。 Vue.prototype._init = function (options?: Object) { 获取vue的实例 const vm: Component = this 每个vue下面都有一个uid 让vueuid自增 保障vue的唯一性 vm._uid = uid++ vue实例不应该是一个响应式的,做个标记 vm._isVue = true ***************************************************************************** if (options && options._isComponent) { /** * 如果是子组件初始化时走这里,这里只做了一些性能优化 * 将组件配置对象上的一些深层次属性放到 vm.$options 选项中,以进步代码的执行效率 */ initInternalComponent(vm, options) } else { vm.$options = mergeOptions( resolveConstructorOptions(vm.constructor), options || {}, vm ) } /* istanbul ignore else */ if (process.env.NODE_ENV !== 'production') { initProxy(vm) } else { vm._renderProxy = vm } // expose real self vm._self = vm 组件关系初始化 initLifecycle(vm) 初始化自定义事件 initEvents(vm) 初始化插槽 initRender(vm) 调用 beforeCreate 的生命周期 callHook(vm, 'beforeCreate') provide和reject传值 initInjections(vm) // resolve injections before data/props 数据初始化 响应式原理的外围,解决 props methods computed data watch 等 initState(vm) provide和reject传值 initProvide(vm) // resolve provide after data/props 调用 created 的生命周期 callHook(vm, 'created') /* istanbul ignore if */ // if (process.env.NODE_ENV !== 'production' && config.performance && mark) { // vm._name = formatComponentName(vm, false) // mark(endTag) // measure(`vue ${vm._name} init`, startTag, endTag) // } 判断数据中有没有el,如果有,主动执行$mount 没有的话,就要手动去挂载。 if (vm.$options.el) { vm.$mount(vm.$options.el) } }}3.响应式原理initState(vm)initState在import { initState } from './state'同级目录下找到state.jsexport function initState (vm: Component) { vm._watchers = [] const opts = vm.$options 解决props对象 为每一个props对象下面设置响应式 if (opts.props) initProps(vm, opts.props) 解决methods if (opts.methods) initMethods(vm, opts.methods) 初始化data, if (opts.data) { initData(vm) } else { observe(vm._data = {}, true /* asRootData */) } 解决conputed if (opts.computed) initComputed(vm, opts.computed) 解决watch if (opts.watch && opts.watch !== nativeWatch) { initWatch(vm, opts.watch) }}

July 21, 2021 · 2 min · jiezi

关于vue.js:elementUI中的eldatepicker日期月份时间选择器禁用选中当前和以后的日期

问题形容工夫选择器抉择日期、月份在我的项目中比拟常见,比方查问历史记录,咱们须要抉择具体日期或者发申请,获取历史数据。所以咱们须要对工夫选择器做一些管制,比方历史记录查问的话,就不能抉择以后日期和当前的日期了。所以就须要把以后日期和将来日期给禁用掉,本文记录一下相应的代码写法。 应用饿了么UI必定是要用官网给到的api,这里咱们应用的是picker-options和disabledDate去管制,附上官网文档地址链接: https://element.eleme.cn/#/zh...禁用日期案例效果图 代码如下<template> <div id="app"> <el-date-picker format="yyyy-MM-dd" value-format="yyyy-MM-dd" type="date" placeholder="请抉择日期" v-model="dayDate" :picker-options="setDisabled" ></el-date-picker> </div></template><script>export default { data() { return { timer: null, dayDate: "", setDisabled: { disabledDate(time) { return time.getTime() > Date.now(); // 可选历史天、可选以后天、不可选将来天 // return time.getTime() > Date.now() - 8.64e7; // 可选历史天、不可选以后天、不可选将来天 // return time.getTime() < Date.now() - 8.64e7; // 不可选历史天、可选以后天、可选将来天 // return time.getTime() < Date.now(); // 不可选历史天、不可选以后天、可选将来天 }, }, }; }, /* 8.64e7 是迷信计数法 8.64乘以10的7次方,即为86400000也就是 1000*60*60*24 也就是一天的毫秒数。因为Date.now() 办法可能返回失去自1970年1月1日00:00:00(UTC)到以后工夫的毫秒数。咱们是北京工夫的时区,也就是为东8区, 终点工夫对应就是:"1970/01/01 08:00:00" picker-options须要一个最终的布尔值,所以是否减去8.64e7也就是是否往前推移一天,也就是是否蕴含以后的天数 */};</script><style lang="less" scoped>#app { width: 950px; height: 600px; box-sizing: border-box; margin: 50px;}</style>禁用日期简略,上面咱们说一下禁用月份,禁用月份须要对日期格局做一个转换并判断即可禁用月份案例效果图 ...

July 20, 2021 · 2 min · jiezi

关于vue.js:Pinia-快速入门

Pinia 是什么?Pinia 是一个用于 Vue 的状态治理库,相似 Vuex, 是 Vue 的另一种状态治理计划 Pinia 反对 Vue2 和 Vue3 本文只讲 Pinia 在 Vue3 中的应用, 在 Vue2 中应用略有差别,参考 官网文档Pinia 劣势合乎直觉,易于学习 极轻, 仅有 1 KB 模块化设计,便于拆分状态 装置 Pinia装置须要 @next 因为 Pinia 2 处于 beta 阶段, Pinia 2 是对应 Vue3 的版本 # 应用 npmnpm install pinia@next# 应用 yarnyarn add pinia@next创立一个 pinia(根存储)并将其传递给应用程序: import { createPinia } from 'pinia';app.use(createPinia());外围概念与根本应用StoreStore 是一个保留状态和业务逻辑的实体,能够自在读取和写入,并通过导入后在 setup 中应用 创立一个 store // store.jsimport { createStore } from "pinia";// createStore 调用后返回一个函数,调用该函数取得 Store 实体export const useStore = creteStore({ // id: 必须的,在所有 Store 中惟一 id: "myGlobalState", // state: 返回对象的函数 state: ()=> ({ count: 1 }),});应用 Store// xxx.vue<template> <div> {{store.count}} </div></template><script> // 导入 Store, 应用本人的门路 import { useStore } from "@/store/store.js"; export default { setup() { // 调用函数 取得Store const store = useStore(); return { store } } }</script>GettersPinia 中的 Getters 作用与 Vuex 中的 Getters 雷同,但应用略有差别 Pinia 中的 Getters 间接在 Store 上读取,形似 Store.xx,就和个别的属性读取一样 ...

July 20, 2021 · 2 min · jiezi

关于vue.js:10个自己遵循的-JavaScript-技巧和实践赶紧收藏吧

作者:Apoorv Tyagi译者:前端小智起源:dev有幻想,有干货,微信搜寻 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。 本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试残缺考点、材料以及我的系列文章。 废话不多说,间接安顿上。 1.应用数字分隔符当我须要解决大的数字时,这是最罕用的运算符之一。当在数字中应用分隔符(只有一个_)时,它看起来比没有分隔的数字要好。例如: let number = 98234567能够这么写 let number = 98_234_567而且它也实用于任何其余进制数。 const binary = 0b1000_0101;const hex = 0x12_34_56_78;几个注意事项: 在前导0后不能应用。 let num= 0_12不容许呈现在数字的开端。 let num= 500_2.始终应用分号应用分号终止行是一种很好的做法。如果遗记了,不会被正告,因为在大多数状况下,它将被JavaScript解析器插入,但依赖于主动分号插入(ASI)是不激励的。 谷歌,Airbnb和jQuery的JS格调指南,也举荐应用分号终止行。 3.不要遗记var当你第一次为一个变量赋值时,肯定要确保你没有对一个未声明的变量进行赋值。 对未声明的变量的赋值会主动导致一个全局变量的创立。防止全局变量❌ 全局变量很容易被其余脚本笼罩。例如,如果应用程序的两个独立局部定义了具备雷同名称但用处不同的全局变量,那么可能会导致不可预测的谬误,调试此类问题将是一个可怕的经验。 通常函数中的变量应该是部分的,这样当你执行完函数时它们就会开释。 4. Delete vs Splice应用splice而不是应用delete从一个数组中删除一个项。应用delete会删除对象的属性,但不会重置索引数组或更新其长度。 Delete > myArray = ['a', 'b', 'c', 'd'] ["a", "b", "c", "d"]> delete myArray[0] true> myArray[0] undefined请留神,事实上它并没有被设置为undefined的值,而是将该属性从数组中移除,使其看起来undefined。这个大家能够在管制把 myArray 打印就出看就晓得 了。 Splice Splice() 实际上删除了元素,重置了索引,并扭转了数组的长度。 > myArray = ['a', 'b', 'c', 'd'] ["a", "b", "c", "d"]> myArray.splice(0, 2) ["a", "b"]> myArray ["c", "d"]delete办法应该用于删除对象属性。5. map vs for loop应用map()函数遍历数组的项 ...

July 20, 2021 · 2 min · jiezi

关于vue.js:只需一步让你的搜索框智能得起飞

以前我总是这样过滤搜寻内容data.filter(item => item.indexOf(keywords) >= 0)这样的确能够满足关键字搜寻需要,但鉴于前端是间接出现画面给用户的人,咱们总是须要站在用户的角度去思考问题。前面我的项目做多了,其实发现这样在用户体验上并不够敌对,咱们来看下上面这个例子: chrome浏览器内编辑款式 vs code内编辑款式 在chrome浏览器内无奈进行非间断的字符匹配,造成了一些体验感的缺失,而在vs code内却能够自在间断地输出关键字匹配。毫无疑问在vs code中咱们的编辑体验会更加晦涩,因为在很多场景下,咱们记不得一段间断的关键字,而是在断断续续的关键字,此时咱们应用这种间断的关键字进行搜寻能够很好地进步用户体验,而且也不影响间断的关键字搜寻。 什么场景下能够用非间断关键字搜寻这类需要个别为搜寻本地数据时,且需要场景没有明确指定须要间断的关键字搜寻时,咱们都能够应用非间断关键字搜寻来实现,具体列举了以下几个场景: 树形菜单项搜寻:相似治理后盾页面的菜单、多节点搜寻checkbox选项搜寻:选项较多的可搜寻checkbox内门路列表搜寻:如vs code的文件搜寻本地缓存搜寻:微信的缓存聊天记录关键字搜寻接下来咱们探讨一下如何实现得益于万能的npmjs.com,经验百般搜寻,我在下面找到了一个不错的js函数库实现了非间断关键字搜寻,咱们先看一个简略的Demo,再分析一下它的实现原理。 js库在此 -> string-discontinuous-match此Demo中在1000条长度为200的随机字符串中非间断关键字搜寻,实现单次搜寻只须要1-2ms,性能可观。 接下来贴一下实现代码,通过Vue实现 <div id="app"> <div class="search-wrap"> <label></label> <input class="search-box" v-model="val" @input="inputHandler" /> </div> <div class="info"> <span>Data totals: {{ numbers }}</span> <span v-if="performance">Performance: {{ performance }}</span> </div> <div class="result"> <span class="item" v-for="item in strings" :key="item" v-html="item"></span> </div></div>// 初始状态data() { return { val: '', strings: strings, // strings内蕴含1000条测试随机字符串 numbers: strings.length, performance: '', };}以下为input事件实现 <input @input="inputHandler" />import { discontinuousMatch, replaceMatchedString } from 'string-discontinuous-match';function inputHandler() { // this.val为搜寻关键字 if (this.val) { let s = performance.now(); let ret = discontinuousMatch(strings, this.val); let e = performance.now(); this.strings = ret.map(item => { // 辅助函数replaceMatchedString return replaceMatchedString(item, chars => `<span class="keyword">${chars}</span>`); }); this.performance = (e - s) + 'ms'; } else { this.data = strings; this.strings = strings; this.performance = ''; } this.numbers = this.strings.length; }搜寻后果格局为: ...

July 19, 2021 · 1 min · jiezi

关于vue.js:Oracle122-cdb数据库统一检查

随着Oracle19c 被越来越多的客户应用,pdb 模式越来越多,如何更好更疾速的查看他们的信息呢,Oracle12c当前多了一个cdb_结尾的视图,来进行对立查看。 上面节选几个常用命令、 --查看pdb信息 or dba_pdbsset lines 160col name for a20col open_time for a40select con_id,dbid,name,open_mode,open_time,creation_time from v$pdbs; --查看CDB局部信息set lines 160col con_name for a30select c.con_id,c.name con_name,t.tablespace_name,t.contents,t.statusfrom v$containers c,cdb_tablespaces t where c.con_id=t.con_id and t.contents='UNDO'order by 1,2; --追随CDB启动alter pluggable database firsoul01 save state; --查看每个pdb大小select c.name,round(sum(s.bytes/1024/1024/1024),2) size_gbfrom cdb_segments s,v$containers c where c.con_id=s.con_id group by c.name order by 2 desc; --连贯 or tnsnamesalter session set container=orclpdb; --查看pdb的服务名col pdb for a15col name for a20col network_name for a20SELECT PDB, name,NETWORK_NAME, CON_ID FROM CDB_SERVICESWHERE PDB IS NOT NULL AND CON_ID > 2 ORDER BY PDB; ...

July 19, 2021 · 2 min · jiezi

关于vue.js:老大喊我做一个项目埋点方案我给他这么搞做前端的都用得上

啰里八嗦的话家喻户晓,做C端产品对用户体验的要求是极高的。同时产品施行是否到位,投入回报是否成正比,成了一个团队是否有处分的关键因素(这是一个最理论的软件团队的实在诉求“之一“哈哈哈)。只管后期会做泛滥的用户调研,收集收据等等,明确哪些是用户根底需要,哪些是用户兴奋需要,但还是须要一个具体的能够量化的数据撑持,来评估某项业务是否满足了用户实在的需要,以及为产品前期迭代做参考等等。 那么基于以上的理论状况,对于整个产品线而言,做一个埋点业务收集是十分必要的。当然做埋点还有更多的意义,在这里暂不展开讨论。 以下将对该计划施行过程进行全面的剖析,同时也将提供一个简略的正当的可复用的计划输入,感兴趣的客官请留步~✌ 以后现状目前3个产品业务线产品,对于前端我的项目而言是离开治理的,现有业务也会有源源不断的需要减少,前面还会减少新的产品线。次要应用Vue.js@2.0版本,但有一个我的项目是采纳3.0版本开发的。我的项目已开发迭代历经8个月,次要产品业务代码已超17万行。整体剖析对接第三方没有能够既能够满足当下需要,又能够满足强扩展性的要害因素的现成计划,同时对于隐衷信息的收集不能交给第三方。现有代码量不具备可精准卖点的条件。pv类型的数据收集可临时交给某度统计,这种大而抽象的数据只有经营会关注,埋点对用户剖析的粒度更小。埋点尽量不影响具体业务性能及代码,甚至相对的不影响。理论需要收集粒度到按钮级别的用户。页面进入工夫,停留时间,也就是要拿到enterTime和leaveTime。要具备可对某页面使用量,某按钮使用量,某用户应用轨迹,某时间段按钮使用量,用户浏览器根本信息,后盾最好具备前端页面性能点击量的可视化还原。把需要转换成数据以下是大抵的须要收集到的数据 userAgent // 浏览器信息,蕴含设施信息,分辨率等 path // 拜访页面 能够用router也能够用location.href pageInfo // 页面信息 enterTime和leaveTime userInfo // 用户信息 以后登录用户个人信息 eventData // 操作事件信息 事件类型,操作DOM节点,操作工夫,节点名称(html节点名称),节点文本 代码怎么下手不影响现有业务,抽离成公共类是必须的。用户信息以及其余前期可能记录的属于扩展性信息,应能够内部传入。目前应用开源UI框架,我的项目整体按钮节点都是button标签(局部不是的能够改过来)。数据记录和发送,发送不能太频繁,须要一个记录数据的队列,设定一个阈值,达到阈值后进行发送并清空。代码大略的雏形根本构造 class Monitor { constructor() { } /** * @description 初始化办法: * extentData 用于传入基于业务的数据信息, * router 是vue-router对象,这里既能够通过init传入,也能够在以后类模块间接引入, * config 是配置信息 * @param {*} { extentData = null, router = null, config = {} } * @memberof Monitor */ init({ extentData = null, router = null, config = {} }) { //TODO // 这里能够做一些笼罩默认配置,初始化监听事件等操作 let { vpt } = config this.vpt = vpt ? vpt : this.vpt this.uaHandler() // 这里上面会讲 this.eventHandler = this.eventCallback.bind(this) // 要害 document.addEventListener('click', this.eventHandler, true) }}应用形式 ...

July 19, 2021 · 3 min · jiezi

关于vue.js:Vue中的nextTick和update生命周期

nextTick的源码剖析var callbacks = [];var pending = false;function nextTick(cb, ctx) { var _resolve; callbacks.push(function() { if (cb) { try { cb.call(ctx); } catch (e) { handleError(e, ctx, 'nextTick'); } } else if (_resolve) { _resolve(ctx); } }); if (!pending) { pending = true; timerFunc(); } if (!cb && typeof Promise !== 'undefined') { return new Promise(function(resolve) { _resolve = resolve; }) }}能够看到在 nextTick 函数中把通过参数 cb 传入的函数,做一下包装而后 push 到 callbacks 数组中。而后用变量 pending 来保障执行一个事件循环中只执行一次 timerFunc()。最初执行 if (!cb && typeof Promise !== 'undefined'),判断参数 cb 不存在且浏览器反对 Promise,则返回一个 Promise 类实例化对象。例如 nextTick().then(() => {}),当 _resolve 函数执行,就会执行 then 的逻辑中。来看一下 timerFunc 函数的定义,先只看用 Promise 创立一个异步执行的 timerFunc 函数 ...

July 18, 2021 · 2 min · jiezi

关于vue.js:vue使用leafletanimatedmarker实现轨迹回放功能

一、装置依赖npm i -save leaflet.animatedmarker 二、在页面引入import 'leaflet.animatedmarker/src/AnimatedMarker'; var latlngs=[[113.3296179,23.1056464],[113.3441455,23.1029357],[111.37807769946298,23.469783629934806],[115.31021330053697,22.7360877700652]]; let car = require(`../../assets/img/car.png`); var carIcon = L.icon({ iconUrl: car, iconSize: [24, 24], iconAnchor: [12, 20], popupAnchor: [0, 0] }); animatedMarker = L.animatedMarker(latlngs, { icon: carIcon, interval: 2000, }).addTo(this.map)

July 17, 2021 · 1 min · jiezi

关于vue.js:基于vue20的相册组件

因为需要做了一个相册的业务组件,我感觉还挺难看的,分享给大家看一下,能够本人提取,6点几了,上班先! <template> <div class="img-wrapper"> <el-button icon="h-icon-angle_left" plain class="left to" :disabled="disabledPrev" @click="toRight" ></el-button> <div ref="imagesWrapper" class="images"> <div v-if="noData" class="empty-text"> <slot name="empty">暂无数据</slot> </div> <div v-show="!noData" class="items" :style="itemsStyle"> <div v-for="(item, index) in data" :key="index" class="item-img" :style="imgSize" :class="{ 'is-active': index === currentIndex }" @click="selected(index)" > <img :title="item[props.title]" :src="item[props.url]" /> <p v-if="item[props.title]" v-ellipsis class="item-date"> {{ item[props.title] }} </p> </div> </div> </div> <el-button icon="h-icon-angle_right" :disabled="disabledNext" plain class="right to" @click="Left" ></el-button> </div></template><script>export default { name: 'ImagesGroup', props: { imgSize: { type: Object, default: () => { return { width: '120px', height: '120px' }; } }, value: { type: Number, default: null }, data: { type: Array, default: () => [] } }, data() { return { props: { title: 'title', url: 'url', key: 'key', type: 'type' }, currentIndex: '', translateX: 0, pageSize: 0 // 一页展现的图片数 }; }, computed: { // 偏移度数 itemsStyle() { return { transform: `translateX(${-this.translateX}px)` }; }, // 每一项宽度 itemWidth() { return parseInt(this.imgSize.width.replace('px', '')) + 8; }, disabledPrev() { // 禁用前一页按钮 return this.translateX <= 0; }, disabledNext() { // 禁用后一页按钮 return ( this.translateX >= (this.data.length - this.pageSize) * this.itemWidth ); }, noData() { return this.data.length === 0; }, dataLength() { return this.data.length; } }, watch: { value: { immediate: true, handler(val) { this.currentIndex = val; } } }, mounted() { this.pageSize = this.wrapperWidth() / this.itemWidth; }, methods: { toRight() { if (this.translateX < this.pageSize * this.itemWidth) { this.translateX = 0; } else { this.translateX = this.translateX - this.pageSize * this.itemWidth; } }, Left() { this.translateX = this.translateX + this.pageSize * this.itemWidth; const maxTrans = this.itemWidth * (this.dataLength - this.pageSize); if (this.translateX > maxTrans) { this.translateX = maxTrans; } }, selected(index) { const center = this.pageSize >> 1; // 最初一页的两头地位 const lastCenter = this.dataLength - center; if (index > center && index < lastCenter) { // 与相册两头相差的图片数量 const step = index - center; // 将点击图片挪动到两头 this.translateX = this.itemWidth * step; } else { const maxTrans = this.itemWidth * (this.dataLength - this.pageSize); this.translateX = index <= center ? 0 : maxTrans; } if (this.currentIndex !== index) { this.currentIndex = index; this.$emit('input', index); } }, wrapperWidth() { if (this.$refs.imagesWrapper) { return this.$refs.imagesWrapper.offsetWidth; } return 0; } }};</script><style lang="less" scoped>.img-wrapper { display: flex; position: relative; margin: 20px; height: 120px; .to { width: 32px; height: 100%; padding: 0; } .images::before { position: absolute; z-index: 5; top: 0; height: 100%; width: 84px; content: ''; pointer-events: none; background: -webkit-gradient( linear, left top, right top, from(#fff), color-stop(50%, rgba(0, 0, 0, 0)) ); background: -o-linear-gradient(left, #fff, rgba(0, 0, 0, 0) 50%); background: linear-gradient(90deg, #fff, rgba(0, 0, 0, 0) 50%); } .images::after { position: absolute; z-index: 5; top: 0; height: 100%; right: 0; width: 84px; content: ''; pointer-events: none; background: -webkit-gradient( linear, right top, left top, from(#fff), color-stop(50%, rgba(0, 0, 0, 0)) ); background: -o-linear-gradient(right, #fff, rgba(0, 0, 0, 0) 50%); background: linear-gradient(270deg, #fff, rgba(0, 0, 0, 0) 50%); } .images { position: relative; overflow: hidden; width: 100%; height: 100%; margin: 0 2px; .empty-text { color: rgb(158, 158, 158); height: 100%; display: flex; align-items: center; justify-content: center; } .items { position: absolute; top: 0; left: 0; display: flex; // width: 6000px; height: 100%; align-items: center; transition: transform 0.25s ease; .item-img { display: inline-block; box-sizing: border-box; position: relative; margin-right: 8px; border: 2px solid rgba(0, 0, 0, 0); cursor: pointer; .item-date { bottom: 0px; position: absolute; width: 100%; height: 24px; background: rgba(0, 0, 0, 0.2); text-align: center; line-height: 24px; color: white; } img { width: 100%; height: 100%; } } .item-img:hover::after { // border-color: #409EFF; opacity: 0; } .item-img::after { position: absolute; top: 0; left: 0; width: 100%; height: 100%; content: ''; opacity: 0.2; pointer-events: none; -webkit-transition: opacity 0.3s ease; -o-transition: opacity 0.3s ease; transition: opacity 0.3s ease; background-color: #fff; } .is-active { border-color: #409eff; } .is-active:after { opacity: 0; } } }}</style> ...

July 17, 2021 · 3 min · jiezi