关于vue.js:ts-版-vue-之-vuepropertydecorator

明天咱们来聊一聊 vue-property-decorator 官网链接:https://www.npmjs.com/package... 来讲讲怎么用vue-property-decorator 提供了装璜器,和 Mixin 性能。 装璜器@Prop父子组件通信传值的装璜器,跟未用 ts 版的 vue prop 组件传值一样 @Prop({ type: String, default: '' }) xxx!: string;@PropSync与 @prop 相似,用于组件传值。不同的是,1.@PropSync 装璜器接管两个参数:propName:父组件传递过去的属性名;options:与@Prop的第一个参数统一;2.@PropSync 会生成一个新的计算属性 // 子组件 @PropSync('variate', { type: String, default: '' }) variate0!: string; variate0 为子组件应用变量// 父组件 :variate.sync="variate1" // variate1 为父组件所给变量小结:@PropSync 的工作形式与 @Prop 相似,除了它承受propName作为装璜器的参数之外,它还在幕后创立了一个计算的getter和setter。这样你就能够像应用惯例的数据属性一样应用这个属性,同时也能够像在父组件中增加.sync修饰符一样简略。 @Component在 ts 版本的vue中,@Component 装璜器代替了原来未用 ts 版本的 Component 页面援用组件 形式。 @Model@Model装璜器容许咱们在一个组件上自定义 v-model,接管两个参数:event: string 事件名;options: 与@Prop的第一个参数统一; @Model('change', { type: Boolean }) readonly checked!: boolean当父组件调用子组件去触发一个 change 事件并附带一个新的值的时候,这个值将会被更新到子组件 ...

December 27, 2021 · 1 min · jiezi

关于vue.js:Vue学习的4个实用的Javascript技巧

学习一门语言的一种十分无效的办法就是浏览该编程语言开发的优良开源我的项目的源代码。 Vuejs是最好的Javascript开源我的项目之一。 1.变量转字符串 vue/src/shared/util.js 将值转换为字符串是一个十分常见的需要,在Javascript中,有两个函数将值转换为字符串: String()JSON.stringify() 这两个性能具备不同的机制,请看上面代码: console.log(String(null)); // nullconsole.log(JSON.stringify(null)); // null console.log(String(undefined)); // undefined 这里是字符串console.log(JSON.stringify(undefined)); // undefined 这里是变量 console.log(String("abc")); // abcconsole.log(JSON.stringify("abc")); // "abc" console.log(String({ key: "value" })); // [object Object]console.log(JSON.stringify({ key: "value" })); // {"key":"value"} console.log(String([1, 2, 3])); // 1,2,3console.log(JSON.stringify([1, 2, 3])); // [1,2,3] const obj = { title: "devpoint", toString() { return "obj"; },};console.log(String(obj)); // objconsole.log(JSON.stringify(obj)); // {"title":"devpoint"}从下面输入后果来看,两个办法将对象转为字符串机制存在差别,如何抉择呢? 理论开发中咱们须要将null和undefined转换为字符串时,常常是心愿它返回一个空字符串。 当须要将一个数组和一个一般对象转换为字符串时,常常应用JSON.stringify。 如果须要对象的toString办法被重写,则须要应用String()。 在其余状况下,应用String()将变量转换为字符串。 为了满足以上条件,Vue源码的实现如下: function isPlainObject(obj) { return Object.prototype.toString.call(obj) === "[object Object]";}function toString(val) { if (val === null || val === undefined) return ""; if (Array.isArray(val)) return JSON.stringify(val); if (isPlainObject(val) && val.toString === Object.prototype.toString) return JSON.stringify(val); return String(val);} const obj = { title: "devpoint", toString() { return "obj"; },};console.log(toString(obj)); // objconsole.log(toString([1, 2, 3])); // [1, 2, 3]console.log(toString(undefined)); // ""console.log(toString(null)); // ""2.一般对象 ...

December 27, 2021 · 2 min · jiezi

关于vue.js:Vue-Render-函数-Table内编辑-应用

Vue Render 函数 Table内编辑 利用前言在以前版本中,通过在table中嵌套span和input的形式,来实现这个性能,然而在理论应用过程中,代码会显得特地的简短繁琐。这个时候,能够通过应用render函数来解决这个问题。 思路思路的话,大略都是一样的,通过管制其span、input的显隐来实现,点击后更改的作用。 代码局部通过creatElement创立一个divVNode,在再其中创立span的和input的VNode。 createElement('el-input', {}),createElement('span', {}),span VNodedomProps插入根底属性,再通过attrs赋值,通过class来管制showClass属性是否失效。 on中,通过input办法,将input中的value值传递到父级中,父级将值赋给以后单元格。 blur则是当input失去焦点时,暗藏input,使span显示。 domProps: { value: '',},ref: 'input',attrs: { value: this.value},on: { input: (event) => { this.$emit('input', event) }, blur: () => { this.show = 'text' this.$emit('refreshTable') },},class: { showClass: this.show != 'input',},残缺代码内部代码scope.row.date为行数据中单元格的数据 refreshTable是为了保障每次更新数据时,单元格能即便刷新 <radect :value="scope.row.date" @input="scope.row.date = $event" @refreshTable="refreshTable"></radect>组件代码<script>export default { props: ['value'], data () { return { show: 'text' //管制文本和输入框显影 } }, render: function (createElement) { return createElement('div', [ createElement('el-input', { domProps: { value: '', }, ref: 'input', attrs: { value: this.value }, on: { input: (event) => { this.$emit('input', event) }, blur: () => { this.show = 'text' this.$emit('refreshTable') }, }, class: { showClass: this.show != 'input', }, }), createElement('span', { domProps: { innerText: this.value }, on: { click: () => { this.show = 'input' this.$nextTick(() => { this.$refs.input.focus() }) } }, class: { showClass: this.show != 'text', }, }), ]) },}</script><style>.showClass { display: none;}</style>

December 27, 2021 · 1 min · jiezi

关于vue.js:Vue-使用dllPlugin编译优化后路由传参问题

应用dll优化编译后,减速了打包编译的过程,然而在应用中遇到一个问题。有个页面的传参是restful格调的路由显示传参,间接白屏了。 注:restful路由显示传参 -> 在router.js中配置const routes = [{ path: '/comparison/:idArr',name: 'Comparison',component: Comparison}]且在跳转时设置了params: { idArr }。 原来的形式(不应用dll编译)没有这种问题。 去看了代码,这个应用params且显示传递参数,需要是在新标签页带着参数关上。 为了这个目标有两种计划1、显示的params传参。 2、query传参。 (这种跳转新标签页关上页面,还要传递参数的状况,如果由前端来实现,肯定是把参数显化在地址栏外面,这个时候应用显式params和query传参都能够做,隐式的params传参,在新标签页关上会失落参数,只能用于原标签页路由跳转) 后由params传参改为query传参,躲避了这个问题。 vue router 路由跳转和传参总结:1、query 配 name2、query 配 path3、params 配 name(留神params不能配path)4、如果用隐式的params传参,在新标签页关上会失落参数。5、新标签页带着参数关上页面的状况,能够用显示的params传参,也能够用query传参,倡议query。 同步更新到本人的语雀https://www.yuque.com/diracke...

December 26, 2021 · 1 min · jiezi

关于vue.js:Vue-20-添加多环境打包配置vuecli45

1.创立vue.config.js 文件 module.exports = { // 根本门路 publicPath: "./", // 输入文件目录 outputDir: process.env.outputDir, lintOnSave: false, devServer: { proxy: { '/proxy': { target: "http://192.168.2.666:8080", changeOrigin: true, pathRewrite:{ '^/proxy':'' } } } }, css: { loaderOptions: { stylus: { import: "~@/assets/css/style.styl" } } }, configureWebpack: config => { config.optimization.minimizer[0].options.terserOptions.compress.drop_console = true }};2.我的项目根目录创立环境配置文件 .env.dev // .env.dev NODE_ENV = 'development'VUE_APP_URL_ENV = 'development'outputDir = 'dev'.env.uat // .env.uat NODE_ENV = 'production'VUE_APP_URL_ENV = 'uat'outputDir = 'uat'.env.prod ...

December 26, 2021 · 1 min · jiezi

关于vue.js:vue中实现-‘换肤-切换样式主题-功能的三种方式详解干货

形式1:定义全局的CSS变量App.vue: <style>/* 定义全局的css变量 */:root { /* 背景色 */ --theme_bg_color: red; /* 按钮色彩 */ --theme_button_color: yellowgreen;}</style>demo.vue(css): <style scoped> /* 应用全局的css变量设置色彩 */.myButton { background: var(--theme_bg_color);}.myDiv { background: var(--theme_button_color); width: 200px; height: 200px;}</style>demo.vue(html): <h3>换肤 / 切换款式主题 形式1:</h3> <button @click="changeTheme('Moccasin')">换肤为Moccasin</button> <button @click="changeTheme('#1E90FF')">换肤为#1E90FF</button> <button @click="changeTheme('#00FF7F')">换肤为#00FF7F</button> <button @click="changeTheme('DeepPink')">换肤为DeepPink</button> <button class="myButton">我是一个能够换肤的按钮</button> <div class="myDiv">我是一个能够换肤的div</div>demo.vue(js): <script>export default { setup() { // 切换主题形式1:批改全局CSS变量 let changeTheme = (color) => { document.documentElement.style.setProperty("--theme_bg_color", color); document.documentElement.style.setProperty("--theme_button_color", color); }; return { changeTheme }; },};</script>成果: ...

December 26, 2021 · 2 min · jiezi

关于vue.js:北京丨蓝湖丨产品设计协同平台丨诚招前端工程师-30K50K

蓝湖,专一于“数字发明经济(Digital Creation Economy)”这一外围畛域,服务于数字产品的外围产研设计流程,提供功能强大的在线协同设计工具和全周期解决方案,在互联网行业的渗透率超过98%,服务着 50 万的产品设计研发团队。 蓝湖产品设计合作平台是一款产品设计研发合作工具,无缝连贯产品、设计、研发流程,旨在升高沟通老本,缩短开发周期,进步工作效率,帮忙企业建设迷信的工作环境,晋升企业的开发效率。 MasterGo近期,蓝湖公布了重量级新产品 —— MasterGo 定位一站式产品设计合作工具。MasterGo 立足数字化发明场景,买通设计和代码的边界;充沛的在线协同和凋谢化;以社区化和资源共享,晋升数字发明效率的先进理念。 欢送各路技术搭档们关注咱们的岗位。坐标望京SOHO达不到预期的能够open再谈,相对高于市场程度,欢送简历猛砸liuguangfei@jwzg.com 前端工程师:岗位职责:: 参加蓝湖大前端架构的设计及外围代码的开发,尤其是可视化、图形编辑器、跨端相干技术,来进一步晋升蓝湖的交互体验。参加多平台组件、智能生成代码等相干的前沿技术的钻研与核心技术的实现,来减速视觉交互类产品的诞生过程。负责外围业务的实现,并领导高级开发工程师成长,一起来打造业界顶尖的大前端团队。 任职资格:有良好的WEB前端开发根底教训精通JS,至多相熟一门前端框架,如Vue计算机科学或相干畛域的本科及以上学历有一线互联网(BAT、TMD等)实习教训优先。

December 25, 2021 · 1 min · jiezi

关于vue.js:聚划算工时费

申达股份打动啊啊受骗了可好彩色的看金刚收快递费必定会借款方给水管道就返回个世纪东方感觉还是大部分看不出V型,指标我哥谨防受骗笔记本加粉丝必定就付款就是DNA粉丝【

December 25, 2021 · 1 min · jiezi

关于vue.js:在vue中使用HTML5-Web-SQL-浏览器数据库

HTML5 Web SQL 数据库Web SQL 是在浏览器上模仿数据库,能够应用 JS 来操作 SQL 实现对数据的读写。\ Web SQL 数据库 API 并不是 HTML5 标准的一部分,然而它是一个独立的标准,引入了一组应用 SQL 操作客户端数据库的 APIs。 如果你是一个 Web 后端程序员,应该很容易了解 SQL 的操作。 Web SQL 数据库能够在最新版的 Safari, Chrome 和 Opera 浏览器中工作。 外围办法以下是标准中定义的三个外围办法: openDatabase:这个办法应用现有的数据库或者新建的数据库创立一个数据库对象。transaction:这个办法让咱们可能管制一个事务,以及基于这种状况执行提交或者回滚。executeSql:这个办法用于执行理论的 SQL 查问。demo示例代码:<template> <div> <h3>HTML5 Web SQL 数据库</h3> <button @click="openWebSQL">关上(创立) Web SQL</button> <button @click="addItem">新增一条记录</button> <button @click="updateItem">批改第一条数据</button> <button @click="deleteItem">删除一条记录</button> <button @click="getData">查问数据</button> </div></template><script>export default { data() { return { MySQL: null }; }, created() { }, mounted() {}, methods: { openWebSQL() { //咱们能够应用 openDatabase() 办法来关上已存在的数据库,如果数据库不存在,则会创立一个新的数据库 this.MySQL = openDatabase("mydb01", "1.0", "Test DB", 2 * 1024 * 1024); /** * 插入数据 * 在执行下面的创立表语句后,咱们能够插入一些数据: */ this.MySQL.transaction(function(tx) { const d = tx.executeSql( "CREATE TABLE IF NOT EXISTS myTable (id unique, log)" ); tx.executeSql('INSERT INTO myTable (id, log) VALUES (1, "你好,同学")'); tx.executeSql('INSERT INTO myTable (id, log) VALUES (2, "甲乙丙丁")'); }); }, //新增一条记录 addItem() { this.MySQL.transaction(function(tx) { //先查 tx.executeSql("Select * FROM myTable", [], (tx, results) => { console.log("查问后果 =>", results); console.log("查问数据长度 =>", results.rows.length); //我再依据查问已有数据的最初一条数据的id + 1 生成新id let e_id = results.rows[results.rows.length - 1].id + 1; let e_log = `Jason Ma到此一游${e_id}`; tx.executeSql("INSERT INTO myTable (id,log) VALUES (?, ?)", [ e_id, e_log ]); }); }); }, //批改一条记录 updateItem() { this.MySQL.transaction(function(tx) { tx.executeSql("UPDATE myTable SET log='大王叫我来巡山...' WHERE id=1"); }); }, //删除一条记录 deleteItem(id = 3) { this.MySQL.transaction(function(tx) { //既能够动静id形式,也能够 tx.executeSql("DELETE FROM myTable WHERE id=?", [id]); // tx.executeSql("DELETE FROM myTable WHERE id=2"); }); }, //查问 getData() { this.MySQL.transaction(function(tx) { tx.executeSql("Select * FROM myTable", [], (tx, results) => { console.log("查问后果 =>", results); console.log("查问数据长度 =>", results.rows); }); }); } }};</script><style></style>

December 25, 2021 · 2 min · jiezi

关于vue.js:组件传值数据双向绑定

一、组件传值组件间的传值形式父子传值:props、emit、$parent、$chidren、ref兄弟之间传值:事件总线(on、emit)、Vuex 传值实例(1)父组件传到子组件(props)一个组件默认能够领有任意数量的 prop,任何值都能够传递给任何 prop。 // 父组件<template> <div> <ceshi @test="test"></ceshi> </div></template><script>export default { data() { test: '测试' }}</script>// 子组件接管 ceshi<template> <div> {{test}} </div></template><script>export default { props: { test: String } data() { }}</script>(2)子组件传到父组件(emit)子组件通过emit触发事件给父组件,父组件通过on去监听数据的变动。 // 父组件<template> <div> <ceshi :test="test" @change="change"></ceshi> </div></template><script>export default { data() { test: '测试' }, methods: { change(val){ console.log(val) } }}</script>// 子组件接管 ceshi<template> <div> {{test}} <button @click="getTitle"></button> </div></template><script>export default { `props: { test: String }` data() { title: '子组件' }, methods: { getTitle(){ this.$emit('change', this.title) // 将值绑定到change上传递过来 } }}</script>二、propprop类型以字符串模式列出: ...

December 24, 2021 · 2 min · jiezi

关于vue.js:input如何获取失去焦点鼠标点击的位置或者元素

需要背景举个栗子:如下日历,目前存在一个问题,当我删除掉input值的时候,日历里model的值并没有删除掉。只是input显示的值被删除了。 为了解决这个bug, 我须要给Input增加blur事件,清空日历model值。同时,如果我blur点击的区域如果在下方日历显示的中央,禁止blur里的办法执行。 重点问题如何判断blur事件鼠标点击的地位在日历上呢? 依据 MDN中blur的定义以及实际,我是没有方法从blur(event) 里获取所点击的地位的信息的。 所以我只能另辟蹊径,监听以后dom元素的click事件获取点击的中央,不就能够获取了。 解决方案全局监听click事件判断是否点击到了日历 window.document.addEventListener('click', this.handleDocClick, false)解决问题的路线是充斥波折的。 此时又产生了一个新的问题,发现blur事件永远比click事件先执行,blur都执行完了,我获取了地位也用不到呀。 blur,click执行程序解决blur和focus事件不会冒泡,其余表单事件都能够 click事件;所有元素都有此事件,会产生冒泡一个元素失去焦点,blur事件优先于click事件执行程序为mousedown > mouseup > click咱们只须要把 全局监听的click事件换成 mousedown就能够了 window.document.addEventListener('mousedown', this.handleDocClick, false)handleDocClick (e) { const target = e.target if (!this.picker) { return } // 日历是否被点击过 this.pickerClicked = contains(this.picker.$el, target) // contains 判断日历picker元素是否蕴含mousedown点击的元素},// 节点蕴含export const contains = (root, target) => { // root 节点是否蕴含 target 节点 const isElement = Object.prototype.toString.call(root).includes('Element') && Object.prototype.toString.call(target).includes('Element') if (!isElement) { return false } let node = target while (node) { if (node === root) { return true } node = node.parentNode } return false}

December 24, 2021 · 1 min · jiezi

关于vue.js:页面的前端路由和后端路由分别指什么

提到路由,大家个别会想到生存中常见的路由器,路由器次要用于连贯多个逻辑上离开的网络,逻辑网络代表-个独自的网络或者一个子网,能够通过路由器性能来实现不同网络之间数据的传递。在Vue中也引人了路由的概念,因而,咱们先来对程序开发中的路由进行简略地理解。 程序开发中的路由分为后端路由和前端路由,上面咱们别离进行简要介绍。 1. 后端路由后端路由通过用户申请的URL散发到具体的处理程序,浏览器每次跳转到不同的URL都会从新拜访服务器。服务器收到申请后,将数据和模板组合,返回HTML页面,或者间接返回HTML模板,由前端JavaScript程序再去申请数据,应用前端模板和数据进行组合生成最终的HTML页面。下图演示了后端路由的工作原理。 2. 前端路由前端路由就是把不同路由对应不同的内容或页面的工作交给前端来做。前端路由和后端路由的原理是相似的,然而实现的形式不一样。对于单页面利用(Single Page Application, SPA)来说,次要通过URL中的hash(#号)来实现不同页面之间的切换。hash有一个特点,就是HTTP申请中不会蕴含hash相干的内容,所以单页面程序中的页面跳转次要用hash来实现。下图演示了前端路由的工作原理。在上图中,index.html 前面的‘#home”是hash形式的路由,由前端路由来解决,将hash值与页面中的组件对应,当hash值为“#/home” 时,就显示“首页”组件。前端路由在拜访一个新页面的时候仅仅是变换了一下hash值而已,没有和服务端交互,所以不存在网络提早,晋升了用户体验。 猜你喜爱:Vue罕用的指令都有哪些?vue全家桶有哪些货色?具体指什么?Vue数据双向绑定的原理是什么?vue router的模式有哪几种?黑马程序员web前端开发高手班课程

December 24, 2021 · 1 min · jiezi

关于vue.js:在uniapp项目中基于uCharts绘制统计图以饼图为例

在dom中用 canvas绘制一个容器。 <view class="qiun-columns" v-show="pieData.length!=0"> <!-- 饼状图 --> <view class="qiun-bg-white qiun-title-bar qiun-common-mt"> <view class="qiun-title-dot-light">数据饼图</view> </view> <view class="qiun-charts"> <!--#ifdef MP-ALIPAY --> <canvas canvas-id="canvasPie" id="canvasPie" class="charts" :width="cWidth*pixelRatio" :height="cHeight*pixelRatio" :style="{'width':cWidth+'px','height':cHeight+'px'}" @touchstart="touchPie($event,'canvasPie')"></canvas> <!--#endif--> <!--#ifndef MP-ALIPAY --> <canvas canvas-id="canvasPie" id="canvasPie" class="charts" @touchstart="touchPie($event,'canvasPie')"></canvas> <!--#endif--> </view> </view>2、 援用组件,定义对象 <script>import uCharts from '@/components/u-charts/u-charts.js';var canvasObj = {};export default { components: { uCharts }, data() { return { cWidth: '', cHeight: '', cWidth2: '', //横屏图表 cHeight2: '', //横屏图表 pixelRatio: 1,//像素比 pieData: [{ "name": "", "data": 0 }], circular: true, }, onLoad(){ this.cWidth = uni.upx2px(750); this.cHeight = uni.upx2px(500); this.cWidth2 = uni.upx2px(700); this.cHeight2 = uni.upx2px(1100); this.showPie("canvasPie", data); }, methods: { showPie(canvasId, chartData) { canvasObj[canvasId] = new uCharts({ $this: _self, canvasId: canvasId,//页面组件canvas-id type: 'pie',//图表类型 fontSize: 11, padding: [15, 15, 0, 15], legend: { show: true, padding: 5, lineHeight: 11, margin: 0, }, background: '#FFFFFF', pixelRatio: _self.pixelRatio, series: chartData, animation: false, width: _self.cWidth * _self.pixelRatio, height: _self.cHeight * _self.pixelRatio, dataLabel: true, extra: { pie: { lableWidth: 15 } }, }); }, touchPie(e, id) { canvasObj[id].showToolTip(e, { format: function(item) { return item.name + ':' + item.data } }); }, }}</script>

December 24, 2021 · 1 min · jiezi

关于vue.js:关于在vuecli中-elementui-默认样式无法修改这件事

不多说,间接上图: F12 查看盒模型信息: 增加css: 失败了: 应用/deep/: 胜利了:

December 24, 2021 · 1 min · jiezi

关于vue.js:Vercel替代方案

优雅:收费,不便,去中心化之前在与敌人交换中,有人提到,将网站部署在vercel上,不是很稳固,常常被墙或者拜访很慢。这个问题在别的交换群里也有人已经提到过,那时候我就想本人掏钱买个服务器得了。然而大家都懂得,自建博客或者网站那些可怜得访问量切实不值得花钱去买一个专门得服务器。因为我也遇到过这些问题,所以听到他人说这个问题,我就特地关注。直到有一天在某技术社区刷到了一个新的解决方案,基于IPFS的去中心化部署--4everland。因而我做了实际,发现的确上手很快,根本与vercel没有差异,零老本转移或者制作备站。去中心化有什么益处呢?永远不会因为核心服务器的起因宕机!再次感叹Web3离咱们是越来越近了。上面是一些部署的过程,根本与Vercel相似,之前部署过vercel的小伙伴看一次预计就都懂了,甚至不必看,哈哈。先找到官网,抉择Hosting连贯你的GitHub账户创立一个新我的项目导入Git储存库,而后抉择一个我的项目,设置根目录抉择框架设置环境变量 最初deploy就行了,是不是很简略!比照于Vercel,4everland在国内的拜访绝对敌对,更重要的是去中心化。感兴趣的小伙伴赶快口头起来吧! 官网在这里

December 23, 2021 · 1 min · jiezi

关于vue.js:node-sass-安装版本

scss执行上面命令就没问题了,一把梭npm uninstall node-sassnpm i -D sass

December 23, 2021 · 1 min · jiezi

关于vue.js:vuejs中封装全局filter

创立filters文件夹,外面创立filters.js文件,用来定义全局filter filters.js let filterOne = (value) => { return value * 10}let filterTwo = (value, pm) => { return value * pm}export default { filterOne, filterTwo}main.js import filters from './filters/filters.js'for (let value in filters) { // value是filter名称(字符串) // filters[value] 对象外面的某个元素,就是filters中定义的办法 Vue.filter(value, filters[value])}这样就全局定义了所有的filter,就能够在界面中应用了。 年龄:{{ age | filterOne | filterTwo(0.5) }}

December 22, 2021 · 1 min · jiezi

关于vue.js:vuejs中mixin的使用

Vue中的mixin,是来散发Vue组件中的可复用性能。1、办法和数据在各个组件中不共享不像vuex那样,一个中央批改其余中央也会批改,mixin的数据的作用域就是被引入的组件外部。 2、援用组件中的钩子函数在混入对象中的钩子函数前面执行。3、援用组件中的同名办法会笼罩混入对象中的办法,不同名的会合并。4、案例剖析HelloWorld.vue <template> <div class="hello"> <div v-for="(item, index) in mixinData" :key="index"> 姓名:{{item.name}}, 年龄:{{item.age}} </div> </div></template><script>import CommonMethods from '../mixin/CommonMethods.vue'export default { name: 'HelloWorld', mixins: [CommonMethods], data () { return { msg: 'Welcome to Your Vue.js App' } }, mounted () { // 1、援用组件中的钩子函数在混入对象中的钩子函数前面执行。 this.mixinData = [ { name: '初始化数据', age: 10 } ] // 2、援用组件中的同名办法会笼罩混入对象中的办法,不同名的会合并。 this.mixinGetData() }, methods: { mixinGetData () { this.mixinData = [] return [] } }}</script>CommonMethods.vue <script>export default { name: 'mixinMethods', data () { return { mixinData: [] } }, mounted () { this.mixinData = [ { name: '初始化数据', age: 0 } ] }, methods: { mixinGetData () { let data = [ { name: 'zxc', age: 32 }, { name: 'lvy', age: 27 } ] this.mixinData = data return data } }}</script>

December 22, 2021 · 1 min · jiezi

关于vue.js:谁知道这个东西怎么调上下

下面图片是这个货色的应用的api上面的图片是我在操作时展现的成果在线求解

December 22, 2021 · 1 min · jiezi

关于vue.js:Vue一些常用的工具类

本文介绍一些罕用的工具类 1.验证码如下图,个别的后盾管理系统都会在登录的时候设计一个验证码,这个验证码是前端生成的,点击canvas能够切换验证码。二维码的类型是数字或者字母本人能够依据须要设置, 1.验证码的js如下图,首先引入验证码的js verifyCode的代码如下,本人依据须要批改长宽(_init办法中的宽和高),验证码的类型,色彩,烦扰线等。 function GVerify (options) { // 创立一个图形验证码对象,接管options对象为参数 this.options = { // 默认options参数值 id: '', // 容器Id canvasId: 'verifyCanvas', // canvas的ID width: '100', // 默认canvas宽度 height: '38', // 默认canvas高度 type: 'number', // 图形验证码默认类型blend:数字字母混合类型、number:纯数字、letter:纯字母 code: ''}if (Object.prototype.toString.call(options) === '[object Object]') { // 判断传入参数类型 for (var i in options) { // 依据传入的参数,批改默认参数值 this.options[i] = options[i] }} else { this.options.id = options}this.options.numArr = '0,1,2,3,4,5,6,7,8,9'.split(',')this.options.letterArr = getAllLetter()this._init()this.refresh()} GVerify.prototype = { ...

December 21, 2021 · 4 min · jiezi

关于vue.js:vitevue3兼容低版本

我的项目在安卓7版本一下手机上,不论是webview还是浏览器拜访,页面都是空白。能够很明确的晓得是vue的兼容问题,起初应用惯例的babel加垫片,但毫无作用,起初查看vite的插件库,发现@vitejs/plugin-legacy:为打包后的文件提供传统浏览器兼容性反对首先装置插件:npm i @vitejs/plugin-legacy -D而后配置vite.config.js import legacyPlugin from '@vitejs/plugin-legacy';export default defineConfig({ plugins: [ legacyPlugin({ targets: ['chrome 52'], // 须要兼容的指标列表,能够设置多个 additionalLegacyPolyfills: ['regenerator-runtime/runtime'], // 面向IE11时须要此插件 }),]})打包、运行到浏览器。新版本浏览器运行失常!旧版本浏览器运行失常!

December 21, 2021 · 1 min · jiezi

关于vue.js:Vue-data-中随意更改一个属性视图都会被更新吗

面试官:看过 Vue 的源码没?候选者:看过。面试官:那你说下 Vue data 中随便更改一个属性,视图都会被更新吗?候选者:不会。面试官:why?候选者:如果该属性没有被用到 template 中,就没有必要去更新视图,频繁这样性能不好。面试官:那 Vue 中是如何去实现该计划的?候选者:在实例初始化过程中,利用Object.defineProperty对 data 中的属性进行数据监听,如果在 template 中被应用到的属性,就被 Dep 类收集起来,等到属性被更改时会调用notify更新视图。面试官:那你怎么晓得那些属性是在 template 被用到的呢?候选者:WTF。。。这个倒不是很分明,您能解释下吗?面试官:OK,那我就简略解释下: 先写个简略的 demo,其中 data 中有 4 个属性a,b,c,d,在模板中被利用到的属性只有a,b。看看是不是只有a,b才会调用Dep收集起来呢?new Vue({ el: '#app', data() { return { a: 1, b: 2, c: 3, d: 4,};}, created() { console.log(this.b);this.b = 'aaa';}, template: '<div>Hello World{{a}}{{b}}</div>',});复制代码 在Vueinstance/state.js外面,会利用proxy把每个属性都 代理一遍 const keys = Object.keys(data) const props = vm.$options.props const methods = vm.$options.methods let i = keys.length while (i--) { const key = keys[i]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 observe(data, true / asRootData /)复制代码 ...

December 21, 2021 · 2 min · jiezi

关于vue.js:Vue2x和Vue30中的响应式原理

vue2.x的响应式实现原理: 对象类型:通过Object.defineProperty()对属性的读取、批改进行拦挡(数据劫持)。数组类型:通过重写更新数组的一系列办法来实现拦挡。(对数组的变更办法进行了包裹)。 Object.defineProperty(data, 'count', { get () {}, set () {}})存在问题: 新增属性、删除属性, 界面不会更新。间接通过下标批改数组, 界面不会自动更新。Vue3.0的响应式实现原理: 通过Proxy(代理): 拦挡对象中任意属性的变动, 包含:属性值的读写、属性的增加、属性的删除等。通过Reflect(反射): 对源对象的属性进行操作。MDN文档中形容的Proxy与Reflect: Proxy:https://developer.mozilla.org...Reflect:https://developer.mozilla.org... new Proxy(data, { // 拦挡读取属性值 get (target, prop) { return Reflect.get(target, prop) }, // 拦挡设置属性值或增加新属性 set (target, prop, value) { return Reflect.set(target, prop, value) }, // 拦挡删除属性 deleteProperty (target, prop) { return Reflect.deleteProperty(target, prop) }})proxy.name = 'tom'

December 21, 2021 · 1 min · jiezi

关于vue.js:深入解读vue3-watch踩坑记录

间接上代码,总共测试了上面这些状况(看正文) <template> <h2>以后求和为:{{ sum }}</h2> <button @click="sum++">点我+1</button> <hr /> <h2>以后的信息为:{{ msg }}</h2> <button @click="msg += '!'">批改信息</button> <hr /> <h2>姓名:{{ person.name }}</h2> <h2>年龄:{{ person.age }}</h2> <h2>薪资:{{ person.job.j1.salary }}K</h2> <button @click="person.name += '~'">批改姓名</button> <button @click="person.age++">增长年龄</button> <button @click="person.job.j1.salary++">涨薪</button></template><script>import { ref, reactive, watch } from "vue";export default { name: "Demo", setup() { //数据 let sum = ref(0); let msg = ref("你好啊"); let person = reactive({ name: "张三", age: 18, job: { j1: { salary: 3, }, }, }); //状况一:监督ref所定义的一个响应式数据 watch( sum, (newValue, oldValue) => { console.log("sum变了", newValue, oldValue); }, { immediate: true } ); //状况二:监督ref所定义的多个响应式数据 watch( [sum, msg], (newValue, oldValue) => { console.log("sum或msg变了", newValue, oldValue); }, { immediate: true } ); /* 状况三:监督reactive所定义的一个响应式数据的全副属性 1.留神:此处无奈正确的获取oldValue 2.留神:强制开启了深度监督(deep配置有效) */ watch( person, (newValue, oldValue) => { console.log("person变动了", newValue, oldValue); }, { deep: false } ); //此处的deep配置有效 //状况四:监督reactive所定义的一个响应式数据中的某个属性 // watch( // () => person.name, // (newValue, oldValue) => { // console.log("person的name变动了", newValue, oldValue); // } // ); //状况五:监督reactive所定义的一个响应式数据中的某些属性 // watch([() => person.name, () => person.age], (newValue, oldValue) => { // console.log("person的name或age变动了", newValue, oldValue); // }); //非凡状况 // watch( // () => person.job, // (newValue, oldValue) => { // console.log("person的job变动了", newValue, oldValue); // }, // { deep: true } // ); //此处因为监督的是reactive素定义的对象中的某个属性,所以deep配置无效 //返回一个对象(罕用) return { sum, msg, person, }; },};</script>总结: ...

December 21, 2021 · 1 min · jiezi

关于vue.js:在Vuecli中使用mockjs

1、mock.js 拦挡ajax申请,生成随机数据新学到的货色,以我的形式分享一下,咱们在开发中,须要后端提供api接口,而后拿到接口去遍历生成数据,渲染到页面上显示。在有的时候,还没拿到后端提供的接口时,前端能够本人模仿后盾制作简略的json格局数据进行开发工作 mock.js 应用:可参考mock.js官网 1、前提在有搭建Vue-cli 我的项目后,下载axios和mock.js 装置:npm install mockjs axios 2、模仿数据,在我的项目src目录中新建mock文件夹,再建xxx.json的json格局数据文件 3、在mock文件夹中建设mockServer.js文件,引入mock,测试mock,可参考下图 4、批改ajax申请的mock门路(baseURL: '/api' 改成为 '/mock',其实就是原来的api) 5、在api文件夹 index.js中引入mockAjax.js文件,进行测试 6、这是我的测试后果 2、mock.js 模仿数据疾速上手,最简略用法1、还是先在脚手架中,下载axios和mock.js // npm install mockjs axios2、而后在src目录中别离创立mock文件夹和index.js文件,并在main.js中引入 require('./mock/index'); 3、开始模仿数据 (目录提醒 --> 在src目录下的mock文件夹index.js文件中书写以下代码) // 1、引入mockjsconst Mock = require('mockjs'); // 2、获取 mock.Random 对象const random = Mock.Random;console.log(random); // 简略应用就不操作了,须要操作的能够去看文档 // 3、根本用法 Mock.mock(url, type, data) // 参数文档 https://github.com/nuysoft/Mo...Mock.mock('/user/list', 'get', { code: 200, message: '胜利', data: { // 生成十个如下格局的数据'list|10': [ { 'id|+1': 1, // 数字从以后数开始顺次 +1 'age|18-40': 20, // 年龄为18-40之间的随机数字 'sex|1': ['男', '女'], // 性别是数组中随机的一个 name: '@cname', // 名字为随机中文名字 email: '@email', // 随机邮箱 isShow: '@boolean', // 随机获取boolean值 },],},}); ...

December 20, 2021 · 1 min · jiezi

关于vue.js:vue3-proxy本地代理

第一步在vue.config.js写上代理 devServer: { hot: true, compress: true, disableHostCheck: true, proxy: { "/api": { target: "http://xxxx:8002/Home",//你的接口地址 changeOrigin: true,//是否跨域 pathRewrite: { "^/api": ""//接口重写,示意/api结尾的就是代理到target,即是http://xxxx:8002/Home } } } },第二步,在axios文件外面配置baseurl const instance3 = axios.create({ baseURL: "/api", //这里会读取vue.config外面的配置。主动重写地址。 timeout: 60000, headers: { "Content-Type": "application/json; charset=utf-8" }});第三部,接口申请 var _this = this; _this .$axios3({ method: "post", url: "gettask", //失常申请接口地址就能够了 data: { id:1 } }) .then(function (res) { console.log(res); });这就是残缺的本地代理设置

December 20, 2021 · 1 min · jiezi

关于vue.js:Electron-app打包后启动报错Cannot-find-module-reflectmetadata

前言这是一系列Electron app开发过程中的踩坑之旅,特此记录下来,分享给大家,每一篇都是一个坑和填坑解决方案! 问题Electron app打包后启动报错:Cannot find module 'reflect-metadata' A JavaScript error occurred in the main processUncaught Exception:Error: Cannot find module 'reflect-metadata'Require stack:- /Applications/aDemo.app/Contents/Resources/app.asar/node_modules/@nestjs/core/index.js- /Applications/aDemo.app/Contents/Resources/app.asar/background.js- at Module._resolveFilename (internal/modules/cjs/loader.js:887:15)at Function.n._resolveFilename (electron/js2c/browser_init.js:257:1128)at Module._load (internal/modules/cjs/loader.js:732:27)at Function.f._load (electron/js2c/asar_bundle.js:5:12913)at Module.require (internal/modules/cjs/loader.js:959:19)at require (internal/modules/cjs/helpers.js:88:18)at Object.<anonymous> (/Applications/aDemo.app/Contents/Resources/app.asar/node_modules/@nestjs/core/index.js:11:1)at Module._compile (internal/modules/cjs/loader.js:1078:30)at Object.Module._extensions..js (internal/modules/cjs/loader.js:1108:10)at Module.load (internal/modules/cjs/loader.js:935:32)剖析依照谬误提醒,是表白在打包后的app.asar/node_modules中没有找到reflect-metadata这个模块,然而我在开发的node_modules目录中找到了这个,然而在app.asar/node_modules中的确没有找到reflect-metadata,所以我狐疑是打包时没有将reflect-metadata打包进app.asar/node_modules 所以猜想如果须要将这个依赖打包进去是不是须要一些额定的配置?依照这个方向在网上找了一圈都没有找到相干配置的阐明,于是我在Github上提交了一个issue,而后只能一点点啃官网的英文文档了! GIthub issue链接:https://github.com/nklayman/v...官网文档链接:https://nklayman.github.io/vu... 解决方案在官网文档中找到了相似的阐明,并且依照阐明测试通过,官网文档阐明片段如下: Native modules are supported and should work without any configuration, assuming nodeIntegration is enabled. If you get errors, you may need to set the native dependency as an webpack external (opens new window). It should get found automatically, but it might not. To do this, use the externals option:// vue.config.jsmodule.exports = { pluginOptions: { electronBuilder: { // List native deps here if they don't work externals: ['my-native-dep'], // If you are using Yarn Workspaces, you may have multiple node_modules folders // List them all here so that VCP Electron Builder can find them nodeModulesPath: ['../../node_modules', './node_modules'] } }}粗心就是通知开发者,如果发现打包后某些模块不工作,须要你在electronBuilder中配置一下! ...

December 20, 2021 · 1 min · jiezi

关于vue.js:爆款预订2022-年最值得关注的后台框架-Fantasticadmin

前言如果 2021 年你还没有据说过 Fantastic-admin ,那行将到来的 2022 年可不要再错过了。Fantastic-admin 做为一款开箱即用的 Vue 中后盾管理系统框架,间隔首次面向公众曾经过来一年多的工夫了,在这一年多的工夫里,咱们服务了数百个团队和集体开发者,利用在近千款的产品和我的项目中(激进预计)。其中小到有刚步入社会的新人,用 Fantastic-admin 写了一个练习我的项目并胜利找到工作;大到地方性的国企/事业单位也有 Fantastic-admin 的身影。 并且在这一年里,Fantastic-admin 也从 Vue2 版本正式降级到了 Vue3 版本,采纳了官网举荐的构建工具 Vite ,减少并优化了许多新个性,让利用场景更加宽泛,开发体验更加丝滑。搭配不断完善的文档,不论是用于学习参考,还是理论利用,置信肯定会有所播种。 接下来我会从几个方面介绍框架的个性,还不快快珍藏一波~ <img src="C:\Users\hoora\Desktop\TVd4qU.gif" style="zoom:50%;" /> 开箱即用什么是「开箱即用」?就是即使不看文档,你也能依据文件夹布局、代码正文,疾速上手开发业务性能。做为框架的作者,我始终认为,只有我尽可能的不偷懒,使用者就能够尽可能的“偷懒”。所以为了升高使用者入门老本,在开发初期就比照了大量同类后盾框架,小到文件夹布局、命名都有考量,尽可能合乎使用者的直觉,或者说是开发人员的习惯,用人话说就是:让你在开发过程中,想找某个模块下的文件,感觉它应该在什么目录下,那它就在你想的那个目录下。 当然除了上手简略,适宜老手外,对高级开发者,在代码里也有详尽的正文,搭配文档上的介绍,让你对某个性能点能够疾速了解框架的设计逻辑与实现形式。 应用有文档,代码有正文,还缺什么呢?对,就是视频教程。思考到有很大一部分后端开发者也在应用 Fantastic-admin ,我十分能了解学习一门新技术时最初期时的那种迷茫,因为可能连入门文档都未必能马上看懂,开发环境都得捣鼓良久,所以我也筹备了几期疾速上手的视频教程(目前视频教程还只有 Vue2 版本的,Vue3 版本的视频教程筹备在明年开始制作)。 丰盛的配置项如何在保障简略易上手的前提下,还能让功能丰富且欠缺?那配置化必然贯通整个框架。框架配置例如布局、主题、标签栏、面包屑导航等简直所有的性能个性,你都能够在框架配置文件里进行配置,并且框架做了最大水平的优化,让配置项足够简单明了,例如大部分的配置都是 Boolean 类型的开关,如下图(局部): 与之绝对的,在我的项目运行的时候,你还能够在浏览器里间接实时查看不同配置项的实际效果(局部): 环境配置为不便不同生产环境下可能须要有不一样的构建配置,框架也提供局部打包构建相干的配置,不便疾速切换。 路由(导航)配置大部分后盾框架都是采纳路由配置生成侧边导航栏的模式,本框架也不例外,但最大的差异就是 Fantastic-admin 的配置参数足够丰盛。例如,除了能够设置导航图标外,还能够设置导航激活时的图标;包含更智能的页面缓存配置(上面会具体介绍);以及可对每个路由页面设置底部网站版权信息是否显示等等。 进阶性能诸如页面缓存、权限、国际化、谬误日志上报、自定义字体、PWA利用等等性能,只有你想应用,无需自行集成,框架全都有。页面缓存三级(多级)路由缓存是后盾框架最常见,且也是很难解决的痛点,而 Fantastic-admin 提供了一种全新的概念,叫路由扁平化,并在框架内提供了最佳实际。 其实路由扁平化的概念就是把多级路由转换成二级,但保留路由原始的层级构造(用于导航栏展现)。这个计划我在去年的这篇《一劳永逸,解决基于 keep-alive 的后盾多级路由缓存问题》文章里曾经实际并验证胜利。 路由扁平化解决后的成果+-------------------------+ +-------------------------+| Layout | | Layout.vue || +-------------------+ | | +-------------------+ || | Empty | | +----------> | | Page | || | +-------------+ | | | | | || | | Page | | | | | | || | +-------------+ | | | | | || +-------------------+ | | +-------------------+ |+-------------------------+ +-------------------------+当初在最新的 Vue3 版本中,页面缓存失去了进一步的优化,通过简略的路由配置就能够开启页面缓存,并且比照同类后盾框架,会更加智能。例如能够依据某个页面来到跳转到不同的页面进行区别解决,如 A 页面跳转到 B 页面时,则 A 页面进行缓存,A 页面跳转到 C 页面时,则 A 页面不缓存。 ...

December 20, 2021 · 2 min · jiezi

关于vue.js:VUE-30-源码-scriptsutilsjs-介绍了模糊匹配模块名称2个方法

文件门路:VUE 3.0 源码 scripts/utils.js 昨天咱们解读的 scripts/dev.js 文件中有这么一句话: // 获取 命令行参数中输出的模块名称,默认值:vueconst target = args._.length ? fuzzyMatchTarget(args._)[0] : 'vue'语句中的 fuzzyMatchTarget 函数就定义在utils.js文件中,目标是对终端命令行中传入的模块参数进行解析,是否可能匹配根目录下/packages 目录下的模块名 源码如下: /** nodejs模块——fs模块:fs模块用于对系统文件及目录进行读写操作 */const fs = require('fs')/** nodejs模块——chalk模块:作用是批改控制台中字符串的款式 */const chalk = require('chalk')/** * targets:返回指标模块列表 如:['compiler-core', 'compiler-dom'] * fs.readdirSync 同步读取 package.json同目录 packages 文件夹,返回改文件夹下所有子文件夹名称列表 */const targets = (exports.targets = fs.readdirSync('packages').filter(f => { // 同步判断:过滤掉不是文件夹的数据 if (!fs.statSync(`packages/${f}`).isDirectory()) { return false } const pkg = require(`../packages/${f}/package.json`) /** * 过滤掉 package.json 中 private:true 的公有库 以及 buildOptions为空的属性 */ if (pkg.private && !pkg.buildOptions) { return false } return true}))/** * 含糊匹配 命令行中输出的模块名称(partialTargets:可输出缩写,含糊匹配也可胜利) 跟理论 所有模块列表(targets)的匹配后果 * @param {string[]} partialTargets Targets 即命令行中输出的 模块名列表 * @param {*} includeAllMatching 设置为 true 时,将返回targets 中所有匹配后果;false时只返回第一个后果 * @returns */exports.fuzzyMatchTarget = (partialTargets, includeAllMatching) => { const matched = [] partialTargets.forEach(partialTarget => { for (const target of targets) { /** * 'compiler-core'.match('core') 返回非null */ if (target.match(partialTarget)) { matched.push(target) // includeAllMatching 设置为 true 时,将返回targets 中所有匹配后果;false时只返回第一个后果 if (!includeAllMatching) { break } } } }) if (matched.length) { return matched } else { console.log() // 匹配后果为空时:抛出Error 提醒命令行中输出端模块名称(partialTargets)找不到 console.error( ` ${chalk.bgRed.white(' ERROR ')} ${chalk.red( `Target ${chalk.underline(partialTargets)} not found!` )}` ) console.log() // 0示意没有任何类型的故障完结过程,而1示意因为某种故障而完结过程。 process.exit(1) }}如果您对 “前端源码” 情有独钟,能够微信扫码关注上面的公众号二维码,内容始终继续更新中!以后 VUE3.0 源码正在解析中,欢送捧场! ...

December 19, 2021 · 1 min · jiezi

关于vue.js:冒泡机制导致的相关问题

在我的项目中,因为冒泡机制,外部div 和内部div 调用的同一个办法执行了屡次,导致传值不正确。 问题代码: <div class="outer" @click="handleCick"> <div class="middle" @click="middle"> <button @click="handleCick">点击我(^_^)</button> </div></div> methods: { middle: function() { // console.log("middle: 这是两头的Div"); console.log("middle ___ isClick", this.isClick); }, outer: function() { // console.log("outer: 这是里面的Div"); console.log("outer ___ isClick", this.isClick); }, handleCick() { console.log(" 以后___ isClick", this.isClick); this.isClick = !this.isClick console.log(" ___ isClick", this.isClick); }, }输入后果: 以后___ isClick false ___ isClick true middle ___ isClick true 以后___ isClick true ___ isClick false从打印后果上看,handleCick 这个办法,执行了两次,这也是冒泡机制导致。所以,在vue 中能够应用事件修饰符stop 来阻止冒泡行为。其余的vue事件修饰符有 .prevent .stop .once .capture .self ...

December 19, 2021 · 1 min · jiezi

关于vue.js:vuecli3-vue2-保留-webpack-支持-vite-成功实践

大家好!文本是为了晋升开发效率及体验实际诞生的。 我的项目背景:脚手架:vue-cli3,具体为 "@vue/cli-service": "^3.4.1"库:vue2,具体为:"vue": "2.6.12"备注:没有 typescript , 非 ssr痛点:随着工夫的推移、业务的一直迭代,依赖、性能、代码越来越多,我的项目本地启动比较慢、开发热更新比较慢。 改良指标:保留原来的 webpack, 反对 vite。并且尽可能的缩小改变,缩小保护老本。 思考: vite 生产环境用的是 rollup,rollup 更适宜打包库。vite 打包提效并没有进步太多。保留原来的 webpack 形式,尽可能的保障生产的稳固与平安。实际次要是解决三方面: 配置文件需依据 vue.config.js 减少 vite.config.js入口文件 index.html 反对 vite 的形式配置 vite 启动命令可能须要 路由懒加载,vite 须要非凡解决解决 commonjs 与 esModule 的引入与混用减少 vite.config.js在我的项目根目录创立一个 vite.config.js 装置所需依赖 npm i vite vite-plugin-vue2 -D依据 vue.config.js 在 vite.config.js 中减少对应配置 // 若改了该文件逻辑,请对照着改一下 vue.config.jsimport path from 'path'import fs from 'fs'import { defineConfig } from 'vite'import config from './config'import { createVuePlugin } from 'vite-plugin-vue2'import { injectHtml } from 'vite-plugin-html'const resolve = dir => path.join(__dirname, dir)const alias = { vue: 'vue/dist/vue.esm.js', '@': resolve('src'),}const publicPath = '/'const mode = 'development'// https://vitejs.dev/config/export default defineConfig({ base: publicPath, plugins: [ createVuePlugin(), ], // 这些是注入我的项目中的变量,若有 process 结尾的,都须要在这儿注入,vite 默认不会注入 process 相干的变量及值 define: { 'process.env.NODE_ENV': JSON.stringify(mode), 'process.env.publicPath': JSON.stringify(publicPath), }, resolve: { // 配置别名 alias, // 导入时想要省略的扩展名列表,必须退出.vue,因为 vite 默认不反对省略 .vue 后缀 extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'] }, server: { // 容许跨域 cors: true, proxy: { // 可间接拷贝 vue.config.js 中对应的 proxy } }})sass 相干配置非凡阐明:若我的项目中有用是 sass 预处理器, 且用到变量了。 ...

December 19, 2021 · 4 min · jiezi

关于vue.js:VUE-30-源码-scriptsverifyCommitjs-文件-对git提交时输入的描述信息进行规范

文件门路:VUE 3.0 源码 scripts/verifyCommit.js 当咱们在命令行敲下 git commit -m "形容信息" 提交代码时,此文件会被触发,要害的配置信息还是在 package.json 这个文件中,具体如下: 知识点-1:如何拿到咱们输出的形容信息? 答案-1:通过 process.env.GIT_PARAMS 读取到git保留形容信息的文件,个别门路如下:.git/COMMIT_EDITMSG 知识点-2:输出形容信息的格局是怎么把控呢? 答案-2:通过 一个看起来很NB然而很容易了解的一个正则表达式实现的,具体如下: /^(revert: )?(feat|fix|docs|dx|style|refactor|perf|test|workflow|build|ci|chore|types|wip|release)(\(.+\))?: .{1,50}/大略分为以下3局部: (1) 结尾固定关键字 - 用于标识此次提交的概括信息: revert|feat|fix|docs|dx|style|refactor|perf|test|workflow|build|ci|chore|types|wip|release (2)括号+冒号+空格 (括号内个别形容批改模块的名称) --> fix(模块名):_ (3)输出一些形容信息 这句正则感觉意义不是太大 .{1,50} 正则小数点 . : 能够匹配除了换行符(/n)以外的任意一个字符正则{m,n} : 表达式至多反复m次,最多反复n次,比方:"ba{1,3}"能够匹配 "ba"或"baa"或"baaa"具体源码如下: // Invoked on the commit-msg git hook by yorkie./** 控制台日志标注款式 */const chalk = require('chalk')/** * 通过 GIT_PARAMS 读取到保留 git commit 时输出的形容信息的文件目录,个别门路如下:.git/COMMIT_EDITMSG */const msgPath = process.env.GIT_PARAMS/** 读取.git/COMMIT_EDITMSG文件信息 */const msg = require('fs') .readFileSync(msgPath, 'utf-8') .trim()/** * 校验提交信息格式 * 示例:fix(runtime-core): check if the key is string on undefined property warning (#1731) * part1 - 结尾关键字:revert|feat|fix|docs|dx|style|refactor|perf|test|workflow|build|ci|chore|types|wip|release * part2 - 括号+冒号+空格 (括号内个别形容批改模块的名称) * part3 - 输出一些形容信息 .{1,50} */const commitRE = /^(revert: )?(feat|fix|docs|dx|style|refactor|perf|test|workflow|build|ci|chore|types|wip|release)(\(.+\))?: .{1,50}/if (!commitRE.test(msg)) { console.log() console.error( ` ${chalk.bgRed.white(' ERROR ')} ${chalk.red( `invalid commit message format.` )}\n\n` + chalk.red( ` Proper commit message format is required for automated changelog generation. Examples:\n\n` ) + ` ${chalk.green(`feat(compiler): add 'comments' option`)}\n` + ` ${chalk.green( `fix(v-model): handle events on blur (close #28)` )}\n\n` + chalk.red(` See .github/commit-convention.md for more details.\n`) ) process.exit(1)}如果您对 “前端源码” 情有独钟,能够微信扫码关注上面的公众号二维码,内容始终继续更新中!以后 VUE3.0 源码正在解析中,欢送捧场! ...

December 18, 2021 · 1 min · jiezi

关于vue.js:shopro商城国际化之多组件

多组件用来解决切换语言css的问题,具体请看代码 mounted() { if (uni.getStorageSync('locale')) { this.locale = uni.getStorageSync('locale'); this.$i18n.locale = uni.getStorageSync('locale') } else { this.locale = 'zh-cn'; this.$i18n.locale = 'zh-cn' } },

December 18, 2021 · 1 min · jiezi

关于vue.js:vuei18n国际化之css国际化

这两天在搞一个商城国际化的我的项目,期间解决了N个问题吧例如 vue中国际化 js中国际化接口内容国际化等等,明天次要说的就是css中内容的国际化看图: after css这里的 个 张 元 应用 css3 after追加进去的,咱们晓得after 其实就是在前面追加一个行内元素而已,那么我咱们就把这段css提取进去换成等价的代码即可拉这里咱们应用<text></text>来替换拉,完满解决此问题 <template> <!-- 钱包卡片 --> <view class="sh-wallet-box u-flex u-m-b-10 u-p-r-20"> <view class="u-flex wallet-left"> <view class="wallet-item u-flex-col u-col-center" @tap="jump('/pages/user/wallet/index')"> <text class="wallet-item__detail item-balance u-ellipsis-1">{{ userInfo.money || '0' }}<text style="font-size: 16rpx;margin-left: 4rpx;">{{userLocale.yuan}}</text></text> <text class="wallet-item__title">{{userLocale.zhanghuyuer}}</text> </view> <view class="wallet-item u-flex-col u-col-center" @tap="jump('/pages/user/wallet/score-balance')"> <text class="wallet-item__detail item-score u-ellipsis-1">{{ userInfo.score || '0' }}<text style="font-size: 14rpx;margin-left: 4rpx;">{{userLocale.ge}}</text></text> <text class="wallet-item__title">{{userLocale.jifen}}</text> </view> <view class="wallet-item u-flex-col u-col-center" @tap="jump('/pages/app/coupon/list')"> <text class="wallet-item__detail item-coupon u-ellipsis-1">{{ userOtherData.coupons_num || '0' }}<text style="font-size: 16rpx;margin-left: 4rpx;">{{userLocale.zhang}}</text></text> <text class="wallet-item__title">{{userLocale.youhuiquan}}</text> </view> </view> <view class="wallet-item u-flex-col wallet-right u-col-center" @tap="jump('/pages/user/wallet/index')"> <image class="cut-off--line" :src="$IMG_URL + '/imgs/user/cut_off_line.png'" mode=""></image> <image class="wallet-img" :src="$IMG_URL + '/imgs/user/wallet.png'" mode="aspectFill"></image> <text class="wallet-item__title">{{userLocaleqianbao}}</text> </view> </view></template>

December 18, 2021 · 1 min · jiezi

关于vue.js:我是如何把vue项目启动时间从70s优化到7秒的

可怕的启动工夫公司的产品是一个比拟大的后盾管理系统,而且应用的是webpack3的vue模板我的项目,单次我的项目启动工夫达到了70s左右 启动个我的项目都够吃一碗豆腐脑了,可是没有豆腐脑怎么办,那就优化启动工夫吧! 思考到降级webpack版本的危险还是比拟大的,出了一点问题都得找我,想想还是先别冒险,稳当为主,所以我抉择了通过插件来优化构建工夫。 通过查阅材料,晋升webpack的构建工夫有以下几个方向: 多过程解决文件,同一时间解决多个文件预编译资源模块,比方把长时间不变的库提取进去做预编译,构建的时候间接取编译后果就好缓存,未修改的模块间接拿到处理结果,不用编译缩小构建搜寻和解决的文件数量针对以上几种优化方向,给出以下几种优化计划。 多过程构建happypackhappypack 的作用就是将文件解析工作分解成多个子过程并发执行。 子过程解决完工作后再将后果发送给主过程。所以能够大大晋升 Webpack 的我的项目构件速度。 查看happypack的github,发现作者曾经不再保护该插件,并且作者举荐应用webpack官网的多过程插件thread-loader,所以我放弃了happypacy,抉择了thread-loader。 thread-loaderthread-loader是官网保护的多过程loader,性能相似于happypack,也是通过开启子工作来并行解析文件,从而进步构建速度。 把这个loader放在其余loader后面。不过该loader是有限度的。示例: loader无奈收回文件。loader不能应用自定义加载器API。loader无法访问网页包选项。每个worker都是一个独自的node.js过程,其开销约为600毫秒。还有过程间通信的开销。在小型我的项目中应用thread-loader可能并不能优化我的项目的构建速度,反而会拖慢构建速度,所以应用该loader时须要明确我的项目构建形成中真正耗时的过程。 我的我的项目中我次要是用该loader用来解析vue和js文件,作用于vue-loader和babel-loader,如下代码: const threadLoader = { loader: 'thread-loader', options: { workers: require('os').cpus().length - 1,}} module.exports = { module:{ rules: [ { test: /\.vue$/, use: [ threadLoader, // vue-loader前应用该loader { loader: 'vue-loader', options: vueLoaderConfig } ], }, { test: /\.js$/, use: [ threadLoader, // babel-loader前应用该loader { loader: 'babel-loader', options: { cacheDirectory: true } } ] }]}} 复制代码配置了thread-loader后,从新构建试试,如下图所示,大略缩短了10秒的构建工夫,还不错。 ...

December 17, 2021 · 2 min · jiezi

关于vue.js:详解虚拟DOM与Diff算法

最近温习到虚构DOM与Diff,翻阅了泛滥材料,特此总结了这篇长文,加深本人对vue的了解。这篇文章比拟具体的剖析了vue的虚构DOM,Diff算法,其中一些要害的中央从别处搬运了一些图进行阐明(感激制图的大佬),也蕴含比拟具体的源码解读。 实在DOM的渲染在讲虚构DOM之前,先说一下实在DOM的渲染。 浏览器实在DOM渲染的过程大略分为以下几个局部 构建DOM树。通过HTML parser解析解决HTML标记,将它们构建为DOM树(DOM tree),当解析器遇到非阻塞资源(图片,css),会持续解析,然而如果遇到script标签(特地是没有async 和 defer属性),会阻塞渲染并进行html的解析,这就是为啥最好把script标签放在body上面的起因。构建CSSOM树。与构建DOM相似,浏览器也会将款式规定,构建成CSSOM。浏览器会遍历CSS中的规定集,依据css选择器创立具备父子,兄弟等关系的节点树。构建Render树。这一步将DOM和CSSOM关联,确定每个 DOM 元素应该利用什么 CSS 规定。将所有相干款式匹配到DOM树中的每个可见节点,并依据CSS级联确定每个节点的计算款式,不可见节点(head,属性包含 display:none的节点)不会生成到Render树中。布局/回流(Layout/Reflow)。浏览器第一次确定节点的地位以及大小叫布局,如果后续节点地位以及大小发生变化,这一步触发布局调整,也就是 回流。绘制/重绘(Paint/Repaint)。将元素的每个可视局部绘制到屏幕上,包含文本、色彩、边框、暗影和替换的元素(如按钮和图像)。如果文本、色彩、边框、暗影等这些元素发生变化时,会触发重绘(Repaint)。为了确保重绘的速度比初始绘制的速度更快,屏幕上的绘图通常被分解成数层。将内容晋升到GPU层(能够通过tranform,filter,will-change,opacity触发)能够进步绘制以及重绘的性能。合成(Compositing)。这一步将绘制过程中的分层合并,确保它们以正确的程序绘制到屏幕上显示正确的内容。为啥须要虚构DOM下面这是一次DOM渲染的过程,如果dom更新,那么dom须要从新渲染一次,如果存在上面这种状况 <body> <div id="container"> <div class="content" style="color: red;font-size:16px;"> This is a container </div> .... <div class="content" style="color: red;font-size:16px;"> This is a container </div> </div></body><script> let content = document.getElementsByClassName('content'); for (let i = 0; i < 1000000; i++) { content[i].innerHTML = `This is a content${i}`; // 触发回流 content[i].style.fontSize = `20px`; }</script>那么须要实在的操作DOM100w次,触发了回流100w次。每次DOM的更新都会依照流程进行无差别的实在dom的更新。所以造成了很大的性能节约。如果循环外面是简单的操作,频繁触发回流与重绘,那么就很容易就影响性能,造成卡顿。另外这里要阐明一下的是,虚构DOM并不是意味着比DOM就更快,性能须要分场景,虚构DOM的性能跟模板大小是正相干。虚构DOM的比拟过程是不会辨别数据量大小的,在组件外部只有大量动静节点时,虚构DOM仍然是会对整个vdom进行遍历,相比间接渲染而言是多了一层操作的。 <div class="list"> <p class="item">item</p> <p class="item">item</p> <p class="item">item</p> <p class="item">{{ item }}</p> <p class="item">item</p> <p class="item">item</p> </div>比方下面这个例子,虚构DOM。尽管只有一个动静节点,然而虚构DOM仍然须要遍历diff整个list的class,文本,标签等信息,最初仍然须要进行DOM渲染。如果只是dom操作,就只有操作一个具体的DOM而后进行渲染。虚构DOM最外围的价值在于,它能通过js形容实在DOM,表达力更强,通过申明式的语言操作,为开发者提供了更加方便快捷开发体验,而且在没有手动优化,大部分情景下,保障了性能上限,性价比更高。 ...

December 17, 2021 · 6 min · jiezi

关于vue.js:vuex-store-进阶

背景:vuex store的进阶版 实用于大型简单的单页利用用处:数据管理 state 相似于 data存储全局状态值,当扭转值会触发dom更新, 应用时挂载在子组件的computed计算属性上(这样的目标是为了实时更新) mapState gettersgetters 能够返回一个值(属性),也可返回一个办法函数 拜访办法时 每次进行调用 不会缓存后果拜访属性时 作为vue响应式零碎的一部分缓存起来mapGetters --辅助函数将store中的getter映射到部分计算属性,即 定义getter后 在总的vuex去注入这个getter 从而在全局进行应用 mutations用于更改store中的状态值 蕴含一个事件类型和一个回调函数 不反对异步 mutations: { increment (state, n) { state.count += n }}store.commit('increment', 10)// 以对象模式传参mutations: { increment (state, payload) { state.count += payload.amount }}// amount相当于传入参数store.commit('increment', { amount: 10})actions相似于mutations 反对异步 通过 store.dispatch 触发 actions: { incrementAsync ({ commit }) { setTimeout(() => { commit('increment') }, 1000) }}// 两种模式散发调用store.dispatch('incrementAsync', { amount: 10})store.dispatch({ type: 'incrementAsync', amount: 10})mapActions在组件中应用 this.$store.dispatch('xxx') 散发 action,或者应用 mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用(须要先在根节点注入 store) ...

December 17, 2021 · 2 min · jiezi

关于vue.js:聊一聊vue插槽

插槽存在的意义父组件中定义插槽 自组件中应用 显示由父组件决定 插槽分为 3 种匿名插槽/具名插槽/作用域插槽 匿名插槽(默认插槽)顾名思义,没有名字的插槽 具名插槽:带有 slot="xxx" 的 div 作用域插槽:带有 slot-scope="xxxx" 欢送补充~~

December 17, 2021 · 1 min · jiezi

关于vue.js:Vue生命周期详解

Vue生命周期详解Vue的生命周期,指的是Vue实列中创立产生到被销毁的整个过程所经验的状态 Vue共有11个生命状态:8个常见和3个后减少的 Vue生命周期共有8个钩子函数,罕用的有4个 第一阶段:初始阶段1.创立Vue实列,此时只是创立还没有开始,生命处于胚芽状态 1.生命处于胚芽状态2.初始化Vue实列及外部的很多事件,筹备中的胚芽的活性蛋白开始沉闷(筹备工作),生命周期就这样开始了 2.筹备中的胚芽的活性蛋白开始沉闷(筹备工作),生命周期就这样开始了 诞生了 — 钩子函数:beforeCreate 3.初始化,将data中的数据挂载到Vue实列上,并实现双向绑定(数据劫持),当初能够拜访到Vue外面的数据(Vue有了数据) 3.胚芽冲破细胞壁,通过缝隙([Object.defineProperty]),开始发芽(数据) 诞生了 — 钩子函数:created,这个阶段不操作元素和节点,仅仅操作数据,通常咱们会在这个阶段调用办法,发送申请,将申请回来的数据放到data定义的数据中。 4.查看是否有el 4.嫩芽向上成长,查看此地的阳光(el)是否适合5.如果没有el,期待Vue实列调用$mount来传入el参数 5.如果阳光不好,那就另寻他处(调用$mount),但通常状况下不须要另寻他处(调用$mount)6.有el判断是不是传递template参数 6.嫩芽发现有了阳光,开始探测此地土地是否肥沃(template参数),但通常土壤并不肥沃(template参数)7.如果有template参数,将template参数编译成渲染函数,联合html和js创立整体构造,如果没有也不影响,将el参数的outerhtml编译成一个整体 7.嫩芽通过探查做出了判断,如果肥沃(template参数)致力排汇营养能抽出两片嫩芽(,联合html和js创立整体构造),如果一般能抽出一片嫩芽(将el参数的outerHTML编译成一个整体) 诞生了 — 钩子函数:beforeMount 8.搭建好的构造,放在Vue实例的$el属性中,并用这个构造替换掉el参数 8.新成长的叶子 替换掉旧的叶子(替换掉el参数),嫩芽成长为一朵小花 诞生了 — 钩子函数:mounted 挂载结束的时候调用,页面中的标签构造加载实现了。 此时,在这个阶段能够操作页面中的DOM标签了。 留神:这个钩子函数在整个生命周期中只会调用一次。 第二阶段:Vue的更新阶段 - 两个小阶段循环执行9.在页面显示最终内容,这里造成一个死循环,期待数据的变动 9.小花一直的成长,新叶一直代替旧叶(死循环),期待开花的那天(期待数据的变动) 诞生了 — 钩子函数:beforeUpdate 10.数据产生扭转,从新渲染页面的构造和内容,并依据更改内容晓得那局部内容 10.到了开花的这天(数据产生扭转),通过传粉笼罩(从新渲染页面的构造和内容)雌蕊取得信息素判断传得粉,从而判断是否后果(更改内容晓得那局部内容) 诞生了 — 钩子函数:updated 依据新批改的数据从新渲染完页面后调用。能够获取到新数据,能够获取到新的DOM。 第三阶段:Vue的销毁阶段11.期待vm.$destroy办法调用 11.果子接完了,期待进入秋天(期待vm.$destroy办法调用) 诞生了 — 钩子函数:beforeDestroy 实例销毁之前调用。在这一步,实例依然齐全可用。 12.调用后卸载vue中所有的监听:包含数据监听,页面构造监听、其余事件监听。。。 12.进入秋天,叶子全副脱落,开始缓缓的凋零(卸载vue中所有的监听) 诞生了 — 钩子函数:destroyed Vue 实例批示的所有货色都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。 13.Vue实例销毁

December 16, 2021 · 1 min · jiezi

关于vue.js:基于Vue3ViteTS二次封装elementplus业务组件agsa

download:基于Vue3+Vite+TS,二次封装element-plus业务组件python字符串/元组/列表/字典互转 --coding:utf-8--1、字典dict = {'name': 'Zara', 'age': 7, 'class': 'First'} 字典转为字符串,返回:<type 'str'> {'age': 7, 'name': 'Zara', 'class': 'First'}print type(str(dict)), str(dict) 字典可能转为元组,返回:('age', 'name', 'class')print tuple(dict) 字典可能转为元组,返回:(7, 'Zara', 'First')print tuple(dict.values()) 字典转为列表,返回:['age', 'name', 'class']print list(dict) 字典转为列表print dict.values 2、元组tup=(1, 2, 3, 4, 5) 元组转为字符串,返回:(1, 2, 3, 4, 5)print tup.__str__() 元组转为列表,返回:[1, 2, 3, 4, 5]print list(tup) 元组不可能转为字典3、列表nums=[1, 3, 5, 7, 8, 13, 20]; 列表转为字符串,返回:[1, 3, 5, 7, 8, 13, 20]print str(nums) 列表转为元组,返回:(1, 3, 5, 7, 8, 13, 20)print tuple(nums) ...

December 16, 2021 · 1 min · jiezi

关于vue.js:10个常见的前端手写功能你全都会吗

万丈高楼平地起,地基打的牢,能力永远立于不败之地。明天给大家带来的是10个常见的 JavaScript 手写性能,重要的中央已增加正文。有的是借鉴他人的,有的是本人写的,如有不正确的中央,欢送多多斧正。 1、防抖function debounce(fn, delay) { let timer return function (...args) { if (timer) { clearTimeout(timer)}timer = setTimeout(() => { fn.apply(this, args)}, delay)}} // 测试function task() { console.log('run task')}const debounceTask = debounce(task, 1000)window.addEventListener('scroll', debounceTask)复制代码2、节流function throttle(fn, delay) { let last = 0 // 上次触发工夫 return (...args) => { const now = Date.now()if (now - last > delay) { last = now fn.apply(this, args)}}} // 测试function task() { console.log('run task')}const throttleTask = throttle(task, 1000)window.addEventListener('scroll', throttleTask)复制代码3、深拷贝function deepClone(obj, cache = new WeakMap()) { if (typeof obj !== 'object') return obj // 一般类型,间接返回 if (obj === null) return obj if (cache.get(obj)) return cache.get(obj) // 避免循环援用,程序进入死循环 if (obj instanceof Date) return new Date(obj) if (obj instanceof RegExp) return new RegExp(obj) ...

December 16, 2021 · 4 min · jiezi

关于vue.js:VUE-30-源码阅读-注释-解读-tsconfigjson-各项配置信息

本文通过对VUE源码中的 tsconfig.json 文件中的每个属性做具体解释,使读者对罕用的配置信息做进一步的理解,心愿对看到此篇文章的读者有所帮忙。 { "compilerOptions": { /* * 用于拓宽引入非绝对模块时的查找门路的。其默认值就是"./" * 目标是解决我的项目代码层级较深相互之间援用起来会比拟麻烦的问题,各种 …/,…/…/,…/…/…/ 等等 * "paths": { * "@vue": ["packages/vue/src"] * } */ "baseUrl": ".", /* 指定输入目录 */ "outDir": "dist", /* * 是否生成指标文件的sourceMap文件 * 此文件容许调试器和其余工具在理论应用收回的JavaScript文件时显示原始的TypeScript源代码。 * 此文件为 .js.map (or .jsx.map) 格局,位于相应的.js 输入文件雷同目录 */ "sourceMap": false, /* * 定义了编译后的指标 javascript 版本, 可抉择包含es6、es5、esnext * 如果须要思考兼容性问题就能够设置为es5或更低的版本,一般来说,咱们须要让他编译为 es5,这样就能够被支流浏览器解读了。 * 当然,你说我的 react 代码不是给浏览器看的,比如说,你应用的是 react-native 做作手机 app,那么这里的选项能够抉择 es6。 * 如果代码是在高版本的古代浏览器或高版本的node端,就能够设置为esnext */ "target": "esnext", /* * 通知编译器对收回的.js文件中的模块应用什么语法。可抉择 none、commonjs、amd、system、umd、es2015或esnext * 通知编译器以哪种语法编写代码,意味着必须从哪个代码将其编译为commonjs。 * 如果用于服务器端我的项目 如果应用的是Angular前端应用程序,则应用Node.js,而后可能应用CJS 可能不是ESM * 较新的JS版本有时蕴含用于模块导入/导出的更多功能。 将export设置为"module"能够反对这些性能,而这些性能通常尚未增加到官网标准中。例如dynamic import的"ESNext"表达式。 * 无论如何,编译器的目标是将代码编译成浏览器可了解的语法(commonjs) * module影响收回代码的模块语法,而target影响其余代码 */ "module": "esnext", /* * 模块解析策略,ts默认用node的解析策略,即绝对的形式导入, 可选值:node、classic * 如果未指定,则 --module commonjs 默认为 node,否则默认为 classic(包含 --module 设置为 amd、system、umd、es2015、esnext 等) * Node 模块解析是 TypeScript 社区中最罕用的,举荐用于大多数我的项目。 * 如果您在 TypeScript 中遇到导入和导出的解析问题,请尝试设置 moduleResolution: “node” 以查看它是否解决了问题。 */ "moduleResolution": "node", /* * 容许在 TS 我的项目中导入JavaScript文件,而不是仅导入.ts和.tsx文件。即容许ts和tsx文件与现有JavaScript文件共存 * 例如js文件 @filename: card.js: export const defaultCardDeck = "Heart"; * ts文件 @filename: index.ts 中引入下面的js变量:import { defaultCardDeck } from "./card"; * 如果 allowJs 设置为 false, 将会抛出谬误。 */ "allowJs": false, /* * 开启所有严格的类型查看 * true => 同时开启 alwaysStrict, noImplicitAny, noImplicitThis 和 strictNullChecks * alwaysStrict:严格模式,为每个文件增加 "use strict" * noImplicitAny:不容许隐式 any,如果true,函数的形参必须带类型,如果叫不出class名的js对象,那就得any。比方(d:any)=>{};如果false, 则容许隐式any,函数的样子更像js (d)=>{} * noImplicitThis:不容许 this 为隐式 any * strictNullChecks:undefined 和 null 两个空类型的设计,应用上不不便,所以 通过strictNullChecks严格校验类型,让代码更平安 */ "strict": true, /* 查看只申明、未应用的局部变量(只提醒不报错) */ "noUnusedLocals": true, /** * 是否启用实验性的装璜器个性,装璜器的语法是ES7的实验性语法, 不关上可能会呈现如下谬误: * Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option to remove this warning. */ "experimentalDecorators": true, /** * 避免 ts文件中引入json文件,会报如下红色波浪线。 * TypeScript 2.9的resolveJsonModule性能,只有我应用ts-node执行应用程序,该性能就能够失常工作 */ "resolveJsonModule": true, /* 作用是反对应用import d from 'cjs'的形式引入commonjs包 */ "esModuleInterop": true, /* 用于指定是否将编译后的文件正文删掉,设为true的话即删除正文,默认为false */ "removeComments": false, /** * 指定jsx代码用于的开发环境: 'preserve', 'react-native', or 'react' * preserve:生成代码中会保留JSX以供后续的转换操作应用(比方:Babel).另外,输入文件会带有.jsx扩展名。 * react:会生成React.createElement,在应用前不须要再进行转换操作了,输入文件的扩大名为.js。 * react-native:相当于preserve,它也保留了所有的JSX,然而输入文件的扩展名是.js */ "jsx": "preserve", /* * 编译过程中须要引入的库文件的列表,通知 typescript 编译器能够应用哪些性能。 * 比如说,咱们这里有一个 dom 的库文件,这个文件会通知编译器 dom api 的接口,所以当咱们在 ts 代码中应用 dom 的时候,比如说执行 “document.getElementById ("root")” 这句话的时候,编译器就会晓得该如何进行查看。 * 如果咱们不设置这个选项,那么编译器也有本人默认的库文件列表,一般来说是 ["dom", "es6","DOM.Iterable"] 等等 */ "lib": ["esnext", "dom"], /* 用于指定须要蕴含的模块,只有在这里列出的模块的申明文件才会被加载 */ "types": ["jest", "puppeteer", "node"], /** * 用来指定编译文件的根目录,编译器会在根目录查找入口文件, * 如果编译器发现以rootDir的值作为根目录查找入口文件,并不会把所有文件加载进去的话会报错,然而不会进行编译 */ "rootDir": ".", /* 用于设置模块名称到基于baseUrl的门路映射 */ "paths": { "@vue/*": ["packages/*/src"], "vue": ["packages/vue/src"] } }, /** * include 用于指定要编译的门路列表,然而和files的区别在于,这里的门路能够是文件夹, * 也能够是文件,能够应用绝对和绝对路径,而且能够应用通配符, * 比方"./src"即示意要编译src文件夹下的所有文件以及子文件夹的文件 */ "include": [ "packages/global.d.ts", "packages/*/src", "packages/runtime-dom/types/jsx.d.ts", "packages/*/__tests__", "test-dts" ]}

December 16, 2021 · 2 min · jiezi

关于vue.js:VUEX的store用法

从新搭建我的项目进入以个文件夹:cd vuewebpackapp初始化这个我的项目:vue init webpack vuexapp一系列的抉择确认后就会创立好文件在搭建好的环境中操作父组件传递数据给子组件在components新建parent.vue(父组件)和一个son.vue子组件;在父组件内引入子组件import son from './son',并传msg给子组件 子组件如何接管父组件传递的内容: helloworld.vue子组件传数据给父组件父组件从子组件接收数据,如何设置 子组件向父组件传递数据在子组件设置按钮 在父组件里接管 渲染在页面上 VUEX的作用?例如关上淘宝下面有很多不同的界面和组件,然而每一个组件都晓得我的登录状态,就是用vuex来实现的 用来治理状态,共享数据,在各个组件之间治理内部状态,如何应用?第一步:引入vuex,通过use办法应用它;第二步:创立状态仓库;第三步:通过this.$store.state.xxx间接拿到须要的数据//创立状态仓库var store = new Vuex.Store({ state:{XXX:xxx}})//间接通过this.$store.xxx拿到全局状态复制代码新建outter.vueoutter文件和parent和son文件,没有父子关系,然而又想让他们之间共享数据,就用到vuex文件;在终端装置:npm i vuex在main.js中引入Vuex:import Vuex from 'vuex'接着在main.js中use一下:Vue.use(Vuex)创立状态仓库var store = new Vuex.store({ state:{ num:88 } }) 在son.vue文件中如何获取文件? 把这个计算属性渲染到页面上: 在父组件中的代码与子组件相似,只是getNum换成getCount在outter中 也是一样 三个组件都拿到了Num:88,实现了资源共享。 最初如果你感觉此文对你有一丁点帮忙,点个赞。或者能够退出我的开发交换群:1025263163互相学习,咱们会有业余的技术答疑解惑 如果你感觉这篇文章对你有点用的话,麻烦请给咱们的开源我的项目点点star: https://gitee.com/ZhongBangKe...不胜感激 !

December 15, 2021 · 1 min · jiezi

关于vue.js:vite系列手写一个简易版的vite依赖预构建版本

之前咱们曾经实现了一个不带依赖预构建版本的vite, 在vite2.0中减少了一个代表性优化策略 依赖预构建明天咱们也来手写一个。 咱们要实现的性能如下图所示: 依赖预构建性能实现对SFC的解析实现对vue3语法的解析实现对html和js的解析最初实现一个对数字的加减操作性能代码分两局部 依赖预构建局部本地服务局部先开始编写依赖预构建局部 先把所须要的依赖引入 const http = require('http');const path = require('path');const url = require('url');const querystring = require('querystring');const glob = require('fast-glob'); // 在规定范畴内查问指定的文件,并返回绝对路径const { build } = require('esbuild'); // 打包编译esm模块const fs = require('fs');const os = require('os'); // 获取以后的零碎信息const { createHash } = require('crypto'); // 加密应用const { init, parse } = require('es-module-lexer'); // 查问出代码中应用import局部信息const MagicString = require('magic-string');// 替换代码中门路const compilerSfc = require('@vue/compiler-sfc');// 将sfc转化为json数据const compilerDom = require('@vue/compiler-dom');// 将template转化为render函数编写依赖预构建主函数 async function optimizeDeps() { // 第一步:设置缓存存储的地位 let cacheDir = 'node_modules/.vite'; const dataPath = path.join(cacheDir, '_metadata.json'); const mainHash = getDepHash(); const data = { hash: mainHash, browserHash: mainHash, optimized: {}, }; if (fs.existsSync(dataPath)) { let prevData; try { // 解析.vite下的_metadata.json文件 prevData = JSON.parse(fs.readFileSync(dataPath, 'utf-8')); } catch (error) { console.log(error); } // 哈希是统一的,不须要从新绑定 if (prevData && prevData.hash === data.hash) { return prevData; } } if (fs.existsSync(cacheDir)) { // 如果node_modules/.vite这个文件存在则清空.vite下的所有文件 emptyDir(cacheDir); } else { fs.mkdirSync(cacheDir, { recursive: true }); } // 第二步:收集依赖模块门路 const { deps, missing } = await scanImports(); // { // 'vue': ''C:\\Users\\dftd\\desktop\\vite\\node-vue\\node_modules\\vue\\dist\\vue.runtime.esm-bundler.js'' // } console.log('deps', deps); // update browser hash data.browserHash = createHash('sha256') .update(data.hash + JSON.stringify(deps)) .digest('hex') .substr(0, 8); const qualifiedIds = Object.keys(deps); // 如果没有找到任何依赖,那么间接把data数据写入.vite/_metadata.json if (!qualifiedIds.length) { fs.writeFileSync(dataPath, data); return data; } // 第三步: 对收集的依赖进行解决 // 比方deps的数据是 { 'plamat/byte': 'C:\\Users\\dftd\\node_modules\\vue\\dist\\byte.js' } const flatIdDeps = {}; // 这个对象存储的是 { plamat_byte: 'path' } 的模式 const idToExports = {}; // 这个对象存储的是{ plamat/byte: 'souce'} 的模式 const flatIdToExports = {}; // 这个对象存储的是{ plamat/byte: 'souce'} 的模式 await init; // 将 例如 node/example ==> node_example const flattenId = (id) => id.replace(/[\/\.]/g, '_'); for (const id in deps) { const flatId = flattenId(id); flatIdDeps[flatId] = deps[id]; const entryContent = fs.readFileSync(deps[id], 'utf-8'); const exportsData = parse(entryContent); for (const { ss, se } of exportsData[0]) { const exp = entryContent.slice(ss, se); if (/export\s+\*\s+from/.test(exp)) { exportsData.hasReExports = true; } } idToExports[id] = exportsData; flatIdToExports[flatId] = exportsData; } const define = { 'process.env.NODE_ENV': 'development', }; console.log('flatIdDeps', flatIdDeps); function esbuildVitePlugin(flatIdDeps) { return { name: 'vite-scan', setup(build) { build.onResolve({ filter: /\*/ }, (args) => { console.log('打印后果', args); }); }, }; } const result = await build({ absWorkingDir: process.cwd(), // entryPoints: Object.keys(flatIdDeps), entryPoints: Object.values(flatIdDeps), bundle: true, format: 'esm', outdir: cacheDir, // 配置打完包的文件存储的地位 cacheDir默认为 treeShaking: true, metafile: true, define, // plugins: [esbuildVitePlugin(flatIdDeps)], }); // console.log('result', result); const metafile = result.metafile; // 将 _metadata.json 写入 .vite const cacheDirOutputPath = path.relative(process.cwd(), cacheDir); // console.log(cacheDirOutputPath); for (const id in deps) { // p ==> C:\Users\dftd\desktop\vite\node-vue\node_modules\.vite\vue.js // normalizePath(p) ==> C:/Users/dftd/desktop/vite/node-vue/node_modules/.vite/vue.js const p = path.resolve(cacheDir, flattenId(id) + '.js'); const entry = deps[id]; data.optimized[id] = { file: normalizePath(p), src: normalizePath(entry), needsInterop: false, }; } fs.writeFileSync(dataPath, JSON.stringify(data, null, 2)); return data;}function normalizePath(id) { const isWindows = os.platform() === 'win32'; return path.posix.normalize(isWindows ? id.replace(/\\/g, '/') : id);}// 将此我的项目的xxx.lock.json文件和局部vite配置内容生成一个hashfunction getDepHash() { // 读取xxx.lock.json文件的内容 const content = lookupFile() || ''; const cryptographicStr = createHash('sha256') .update(content) .digest('hex') .substring(0, 8); return cryptographicStr;}// 读取xxx.lock.json文件的内容function lookupFile() { const lockfileFormats = ['package-lock.json', 'yarn.lock', 'pnpm-lock.yaml']; let content = null; for (let index = 0; index < lockfileFormats.length; index++) { const lockPath = path.resolve(__dirname, lockfileFormats[index]); const isExist = fs.existsSync(lockPath, 'utf-8'); if (isExist) { content = fs.readFileSync(lockPath); break; } } // for (const index of lockfileFormats) { // console.log(index); // const lockPath = path.resolve(__dirname, index); // const isExist = fs.existsSync(lockPath, 'utf-8'); // if (isExist) { // content = fs.readFileSync(lockPath); // return content; // } // } return content;}function emptyDir(dir) { for (const file of fs.readdirSync(dir)) { const abs = path.resolve(dir, file); if (fs.lstatSync(abs).isDirectory()) { emptyDir(abs); fs.rmdirSync(abs); } else { fs.unlinkSync(abs); } }}// esbuild pluginfunction esbuildScanPlugin(deps) { return { name: 'dep-scan', setup(build) { // 解析index.html build.onResolve({ filter: /\.(html|vue)$/ }, (args) => { // console.log(args); // const path1 = path.resolve(__dirname, args.path); return { path: args.path, namespace: 'html', }; }); // 加载以后index.html 文件 返回出 main.js build.onLoad( { filter: /\.(html|vue)$/, namespace: 'html' }, async ({ path: ids }) => { const scriptModuleRE = /(<script\b[^>]*type\s*=\s*(?:"module"|'module')[^>]*>)(.*?)<\/script>/gims; const srcRE = /\bsrc\s*=\s*(?:"([^"]+)"|'([^']+)'|([^\s'">]+))/im; const langRE = /\blang\s*=\s*(?:"([^"]+)"|'([^']+)'|([^\s'">]+))/im; const scriptRE = /(<script\b(?:\s[^>]*>|>))(.*?)<\/script>/gims; const importsRE = /(?:^|;|\*\/)\s*import(?!\s+type)(?:[\w*{}\n\r\t, ]+from\s*)?\s*("[^"]+"|'[^']+')\s*(?:$|;|\/\/|\/\*)/gm; let raw = fs.readFileSync(ids, 'utf-8'); raw = raw.replace(/<!--(.|[\r\n])*?-->/, '<!---->'); const isHtml = ids.endsWith('.html'); const regex = isHtml ? scriptModuleRE : scriptRE; regex.lastIndex = 0; let js = ''; let loader = 'js'; let match; while ((match = regex.exec(raw))) { const [, openTag, content] = match; const srcMatch = openTag.match(srcRE); const langMatch = openTag.match(langRE); const lang = langMatch && (langMatch[1] || langMatch[2] || langMatch[3]); if (lang === 'ts' || lang === 'tsx' || lang === 'jsx') { loader = lang; } if (srcMatch) { const src = srcMatch[1] || srcMatch[2] || srcMatch[3]; js += `import ${JSON.stringify(src)}\n`; } else if (content.trim()) { js += content + '\n'; } } if ( loader.startsWith('ts') && (ids.endsWith('.svelte') || (ids.endsWith('.vue') && /<script\s+setup/.test(raw))) ) { // when using TS + (Vue + <script setup>) or Svelte, imports may seem // unused to esbuild and dropped in the build output, which prevents // esbuild from crawling further. // the solution is to add `import 'x'` for every source to force // esbuild to keep crawling due to potential side effects. let m; const original = js; while ((m = importsRE.exec(original)) !== null) { // This is necessary to avoid infinite loops with zero-width matches if (m.index === importsRE.lastIndex) { importsRE.lastIndex++; } js += `\nimport ${m[1]}`; } } if (!js.includes(`export default`)) { js += `\nexport default {}`; } return { loader, contents: js, }; }, ); // 解析第三方库的esm js模块文件 间接走打包 build.onResolve( { // avoid matching windows volume filter: /\.js\?v=1$/, }, ({ path: id, importer }) => { return { path: id, external: true, }; }, ); // 解析.js 文件 build.onResolve( { // avoid matching windows volume filter: /main\.js$/, }, ({ path: id, importer }) => { return { path: id, namespace: 'mianJs', }; }, ); // 加载.js文件的内容 build.onLoad( { filter: /main\.js$/, namespace: 'mianJs' }, ({ path: id }) => { const c = fs.readFileSync(id, 'utf-8'); const magicString = new MagicString(c); let imports = parse(c)[0]; imports.forEach((i) => { const { s, e, n } = i; let absolutePath = path.resolve(__dirname, 'node_modules', n); const isExist = fs.existsSync(absolutePath); if (isExist) { const modulePath = require(absolutePath + '/package.json').module; const esmPath = path.resolve(absolutePath, modulePath); magicString.overwrite(s, e, `${esmPath}?v=1`); deps[n] = esmPath; } else { // let aa = path.resolve(__dirname, n); // magicString.overwrite(s, e, aa); } }); return { loader: 'js', contents: magicString.toString(), }; }, ); }, };}// 收集依赖模块门路 返回一个依赖合集对象async function scanImports() { const deps = {}; const missing = {}; let entries; // 查问出当前目录下后缀为html的文件 entries = await glob('**/*.html', { cwd: process.cwd(), ignore: ['**/node_modules/**'], absolute: true, }); // entries => [ 'C:/Users/dftd/Desktop/vite/node-vue/index.html' ] // console.log('entries', entries); if (!entries.length) { return { deps: {}, missing: {}, }; } const scanPath = esbuildScanPlugin(deps); // 应用 esbuild 进行一次打包,打包过程中就找到了deps和missing,最初返回deps和missing // Promise.all( // entries.map((entry) => { // console.log(222); // await build({ // absWorkingDir: process.cwd(), // 工作的目录 // entryPoints: [entry], // 入口文件(个别为index.html) // write: false, // build API能够间接写入文件系统 默认状况下,JavaScript API会写入文件系统 // bundle: true, // 应用analyze性能生成一个对于bundle内容的易于浏览的报告 // format: 'esm', // 输入的类型 (iife, cjs, esm) // plugins: [scanPath], // }); // }), // ); await build({ absWorkingDir: process.cwd(), // 工作的目录 entryPoints: entries, // 入口文件(个别为index.html) write: false, // build API能够间接写入文件系统 默认状况下,JavaScript API会写入文件系统 bundle: true, // 应用analyze性能生成一个对于bundle内容的易于浏览的报告 format: 'esm', // 输入的类型 (iife, cjs, esm) plugins: [scanPath], }); return { deps, missing, };}依赖预构建总结:依赖预构建产生在在本地服务启动之前执行, 大抵过程分为两步,第一步就是依赖的收集(这部分用到了esbuild build办法来收集所有的依赖门路),第二部是把这些收集的依赖门路再次用esbuild build办法进行编译,编译的后果存储到node_modules/.vite中, 并且还创立了一份_metadata.json文件对构建出的依赖做记录。接下来编写本地服务局部 ...

December 15, 2021 · 8 min · jiezi

关于vue.js:前端工作笔记

一、.sync修饰符在jsx中如何写<cl-dialog title="用户应用详情" visible={this.visible} {...{on: {'update:visible': val => this.visible = val}}} width={"60%"}>Vue中的.sync原理是:prop.sync="data" 只是 :prop="data" @update:prop="val => data = val" 的语法糖,JSX 下本人实现监听逻辑即可。

December 14, 2021 · 1 min · jiezi

关于vue.js:实现自动引入按需引入elementplus原来如此简单

前言:应用unplugin-vue-components后,能够实现按需引入,而且也不必再应用import引入须要的组件,间接应用<el-button>等组件就能够。 1.装置npm包npm i unplugin-vue-components unplugin-auto-import -D2.配置vue.config.js(这里是vuecli配置办法,其余脚手架须要参考文档) const AutoImport = require('unplugin-auto-import/webpack')const Components = require('unplugin-vue-components/webpack')const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')module.exports = { configureWebpack: { plugins: [ AutoImport({ resolvers: [ElementPlusResolver()], }), Components({ resolvers: [ElementPlusResolver()], }), ], }}3.具体应用app.vue <template> <div> <el-button>按钮</el-button> </div></template>4.确认是否按需引入首先,装置webpack-bundle-analyzer插件, npm install --save-dev webpack-bundle-analyzer而后执行以下命令: npm run build --report不必做任何配置,就能够看到终端打印进去打包后各文件大小。 如果想看具体的打包后文件的信息,能够在vue.config.js中做如下配置: const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;module.exports = { configureWebpack: { plugins: [ new BundleAnalyzerPlugin() ] }}而后关上地址http://127.0.0.1:8888就能够了。据我集体测试,残缺引入时,打包后chunk.js文件大小为400k左右。按需引入后,打包后chunk.js文件大小为200k左右。 参考文章:element-plus unplugin-vue-components

December 14, 2021 · 1 min · jiezi

关于vue.js:vue项目中使用vuecodemirror

最近开发中的一个需要如下: 相似代码题库,代码展现的区域刚开始用模板字符串和v-html,能够失常显示,然而不能够按代码格局展现,所以去gitHub上找到了vue-codemirror,顺便记录下在vue我的项目中应用vue-codemirror应用过程 第一步:装置vue-codemirror应用npm:npm install vue-codemirror --save应用yarn:yarn add vue-codemirror应用cdn: <link rel="stylesheet" href="path/to/codemirror/lib/codemirror.css"><script type="text/javascript" src="path/to/codemirror.js"></script><script type="text/javascript" src="path/to/vue.min.js"></script><script type="text/javascript" src="path/to/dist/vue-codemirror.js"></script><script type="text/javascript" src="path/to/codemirror/{some-resources}"></script><script type="text/javascript"> Vue.use(window.VueCodemirror)</script>第二步:全局配置我的项目全局main.js文件内引入: import VueCodemirror from 'vue-codemirror'// import base styleimport 'codemirror/lib/codemirror.css'// import more codemirror resource...Vue.use(VueCodemirror, /* { options: { theme: 'base16-dark', ... }, events: ['scroll', ...]} */)第三步:组件文件内应用test.vue文件内应用: <template> <div class="exercise"> <codemirror v-model="codeSnippets" :options="cmOptions" /> </div></template><script>import { codemirror } from 'vue-codemirror'import 'codemirror/lib/codemirror.css'export default { data() { return { cmOptions: { tabSize: 4, mode: 'text/javascript', // 模式 theme: 'base16-dark', // 主题 lineNumbers: true, // 是否显示行数 line: true, viewportMargin: Infinity, // 解决高度自适应时搭配应用 highlightDifferences: true, autofocus: false, indentUnit: 2, smartIndent: true, readOnly: true, // 只读 showCursorWhenSelecting: true, firstLineNumber: 1, // 更多配置查问 https://codemirror.net/doc/manual.html#config }, codeSnippets: `for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 1) } for (let i = 0; i < 3; i++) { setTimeout(() => console.log(i), 1) }`, } }, components: { codemirror },}</script><style> /* 留神:这里的款式须要全局,如果写了scoped会导致款式不失效 */.CodeMirror { border: 1px solid #eee; height: auto; /* 编辑器盒子高度自适应 */ width: 30%;}</style>

December 14, 2021 · 1 min · jiezi

关于vue.js:vue-中循环渲染对象并通过ref-取值

<el-select v-model="model.industry" filterable> <el-option-group v-for="(parentVal, parentKey, parentIndex) in industrys" :key="'parentKey_'+ parentKey + '_index_'+parentIndex" :label="parentVal.name_zh"> <el-option v-for="(sonVal,sonKey, sonIndex) in parentVal.son" :ref="'ref_'+sonVal.id" :key="'sonKey_'+sonKey+'_index_'+sonIndex" :label="sonVal.name_zh" :value="sonVal.id" :en_name="sonVal.en_name"> </el-option> </el-option-group> </el-select>这是一个分组抉择框, 给el-option 绑定ref 和自定义的en_name 属性在js 中通过model.industry 绑定的值,取label 和en_name 的值 let label_name = this.$refs['ref_'+this.model.industry][0].labellet en_name = this.$refs['ref_'+this.model.industry][0].$attrs['en_name']

December 14, 2021 · 1 min · jiezi

关于vue.js:Vue-3-响应式源码中为什么使用-WeakMap-作为缓存区

在读 Vue 3 响应式原理局部代码的过程中看到其在进行响应式解决的时候,为每个对象应用 WeakMap 创立了一个「缓存区」,代码如下: // 留神上面这句代码!const reactiveMap = new WeakMap();// 外围进行劫持的办法 解决 get 和 set 的逻辑const mutableHandlers = { get, set}function reactive(target: object) { return createReactiveObject(target, mutableHandlers, reactiveMap);}/** * @description 创立响应式对象 * @param {Object} target 须要被代理的指标对象 * @param {Function} baseHandlers 针对每种形式对应的不同处理函数 * @param {Object} proxyMap WeakMap 对象 */function createReactiveObject(target, baseHandlers, proxyMap) { // 检测 target 是不是对象,不是对象间接返回,不进行代理 if (!isObject(target)) { return target } const existsProxy = proxyMap.get(target); // 如果该对象曾经被代理过了,则间接返回,不进行反复代理 if (existsProxy) { return existsProxy } // 未被代理过,则创立代理对象 const proxy = new Proxy(target,baseHandlers); // 缓存,防止反复代理,即防止 reactive(reactive(Object)) 的状况呈现 proxyMap.set(target,proxy); return proxy}从下面的代码能够看出,WeakMap 缓存区的作用就是用来避免对象被反复代理。 ...

December 13, 2021 · 3 min · jiezi

关于vue.js:如何优雅地在Vue页面中引入img图片

咱们在学习html的时候,图片标签<img>引入图片 <img src="../assets/images/avatar.png" width="100%">复制代码然而这样会有2个弊病: 因为采纳绝对路径引入,所以如果前面这张图片挪动了目录,就须要批改代src里的门路如果这张图片在同一页面内有多个中央要应用到,就须要引入屡次,而且图片挪动了目录,这么多中央都要批改src门路怎么办?应用动静门路import、require首先讲讲这两个兄弟,在ES6之前,JS始终没有本人的模块语法,为了解决这种难堪就有了require.js,在ES6公布之后JS又引入了import的概念 应用import引入import之后须要在data中注册一下,否则显示不了 <script>import lf1 from '@/assets/images/lf1.png'import lf2 from '@/assets/images/lf2.png'import lf3 from '@/assets/images/lf3.png'import lf4 from '@/assets/images/lf4.png'import lf5 from '@/assets/images/lf5.png'import lf6 from '@/assets/images/lf6.png'import lf7 from '@/assets/images/lf7.png'import top1 from '@/assets/images/icon_top1.png' export default { name: 'Left', data () { return { lf1, lf2, lf3, lf4, lf5, lf6, lf7, top1}}}</script>复制代码应用require引入<script>import top1 from '@/assets/images/cityOfVitality/icon_top1.png' export default { name: 'Right', data () { return { rt1: require('@/assets/images/crt1.png'), rt2: require('@/assets/images/crt2.png'), rt3: require('@/assets/images/crt3.png'), rt4: require('@/assets/images/crt4.png'), rt5: require('@/assets/images/crt5.png'), rt6: require('@/assets/images/crt6.png'), top1}}}</script>最初如果你感觉此文对你有一丁点帮忙,点个赞。或者能够退出我的开发交换群:1025263163互相学习,咱们会有业余的技术答疑解惑 ...

December 13, 2021 · 1 min · jiezi

关于vue.js:vue-按钮-权限控制

vue 按钮 权限管制前言在日常我的项目中,会碰到须要依据后盾接口返回的数据,来判断以后用户的操作权限。必须当有删除权限时,就显示删除按钮。没有这个权限时,就不显示或者删除这个按钮。通过查找材料,通过vuex来实现这个性能。 步骤1.定义buttom权限在state中创立buttomPermission,用于保留后盾接口返回的权限数据。 setPermission用于承受数据,将页面权限治理传入到buttomPermission对象中。 应用vuexVue.use(Vuex)创立vue实例const store = new Vuex.Store({ state: { buttomPermission: {} }, mutations: { setPermission(state, permission) { state.buttomPermission = permission } }})export default store2.定义storeimport store from './store/index.js'new Vue({ store, el: '#app', render: h => h(App)})3.创立permission指令新建directives文件夹,创立permission.js文件。 这里应用inserted函数,在被绑定元素插入父节点时检测该元素是否有权限。 inserted( el, bindings, vnode ) { }4.应用permission指令在按钮页面引入和定义 permission指令,并且在buttom中写入指令,绑定指令中绝对于的值。 <button v-permission="'add'">增加</button>import permission from './directives/permission'directives: {permission,},5.删除无权限数据在permission指令,通过bindings获取该按钮绑定的value值,而后在buttomPermission对象中找到,而后判断是否有权限,如果没有权限,则删除该节点。 inserted(el, bindings, vnode) { let btnPermissionValue = bindings.value; let boolean =vnode.context.$store.state.buttomPermission[btnPermissionValue]; !boolean && el.parentNode.removeChild(el); }6.传入状态治理数据将状态治理数据,通过setPermission办法传入到权限治理中 ...

December 13, 2021 · 1 min · jiezi

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

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

December 13, 2021 · 1 min · jiezi

关于vue.js:vue-native-修饰符

在我的项目中,因为子组件绑定的 click 事件层级较深,而导致,父组件获取不到。在vue 官网文档中,给出了解决办法:你能够应用 v-on 的 .native 修饰符 <!-- 子组件 --> <div v-for="(item, index) in hotApps" :key="index" class="imgSpace"> <img src="" alt="" @click="handleClick(item)" /> </div> methods: { handleClick(val) { this.$emit("imgInfo", val); },} <!-- 父组件 --> <childer @imgInfo="showImgInfo" >不加 .native 修饰符的时候, 是调用不到父组件办法的。批改 click 为: @click.native="handleClick(item)"就能够拜访父组件办法了。 参考:vue自定义事件vue中'. native'修饰符的应用

December 12, 2021 · 1 min · jiezi

关于vue.js:在Vue项目中引入-ECharts

在Vue我的项目中引入 EChartsECharts是一个弱小的画图插件,在vue我的项目中,咱们经常能够援用Echarts来实现实现一些图表的绘制;以下介绍vue我的项目中援用并应用ECharts。 1.装置应用如下命令通过 npm 装置 ECharts npm install echarts --save2.引入装置实现当前,能够将echarts全副引入,这样一来,咱们能够在该页面应用echarts所有组件;引入代码如下: import * as echarts from "echarts";3.应用引入结束之后,咱们可通过echarts提供的接口画出对应的图表,应用办法如下: <template> <div class="echart" id="mychart" :style="{ float: 'left', width: '100%', height: '400px' }" ></div></template><script>import * as echarts from "echarts";export default { data() { return { name: "张雪", xData: ["2020-02", "2020-03", "2020-04", "2020-05"], //横坐标数据 yData: [30, 132, 80, 134] //纵坐标数据,与横坐标对应 }; }, mounted() { this.initEcharts(); }, methods: { initEcharts() { const option = { title: { text: "ECharts 入门示例" }, tooltip: {}, legend: { data: ["销量"] }, xAxis: { data: ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"] }, yAxis: {}, series: [ { name: "销量", type: "bar", //类型为柱状图 data: [5, 20, 36, 10, 10, 20] } ] }; const myChart = echarts.init(document.getElementById("mychart"));// 图标初始化 myChart.setOption(option);// 渲染页面 //随着屏幕大小调节图表 window.addEventListener("resize", () => { myChart.resize(); }); } }};</script>成果如下: ...

December 11, 2021 · 1 min · jiezi

关于vue.js:vue-watch监听方法汇总

vue中的watch作用就如其命名就是监听的作用比方有个对象 watchData: { name: '', age: '',}监听这个对象的属性watchData: { handler: function() { console.log(); }, deep: true}监听对象能够用deep,深度监测,不然监测不到对象的变动 监听这个对象的属性形式一 watch: { 'watchData.name'(newValue, oldValue) { console.log(newValue); }}形式二watch: { 'watchData.name': { handler: function() { console.log(); } }},为什么要监听对象的属性,监听对象的话,一旦对象外部的任何数据变动,都会导致watch从新执行,这样的话可能不是你想要的监听某一个属性变动才执行watch,或者是一旦说对象外部任何一个属性变动就让其watch执行,也会对性能有肯定性的损耗,所以咱们用这种监听对象单个属性的形式来解决,给要监听的“对象.属性,用引号包裹起来” 监听这个对象的属性computed: { getName() { return this.watchData.name }},watch: { getName(newValue, oldValue) { console.log(newValue); }},这种形式其实和第二种是一样的,区别就是用到了computed,而后再监听办法getName,实际上办法getName返回的就是watchData对象中的name属性

December 11, 2021 · 1 min · jiezi

关于vue.js:React工作记录四React中如何跳转页面传参localStorage和sessionStorage参数较长

前言 我是歌谣 我有个兄弟 巅峰的时候排名c站总榜19 叫前端小歌谣 已经我花了三年的工夫创作了他 当初我要用五年的工夫超过他 明天又是靠近兄弟的一天人生不免崎岖 大不了从头再来 歌谣的意志是永恒的 放弃很容易 然而保持肯定很酷需要 React工作记录三中对页面跳转参数较短得时候进行了数据处理 ,咱们页面跳转得时候能够获取到对应得数据 当数据过长 数据会存在一个失落得状况skip?a=xxxx&b=xxxxxx&c=xxxxx&d=xxxxxxxx 解决方案 这个时候咱们能够采纳localStorage和sessionStorage进行一个存值在下个页面设置得时候永setItem(a,'xxxxx') 获取得时候永getItem('a')获取对应得值 可别忘记json数据之间得转换————————————————版权申明:本文为CSDN博主「前端大歌谣」的原创文章,遵循CC 4.0 BY-SA版权协定,转载请附上原文出处链接及本申明。原文链接:https://blog.csdn.net/geyaois...

December 11, 2021 · 1 min · jiezi

关于vue.js:Vue-前端代码风格指南

一、命名标准 市面上罕用的命名标准: camelCase(小驼峰式命名法 —— 首字母小写)PascalCase(大驼峰式命名法 —— 首字母大写)kebab-case(短横线连贯式)Snake(下划线连贯式) 1.1 我的项目文件命名 1.1.1 我的项目名 全副采纳小写形式, 以短横线分隔。例:my-project-name。 1.1.2 目录名 参照我的项目命名规定,有复数构造时,要采纳复数命名法。例:docs、assets、components、directives、mixins、utils、views。 my-project-name/|- BuildScript // 流水线部署文件目录|- docs // 我的项目的细化文档目录(可选)|- nginx // 部署在容器上前端我的项目 nginx 代理文件目录|- node_modules // 下载的依赖包|- public // 动态页面目录 |- index.html // 我的项目入口|- src // 源码目录 |- api // http 申请目录 |- assets // 动态资源目录,这里的资源会被wabpack构建 |- icon // icon 寄存目录 |- img // 图片寄存目录 |- js // 公共 js 文件目录 |- scss // 公共款式 scss 寄存目录 |- frame.scss // 入口文件 |- global.scss // 公共款式 |- reset.scss // 重置款式 |- components // 组件 |- plugins // 插件 |- router // 路由 |- routes // 具体的路由拆分目录(可选) |- index.js |- store // 全局状态治理 |- utils // 工具寄存目录 |- request.js // 公共申请工具 |- views // 页面寄存目录 |- App.vue // 根组件 |- main.js // 入口文件 |- tests // 测试用例 |- .browserslistrc// 浏览器兼容配置文件 |- .editorconfig // 编辑器配置文件 |- .eslintignore // eslint 疏忽规定 |- .eslintrc.js // eslint 规定 |- .gitignore // git 疏忽规定 |- babel.config.js // babel 规定 |- Dockerfile // Docker 部署文件 |- jest.config.js |- package-lock.json |- package.json // 依赖 |- README.md // 我的项目 README |- vue.config.js // webpack 配置1.1.3 图像文件名 ...

December 10, 2021 · 10 min · jiezi

关于vue.js:壁虎科技Vue中封装axios的取消请求事情

前言须要勾销反复申请的场景: 比方输入框搜寻须要勾销上一次的反复申请tab切换频繁获取数据列表接口时,接口反复申请就是用户频繁切换操作时,咱们调用都是同一个接口的时候,就需要先勾销上一次的接口申请,只申请用户最初一次操作的接口,不然雷同的接口反复申请,接口是异步的,到时就容易拿到数据不是最初一次操作想要的数据了axios自身就封装了勾销事件axios中文文档 勾销事件 axios勾销事件代码如下办法一、能够应用 CancelToken.source 工厂办法创立 cancel token,像这样:const CancelToken = axios.CancelToken;const source = CancelToken.source();axios.get('/user/12345', { cancelToken: source.token}).catch(function(thrown) { if (axios.isCancel(thrown)) { console.log('Request canceled', thrown.message); } else { // 处理错误 }});axios.post('/user/12345', { name: 'new name'}, { cancelToken: source.token})// 勾销申请(message 参数是可选的)source.cancel('Operation canceled by the user.');办法二、还能够通过传递一个 executor 函数到 CancelToken 的构造函数来创立 cancel token:const CancelToken = axios.CancelToken;let cancel;axios.get('/user/12345', { cancelToken: new CancelToken(function executor(c) { // executor 函数接管一个 cancel 函数作为参数 cancel = c; })});// cancel the requestcancel();独自应用axios的时候,两个办法都能够,然而封装好axios办法在vue中全局调用时,办法一有个问题,axios的cancel办法会把行将要收回的申请勾销掉,所以用第二个办法残缺axios封装代码如下:import axios from 'axios'import UserModel from '../models/user'// 接口前缀const PREFIX = { mock: 'https://yapi.comliq.net/mock/31/', // yapi mock 地址 development: 'http://xxx/', // qa环境 production: 'http://xxx/', // 生产环境}const env = process.env.NODE_ENVlet interfacePrefix = PREFIX[env] || PREFIX.production // 接口前缀/** * config 自定义配置项 * @param withoutCheck 不应用默认的接口状态校验,间接返回 response * @param returnOrigin 是否返回整个 response 对象,为 false 只返回 response.data * @param mock 是否应用 mock 服务 * @param timeout 接口申请超时工夫,默认10秒 * @param isCancelRequest 是否能够勾销申请 */const configDefault = { returnOrigin: false, withoutCheck: false, mock: false, timeout: 10000}// 创立申请器const service = axios.create(Object.assign({ baseURL: '', responseType: 'json', headers: { 'Content-Type': 'application/json;charset=utf-8', },}, configDefault))// 增加申请拦截器service.interceptors.request.use( request => { const reqData = request.data || request.params if (reqData && !request.canEmpty) { // 对申请参数进行解决,革除空参数 request.data = deleteEmpty(reqData) } // 检测接口,依据环境主动切换前缀 if (request.url.indexOf('http') === -1) { if (request.url[0] === '/') { request.url = request.url.substr(1) } request.url = `${env !== 'production' && request.mock ? PREFIX.mock : interfacePrefix}${request.url}` } // 若有做鉴权token,须要申请头主动加上token, 这个token本人封装获取的 request.headers.accessToken = UserModel.getToken() return request }, error => { return Promise.reject(error) },)// object对象寄存每次new CancelToken生成的办法let source = {}// 每次申请前都会把path放在此数组中,响应胜利后革除此申请pathlet requestList = []// 定义勾销办法function cancelRequest(path, allCancel) { // 申请列表里存在此path,即发动反复申请,把之前的申请勾销掉 if (path && requestList.includes(path) && typeof source[path] === 'function') { source[path]('终止申请') } else if (!path && allCancel) { // allCancel为true则申请列表里的申请全副勾销 requestList.forEach(el => { source[el]('批量终止申请') }) }}// 增加响应拦截器service.interceptors.response.use( res => { // 获取申请的api const path = JSON.stringify(res.config.url) // 申请实现后,将此申请从申请列表中移除 requestList = requestList.filter(item => !path.includes(item)) // HTTP 状态码 2xx 状态入口,data.code 为 200 示意数据正确,无任何谬误 }, error => { // 非 2xx 状态入口 return Promise.reject(error) },)// 这里只做post封装演示,大家能够本人封装其余申请办法function requestFn(method, path, params = {}, options = {}) { // 勾销上一次申请 if (requestList.length) { cancelRequest(path) } // 设置isCancelRequest为ture, 申请前将path推入requestList if (options.isCancelRequest) { requestList.push(path) } if (method === 'post') { return service.post(path, params, { cancelToken: new axios.CancelToken(c => { source[path] = c }), ...options }) }}export const api = { axios: service, // 原始 axios 对象 // 从新封装 get 函数,对立应用形式 get: (path, data, config) => service.get(path, { params: data, ...config }), delete: (path, data, config) => service.delete(path, { data, ...config }), post: (path, data, config) => requestFn('post', path, data, config), put: (path, data, config) => service.put(path, data, config),}export default api参考文献: ...

December 10, 2021 · 2 min · jiezi

关于vue.js:vue跳页面时-携带信息到新页面的方法

第一个方法是:将数据存到storage外面,之后在新页面取出来 第二个方法,也是我这里要说的方法,像这样写: 跳路由时把数据附带下来 this.$router.push('/admin/personnel/custom-detail/' + item.id)能够看到,前面携带了数据 item.id 在api外面配置好要接管的数据: { path: '/admin/personnel/custom-detail/:id', meta: { title: 'xxx', breadcrumb: 'xxx/xxx/xxx' }, component: () => import('views/personnel/custom/detail/page.vue')},能够看到,在 path 中我增加了 /:id 之后就能够在新页面接管信息了: this.$route.params.id 应用$route.params能够获取到导航栏携带的数据 再将数据存到data外面,这样就OK了

December 10, 2021 · 1 min · jiezi

关于vue.js:vue跨域post

proxy: { '/api': { target: 'xxxxxxxxxxxxxxxx', ws: true, changeOrigin: true, pathRewrite: { '^/api': '/api' }, cssSourceMap: false, onProxyReq: function (proxyReq, req, res) { if (proxyReq.getHeader('origin')) { proxyReq.setHeader('origin', 'xxxxxxxxxxxxxxxx') } console.log('原门路:' + req.originalUrl, '代理门路:' + req.path) } }},

December 10, 2021 · 1 min · jiezi

关于vue.js:在vueelementtemplate中按需引入elementui组件

起因:1,旧的babel-perset-es2015在babel 7.x版本曾经不反对,依照官网配置的话会报错: Cannot find module ‘babel-preset-es2015’2,vue-element-template中并没有 .babelrc ,而是如下图所示 解决方案:1,依照官网装置 babel-plugin-component npm install babel-plugin-component -D2,配置babel.config.js module.exports = { presets: [ '@vue/cli-plugin-babel/preset', ['@babel/preset-env', { 'modules': false }] ], 'plugins': [ [ 'component', { 'libraryName': 'element-ui', 'styleLibraryName': 'theme-chalk' } ] ]}3,参考官网进行相应的按需引入操作即可 未解决问题:是否须要装置@babel/preset,作用是什么? 参考网址:https://blog.csdn.net/zy21131... https://blog.csdn.net/m0_4711...

December 10, 2021 · 1 min · jiezi

关于vue.js:你以为Vue3封装一个弹框组件很简单

总结放后面: Tipes: 封装弹框组件应用了Teleport,防止了组件嵌套可能导致的定位层级的隐患,还应用了defineProps,defineEmits,插槽减少了组件的拓展性。 前言: 之前始终没有本人去封装过一个弹框组件,然而感觉一个小小的弹窗组件那不是洒洒水小意思了。而后明天新我的项目中须要一个弹窗组件,所以我就做了一个。不做不要紧一做发现还是有很多不同的小问题,而后就把遇到的问题和大佬们分享一下。开始先回顾一下需要,一个全局应用的公共弹框组件。那么就有几个要点:公共、全局、弹框,上面咱们就针对这几个要点去一点点实现弹框组件。公共 公共这个简略,置信在座的各位大佬必定都是手拿把掐,轻轻松松就实现了。先实现一个主体内容,我的办法就是应用插槽和参数传递。例子只是简略的传递两个参数,一个题目内容一个管制关上和敞开的布尔值。次要波及到Vue3两个Api的应用defineProps,defineEmits还有插槽的应用。<template> <Mask @click="close" /> // 蒙板层<div class="modal_all" v-if="visible"> <slot name="header"> // 不便页面减少定制头部 <div class="modal_header"> <p class="modal_header_title">{{ title }}</p> <p class="modal_header_img" @click="close"></p> </div> </slot> <div class="modal_content"> <slot></slot> // 凋谢弹框内容应用 </div></div></template><script lang="ts" setup>defineProps({ visible: { type: Boolean, default: false,},title: { type: String,},});const emit = defineEmits(['update:visible']);const close = () => { emit('update:visible', false);};</script>// 款式省略复制代码全局 根本布局差不多了,上面就是全局注册,目标是为了不必每次应用每次都要引入。vue2在注册全局组件的时候,间接Vue.component('名称', 组件)就能够了,那么在vue3中怎么批量注册全局组件呐?提供一个install办法,应用app.use()主动调用。import Modal from './Modal/Modal.vue';import Mask from './Modal/Mask.vue'; // 在script setup不能写name,所以在这里加一个const coms = [ { name: 'Modal', // 应用组件的名称compent: Modal,}, { name: 'Mask',compent: Mask,},]; ...

December 9, 2021 · 1 min · jiezi

关于vue.js:分享一个自己写的vue项目SancksApp

snack-app我的项目简介一个能够和大家分享本人喜爱的零食的挪动端我的项目,波及的技术栈次要有Vue + Vue-Router + Sass + Koa2 + Mongoose。 我的项目次要性能有: 登录/注册搜寻零食公布零食留言/评论珍藏零食/点赞零食显示热门零食批改个人信息如有谬误之处,欢送斧正~ 效果图查看效果图请戳此链接 我的项目地址https://github.com/6fa/Snack-App 运行在终端输出 mongod 启动mongodb(确保已装置了mongodb)下载服务端代码:Snack-server 在server下新启动终端,输出上面命令链接数据库: //装置依赖npm install//链接数据库node app.js回到snack-app(即本我的项目),装置依赖 npm install应用vue cli的热更新性能开启服务: npm run serve如果运行胜利,终端能够看到如下信息: App running at: - Local: http://localhost:8080/ - Network: http://xxx:8080/应用下面的链接即可拜访查看成果

December 9, 2021 · 1 min · jiezi

关于vue.js:vue-audio-浏览器音乐不能自动播放

安卓手机浏览器无奈自动播放背景音乐 须要在mounted 强制执行播放 auido.play()

December 9, 2021 · 1 min · jiezi

关于vue.js:vue项目打包时候遇到的警告需要优化

记录一下明天部署代码遇到的问题 一、npm run build时候提醒谬误如下图:翻译如下:说是依赖关系不对等和兼容问题,这时候共事让我删掉packege-lock.json,删除后呈现了新的warning,相似下图(我本人的报错步骤被我cls了):翻译一下就是可选的跳过可选的依赖:fsevents@2.1.2,其实这个包是能够选择性装置的被装置的起因就是:这个包是mac上能够抉择的依赖,然而你应用了window的电脑,也装置了,能够看看你的package.json文件中是不是fsevents的相干依赖,删除就好;其实这个正告是因为mac须要这个包,然而你是在windows环境下,能够疏忽这个正告,如果你是强迫症能够应用以下方法,不装置这个包 解决办法:1、第一步:在package.json中增加这个对象 "optionalDependencies": { "fsevents": "*" }2、第二步:删除原来装置的包和生成的package-lock.json文件3、第三步:从新执行装置命令 `npm install --no-optional`原文在此二、npm run build时候提醒谬误如下图:翻译意思是:资产规模限度:以下资产超过倡议的规模限度(244千磅)。这可能会影响web性能。就是打包进去的js体积超标了 解决办法:在vue.config.js减少配置: configureWebpack: config => { // 为生产环境批改配置... if (process.env.NODE_ENV === 'production') { config.mode = 'production'; // 打包文件大小配置 config.performance = { maxEntrypointSize: 10000000, maxAssetSize: 30000000 } }},原文在此

December 9, 2021 · 1 min · jiezi

关于vue.js:elementui-级联选择器

<template> <div class="main"> <el-cascader v-model="form.name" :props="props" options="options" @change="changeValue" > </el-cascader> </div></template><script>export default { data() { return { options: [], props: { // value: "code", // label: "name", lazy: true, lazyLoad (node, resolve) { const { level } = node; //const level = node.level; //申请参数 const requestData = {}; if (level === 0) { requestData.type = "province"; } if (level === 1) { requestData.type = "city"; requestData.code = node.value; } if (level === 2) { requestData.type = "area"; requestData.code = node.value; } getFun(requestData).then(res => { const data = res.data; if (level === 0) { data.forEach(item => { item.value = item.code; item.label = item.name; }); } if (level === 1) { data.forEach(item => { item.value = item.code; item.label = item.name; }); } if (level === 2) { data.forEach(item => { item.value = item.code; item.label = item.name; item.leaf = level >= 2; }); } console.log(res); // 返回节点数据,具体看返回内容取res.data.data resolve(res.data); }) } }, }; }, methods: { changeValue(value) { console.log(value.join()); this.$emit("update:value", value.join()); } },};</script></style>

December 8, 2021 · 1 min · jiezi

关于vue.js:ApacheCN-Vue-译文集-20211115-更新

应用 GraphQL 构建 VueJS 利用 零、前言一、数据绑定、事件和计算属性二、组件、混合器和性能组件三、设置咱们的聊天利用——AWS Amplify 环境和 GraphQL四、创立自定义利用组件和布局五、创立用户 Vuex 模块、页面和路由六、创立聊天和音讯 Vuex、页面和路由七、将您的利用程序转换为 PWA 并部署到 WebVueJS2 Web 开发齐全手册 零、前言一、Vue.js 入门二、显示、循环、搜寻和筛选数据三、优化利用并应用组件显示数据四、应用 Dropbox API 获取文件列表五、浏览文件树并从 URL 加载文件夹六、应用 Vuex 缓存以后文件夹构造七、预缓存其余文件夹和文件来放慢导航速度八、介绍 Vue 路由并加载基于 URL 的组件九、应用 Vue 动静路由加载数据十、建设电子商务商店——浏览产品十一、建设电子商务商店——增加收银台十二、应用 Vue 开发工具并测试您的 SPA十三、过渡和动画十四、Vue 与互联网通信十五、单页利用十六、组织 + 自动化 + 部署 = Webpack十七、高级 Vue.js——指令、插件和渲染函数十八、应用 Vuex 的大型利用模式十九、与其余框架的集成二十、Vue 路由模式二十一、将 Vuex 用于状态治理NuxtJS Web 开发实用指南 零、前言第一局部:您的第一个 Nuxt 利用 一、Nuxt 简介二、Nuxt 入门三、增加 UI 框架第二局部:视图、路由、组件、插件和模块 四、增加视图、路由和过渡五、增加 Vue 组件六、编写插件和模块七、增加 Vue 表单第三局部:服务器端开发和数据管理 八、增加服务器端框架九、增加服务器端数据库十、增加 Vuex 商店第四局部:中间件和平安 十一、编写路由中间件和服务器中间件十二、创立用户登录和 API 身份验证第五局部:测试和部署 ...

December 8, 2021 · 2 min · jiezi

关于vue.js:superMap开源框架-使用Cesium实现截图

没有在主页面进行,在独自的一个路由通过监听事件监听截图按钮,依据我的代码或者查看开源代码进行应用或批改! 当初data中定义全局的viewer进行应用!因为要申明一个全局的viewer来进行的; data(){ return{ url:'', viewer:window.viewer, scene:viewer.scene, }},通过监听事件获取; methods: { // 截图 screenshotClick() { var promise = this.scene.outputSceneToFile(); Cesium.when( promise, (base64data)=> { this.download(base64data); } ); }, /** * 依据图片生成画布 */ convertImageToCanvas(image) { var canvas = document.createElement("canvas"); canvas.width = image.width; canvas.height = image.height; canvas.getContext("2d").drawImage(image, 0, 0); return canvas; }, /** * 下载图片 */ download(base64data) { var image = new Image(); image.src = base64data; console.log(image.src,'image'); image.onload = ()=> { var canvas = this.convertImageToCanvas(image); this.url = canvas.toDataURL("image/jpeg"); //生成齐全的base64照片编码 var a = document.createElement("a"); var event = new MouseEvent("click"); a.download = new Date().getTime() + ".jpg"; // 指定下载图片的名称 a.href = this.url; a.dispatchEvent(event); // 触发超链接的点击事件 }; },}总体流程就是这样!有什么没有看明确的也能够上官网参考:http://support.supermap.com.c... ...

December 8, 2021 · 1 min · jiezi

关于vue.js:手把手教你在vue3中使用axios

1.从js文件中引入axios第一种办法是,先在js文件中对axios做一些解决再引入到vue文件中,比方申请拦挡、响应拦挡、封装对立的get、post办法,甚至是定义接口申请。具体做法: 1.装置npm i --save axios 2.对axios做解决requests/index.js import axios from 'axios'axios.defaults.timeout = 50000axios.interceptors.request.use(config => { // ... return config}, error => { return Promise.error(error)})function getName(params) { return axios.get(`xx/xx/${params}`)}export { getName}3.在vue文件中申请接口test.vue <script lang="ts" setup>import {getName} from '~@/requests/index'onMounted(() => { getName('xxxx');});</script>2.将axios挂载在全局变量上这种办法,能够从全局变量中获取axios 1.装置npm i --save axios 2.挂载import axios from 'axios'app.config.globalProperties.axios = axios3.应用axiosimport { getCurrentInstance } from 'vue'const { appContext } = getCurrentInstance();onMounted(() => { console.log(appContext.config.globalProperties.axios)})3.应用vue-axios这种办法能够用vue.use()装置axios,而后通过provide-inject应用。 1.装置npm install --save axios vue-axios 2.挂载import axios from 'axios'import VueAxios from 'vue-axios'const app = createApp(App).use(store)app.use(VueAxios, axios)app.provide('axios', app.config.globalProperties.axios)3.应用import { inject } from 'vue'const axios = inject('axios')console.log(axios)

December 8, 2021 · 1 min · jiezi

关于vue.js:基于Vue3最新标准实现后台前端综合解决方案sfa

download:基于Vue3最新规范,实现后盾前端综合解决方案name = "Raymond" age = 22 born_in = "Oakland, CA" string = "Hello my name is {0} and I'm {1} years old. I was born in {2}.".format(name, age, born_in) print(string)返回tuple元组 Python容许你在一个函数中返回多个元素,这让生存更简略。然而在解包元组的时候出出线这样的常见谬误: def binary(): return 0, 1result = binary() zero = result[0] one = result[1]这是没必要的,你残缺可能换成这样: def binary(): return 0, 1zero, one = binary()要是你需要所有的元素被返回,用个下划线 _ : zero, _ = binary()就是这么高效率! 拜访Dict字典 你也会常常给 dicts 中写入 key,value (键,值)。 如果你试图拜访一个不存在的于 dict 的 key ,可能会为了避免 KeyError 谬误,你会偏向于这样做: ...

December 8, 2021 · 2 min · jiezi

关于vue.js:基于Vue3ViteTS二次封装elementplus业务组件sfasga

download:基于Vue3+Vite+TS,二次封装element-plus业务组件构造字符串 你会常常需要打印字符串。要是有很多变量,避免上面这样: name = "Raymond" age = 22 born_in = "Oakland, CA" string = "Hello my name is " + name + "and I'm " + str(age) + " years old. I was born in " + born_in + "." print(string)额,这看起来多乱呀?你可能用个丑陋简洁的方法来代替, .format 。 这样做: name = "Raymond" age = 22 born_in = "Oakland, CA" string = "Hello my name is {0} and I'm {1} years old. I was born in {2}.".format(name, age, born_in) print(string)返回tuple元组 ...

December 8, 2021 · 2 min · jiezi

关于vue.js:defineProperty-和-Proxy区别直接上结论有一句废话你打我

在Vue2和3 中 defineProperty 和 Proxy 都是用来实现响应式数据绑定的。实现的性能相似,然而两个API却有着实质的区别。 监听数据的角度 defineproperty只能监听某个属性而不能监听整个对象。proxy不必设置具体属性,间接监听整个对象。defineproperty监听须要晓得是哪个对象的哪个属性,而proxy只须要晓得哪个对象就能够了。也就是会省去for in循环进步了效率。监听对原对象的影响 因为defineproperty是通过在原对象身上新增或批改属性减少描述符的形式实现的监听成果,肯定会批改原数据。而proxy只是原对象的代理,proxy会返回一个代理对象不会在原对象上进行改变,对原数据无污染。实现对数组的监听 因为数组 length 的特殊性 (length 的描述符configurable 和 enumerable 为 false,并且妄图批改 configurable 为 True 的话 js 会间接报错:VM305:1 Uncaught TypeError: Cannot redefine property: length)defineproperty无奈监听数组长度变动, Vue只能通过重写数组办法的形式变现达成监听的成果,光重写数组办法还是不能解决批改数组下标时监听的问题,只能再应用自定义的$set的形式而proxy因为本身个性,是创立新的代理对象而不是在原数据身上监听属性,对代理对象进行操作时,所有的操作都会被捕获,包含数组的办法和length操作,再不须要重写数组办法和自定义set函数了。(代码示例在下方)4. 监听的范畴 defineproperty只能监听到value的 get set 变动。proxy能够监听除 [[getOwnPropertyNames]] 以外所有JS的对象操作。(链接看下方)监听的范畴更大更全面。点击查看proxy反对监听的对象操作方法(除getOwnPropertyNames) Proxy监听数组变动示例: let array = ['1', '2']let arrayProxy = new Proxy(array, { get(target, key) { console.log('(key:', key + ") 产生了get操作") return target[key] }, set(target, key, value) { console.log('(key:', key + ") 产生了set操作, value= " + value) return target[key] = value }})arrayProxy.push('我是push函数push到数组中的值')// (key: push) 产生了get操作// (key: length) 产生了get操作// (key: 2) 产生了set操作, value= 我是push函数push到数组中的值// (key: length) 产生了set操作, value= 3// 从log能够看出push length等操作都被捕获了

December 8, 2021 · 1 min · jiezi

关于vue.js:vue-watch监听数组新旧值相同问题

场景vue应用watch监听数组变动时,更改数组但其newVal和oldVal总是雷同,无奈辨别数组中哪条数据是新增加的。 产生起因Vue官网得悉:由watch用法中提到,在变更 (不是替换) 对象或数组时,旧值将与新值雷同,因为它们的援用指向同一个对象/数组。Vue 不会保留变更之前值的正本。 罕用变更函数数组:push、pop、shift、unshift、splice、reverse、sort 解决思路将数组用一个根本数据类型的两头变量做过渡,先将数组转为为一般数据类型的变量,watch就能够监听到两头变量的变动,最初再将一般数据变量转化为数组。很容易就想到数组与string之间的互相转换,这个转化过程就交给vue的computed计算解决。 实例代码data: () { return{ pullStreamList:[] }},computed:{ pullStreamListWatch(){ return JSON.parse(JSON.stringify(this.pullStreamList)); }},watch:{ pullStreamListWatch: { handler: function (value, oldValue) { console.log("newval", newval); console.log("oldval", oldval); }, }}测试后果

December 8, 2021 · 1 min · jiezi

关于vue.js:踩坑记录vue-cli引入umd文件无效问题

问题事件起因是我写了一个基于vue的图片上传插件,用vue cli打包为库后,想在本地引入umd包来测试插件能不能用,后果报错,次要是Unexpected token '<' 和 ChunkLoadError:Loading chunk xx failed: 点入报错的文件链接,发现是<!DOCTYPE html>标签谬误: 搜寻一番后,根本能够确定是引入谬误,然而不晓得起因。 尝试解决在搜索引擎挣扎许久,也尝试过更改publicPath、增加@babel/plugin-transform-modules-umd等均有效,次要是不晓得根本原因。 在看到这两篇博文(webpack之Loading chunk x failed 、Vue CLI build --target lib 时如何防止打包成多个umd.js文件)后,分割联合,猜想起因是分包加载谬误:webpack打包库会将代码分成多个包(看下图),在vue我的项目中只引入 *.umd.js,然而其余分包没有按程序引入,因为被浏览器拦挡申请篡改了分包内容(具体可见下面提及的第一篇博文),不能保障代码的程序执行。 那么能够尝试将代码打包为一个文件,这样不须要保障script代码执行程序,试试是否见效。 须要批改vue.config.js: 限度打包为一个包批改css.extract为false,示意不将css文件独自抽离,省得用户本人导入 CSS// vue.config.jsconst webpack = require("webpack");module.exports = { css: { extract: false }, configureWebpack: { plugins: [ // 限度只打一个包,不分Chunk new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 }) ], // 当库外面引入了比拟大的文件时,为了不影响主包大小,须要设置下该包应用内部引入 externals: { echarts: "echarts" } }}; 再次打包: 尝试引入应用,果然胜利了: 总结尽管依着下面的思路问题是解决了,然而是否就是这个起因,自己也无奈非常确定(兴许是歪打正着了 :) )。如果有人有更好的想法,欢送探讨^_^ 更多学习笔记请戳:https://github.com/6fa/WebKnowledge 参考webpack之Loading chunk x failed Vue CLI build --target lib 时如何防止打包成多个umd.js文件 ...

December 7, 2021 · 1 min · jiezi

关于vue.js:vue-模版编译流程

vue中的模板编译的步骤:将template模板转化成ast语法树(拼接字符串),而后通过new Function + with语法,将ast语法树包装成Render函数,而后生成虚构节点,而后将虚构节点挂载到dom树上,生成实在DOM. (1) 将template模板转换成ast语法树 -parserHTML(正则实现)(2) 对动态语法做动态标记 -markUp(3) 从新生成代码 生成render函数返回的是虚构节点留神:在开发时尽量不要应用template,因为将template转化成render办法,须要在运行时进行编译操作,会有性能损耗,同时援用电邮compiler包的vue体积也会变大。默认.vue文件中的template解决是通过vue-loader(依赖的是vue-template-compiler)来进行解决的而不是通过运行时的编译应用到的正则// 匹配属性const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/const dynamicArgAttribute = /^\s*((?:v-[\w-]+:|@|:|#)\[[^=]+?\][^\s"'<>\/=]*)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z]*`const qnameCapture = `((?:${ncname}\\:)?${ncname})`// 匹配开始标签开始const startTagOpen = new RegExp(`^<${qnameCapture}`)// 匹配开始标签闭合const startTagClose = /^\s*(\/?)>/// 匹配标签完结const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`)const doctype = /^<!DOCTYPE [^>]+>/i解析开始节点,先匹配到tagName,而后再去循环匹配取的属性的值,而后组装成一个节点 function parseStartTag(){ let start = html.match(startTagOpen) if(start && start.length){ const match = { tagName:start[1], attrs: [] } advance(start[0].length) let end,attr while (!(end = html.match(startTagClose)) && (attr = html.match(attribute))) { advance(attr[0].length) match.attrs.push({ name: attr[1], value: attr[3]|| attr[4]|| attr[5] }) } if(end){ advance(end[0].length) } return match } }(1代表dom节点,3代表文本节点)匹配完开始节点后,把曾经匹配过的字符串截取掉,残余字符串接着匹配,上面可能会呈现以下几种状况(1)接下来匹配就是完结标签    那就祝贺你啦,这个节点曾经齐全匹配进去了,只须要把这个节点从咱们记录的栈里弹出,造成一个上面的构造就OK啦,而后截取点曾经匹配过的字符串,拿剩下的字符串持续进行匹配,直到传入的字符串全副被匹配一遍 ...

December 6, 2021 · 2 min · jiezi

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

明天的知识点 (2021.12.05) —— 第964天 (我也要出题)[html] 应用canvas制作一朵玫瑰花[css] transform的rotate在内联元素下面不起作用,如何解决?[js] js Map构造,forEach能够进行遍历,一般for循环为什么不进入执行?[软技能] 如果有事件让你很懊恼,你是如何自我调节的?《论语》,曾子曰:“吾日三省吾身”(我每天屡次检查本人)。前端面试每日3+1题,以面试题来驱动学习,每天提高一点!让致力成为一种习惯,让奋斗成为一种享受!置信 保持 的力量!!! 欢送在 Issues 和敌人们一起探讨学习! 我的项目地址:前端面试每日3+1【举荐】欢送跟 jsliang 一起折腾前端,零碎整顿前端常识,目前正在折腾 LeetCode,打算买通算法与数据结构的任督二脉。GitHub 地址 微信公众号欢送大家前来探讨,如果感觉对你的学习有肯定的帮忙,欢送点个Star, 同时欢送微信扫码关注 前端剑解 公众号,并退出 “前端学习每日3+1” 微信群互相交换(点击公众号的菜单:交换)。 学习不打烊,充电加油只为遇到更好的本人,365天无节假日,每天早上5点纯手工公布面试题(死磕本人,愉悦大家)。心愿大家在这虚夸的前端圈里,放弃沉着,保持每天花20分钟来学习与思考。在这变幻无穷,类库层出不穷的前端,倡议大家不要等到找工作时,才狂刷题,提倡每日学习!(不忘初心,html、css、javascript才是基石!)欢送大家到Issues交换,激励PR,感激Star,大家有啥好的倡议能够加我微信一起交换探讨! 心愿大家每日去学习与思考,这才达到来这里的目标!!!(不要为了谁而来,要为本人而来!)交换探讨欢送大家前来探讨,如果感觉对你的学习有肯定的帮忙,欢送点个[Star]

December 5, 2021 · 1 min · jiezi

关于vue.js:基于Vue3ViteTS二次封装elementplus业务组件mk

download:基于Vue3+Vite+TS,二次封装element-plus业务组件mk后盾代码都是利用的 1.【get形式】使用jquery的get json与后盾交互 前端js代码片段 var data= {'a': $('input[name="a"]').val(),'b': $('input[name="b"]').val()}$.getJSON($SCRIPT_ROOT + '/_add_numbers',data, function(data) {$('#result').text(data.result);$('input[name=a]').focus().select();});后端pthon代码如下 ajax,Get形式与js交互(非表单)采纳了flask框架@app.route('/_add_numbers')def add_numbers():"""Add two numbers server side, ridiculous but well...""" a = request.args.get('a', 0, type=int) b = request.args.get('b', 0, type=int) log.info(a) log.info(b) return jsonify(result=a + b)2.【万能形式】使用jquery的ajax与后盾交互,设置不同的参数,可能get也可能post 下面的例子用ajax形式,前端代码如下 var data= { 'a': $('input[name="a"]').val(), 'b': $('input[name="b"]').val() }{# $.getJSON($SCRIPT_ROOT + '/_add_numbers',data, function(data) {#}{# $('#result').text(data.result);#}{# $('input[name=a]').focus().select();#}{# });#} $.ajax({ type: 'get', url: $SCRIPT_ROOT + '/_add_numbers', data: data, contentType: 'application/json; charset=UTF-8', dataType: 'json', success: function(data) { $('#result').text(data.result); $('input[name=a]').focus().select(); }, error: function(xhr, type,xxx) { alert('error ') } });后盾代码不便依然是 ...

December 5, 2021 · 1 min · jiezi

关于vue.js:vuejs业务页面的发布订阅代码设计

平时用vuejs写业务页面时,发现常常会用到雷同的逻辑去搭建页面,初始化数据、校验参数、子页体面路由的渲染等。所以在这里总结一下这种页面的初始化套路,不便后续创立页面或者优化逻辑。设计准则利用公布-订阅的模式去初始化子页面,父页面解决全局的相干操作。 父页面:校验参数、数据的合法性,并发网络申请,疏导至全局的谬误页面,最终触发initReady=true。子页面:订阅initReady事件,胜利后进行子页面初始化。逻辑图 代码设计1. vuex状态数据// store.jsimport global from './modules/global';import cards from './modules/cards';export default { namespaced: true, modules: { global, cards, },};// ./modules/global.js/** 全局数据*/export default { // 命名空间隔离 namespaced: true, state: { // 全局事件-初始化实现,子页面订阅此事件的变更 initReady: false, // 全局错误码 error: null, // 全局常量,不可更改 constants: Object.freeze({ test: 1, }), }, mutations: { SET_INIT_READY(state, value) { state.initReady = value; }, SET_ERROR(state, value) { state.error = value; }, }, actions: { setInitReady({ commit }, value) { commit('SET_INIT_READY', !!value); }, setError({ commit }, value) { commit('SET_ERROR', value || null); }, },};// ./modules/cards.js/** 卡列表相干数据*/export default { // 命名空间隔离 namespaced: true, state: { // 以后卡 currentCard: {}, // 卡列表 cardsList: [], }, mutations: { SET_CURRENT_CARD(state, value) { state.currentCard = value; }, SET_CARDS_LIST(state, value) { state.cardsList = value; }, }, actions: { setCurrentCard({ commit }, value) { commit('SET_CURRENT_CARD', value || {}); }, setCardsList({ commit }, value) { commit('SET_CARDS_LIST', value || []); }, },};2. vue router路由定义// routes.js,subApp的路由定义const index = () => import(/* webpackChunkName: "HcTplSubApp" */ './views/index.vue');const home = () => import(/* webpackChunkName: "HcTplSubApp" */ './views/home.vue');export default [ { path: '/', component: index, meta: { title: '首页', }, children: [ { path: '', // 首页 name: 'RouteHome', // 应用路由名字进行跳转,有助于代码易读性 component: home, meta: { title: '首页', keepAlive: true, }, }, ], },];3. index父页面<template> <div class="page-index"> <!-- 谬误提醒 --> <error-page v-if="error" :error="error || {}"></error-page> <!-- 子页面 --> <template v-if="initReady"> <!-- 缓存 --> <keep-alive> <router-view v-if="$route.meta.keepAlive"/> </keep-alive> <!-- 非缓存 --> <router-view v-if="!$route.meta.keepAlive"/> </template> </div></template><script>import { mapActions, mapState } from 'vuex';import ErrorPage from '@/components/common/ErrorPage';export default { name: 'PageIndex', components: { ErrorPage, }, data() { return { // loading spinner loading: null, }; }, computed: { ...mapState('tpl/global', { initReady: state => state.initReady, constants: state => state.constants, error: state => state.error, }), ...mapState('tpl/cards', { cardsList: state => state.cardsList, currentCard: state => state.currentCard, }), }, created() { this.initPage(); }, methods: { ...mapActions('tpl/global', [ 'setInitReady', 'setError', ]), ...mapActions('tpl/cards', [ 'setCurrentCard', 'setCardsList', ]), /** * 全局初始化 */ async initPage() { this.loading = this.$weui.loading('加载中'); // 校验参数 if (!this.validateQuery()) { if (this.loading) this.loading.hide(); return; } // 所有初始化的异步申请 await Promise.all([this.initCard()]); // 校验后果 if (!this.validateResult()) { if (this.loading) this.loading.hide(); return; } // 触发ready事件 this.setInitReady(true); }, /** * 校验参数合法性 */ validateQuery() { const { hospitalId = '' } = this.$route.query; if (!hospitalId) { this.setError({ message: '医院标识[hospitalId]不能为空' }); return false; } return true; }, /** * 校验全局数据,报错或跳转 */ validateResult() { // 卡列表数据为空,跳转第三方链接建卡 if (this.cardsList.length === 0) { this.setError({ message: '卡列表不能为空' }); return false; } return true; }, /** * 获取卡列表 */ async initCard() { // 利用卡列表插件读取卡列表 const { card, cards } = await this.$Card.init(); this.setCurrentCard(card); this.setCardsList(cards); // 校准url里的healthCardId参数 const { query } = this.$route; if (card.healthCardId && query.healthCardId !== card.healthCardId) { await this.$router.replace({ query: { ...query, healthCardId: card.healthCardId, ecardNo: card.ecardNo, }, }); } }, },};</script><style lang="scss" scoped>.page-index {}</style>4. home子页面<template> <div class="page-home"> page home </div></template><script>import { mapState } from 'vuex';import pageMixin from 'hc-vue-mixins/page';export default { name: 'PageHome', mixins: [pageMixin], data() { return { // loading spinner loading: null, }; }, computed: { ...mapState('tpl/global', { initReady: state => state.initReady, }), ...mapState('tpl/cards', { cardsList: state => state.cardsList, currentCard: state => state.currentCard, }), }, // 利用hooks或者watch来订阅initReady事件 created() { if (this.initReady) this.initPage(); }, watch: { initReady() { if (this.initReady) this.initPage(); }, }, methods: { /** * 初始化 */ async initPage() { this.loading = this.$weui.loading('加载中'); // do something in this page console.log(this.currentCard); console.log(this.cardsList); this.loading.hide(); }, },};</script><style lang="scss">.page-home {}</style>

December 5, 2021 · 3 min · jiezi

关于vue.js:Vue中如何使用debouce防抖函数

创立一个 debounced(防抖动)函数,该函数会从上一次被调用后,提早 wait 毫秒后调用 func 办法。 debounced(防抖动)函数提供一个 cancel 办法勾销提早的函数调用以及 flush 办法立刻调用。 能够提供一个 options(选项) 对象决定如何调用 func 办法,options.leading 与|或 options.trailing 决定提早前后如何触发(注:是 先调用后期待 还是 先期待后调用)。 func 调用时会传入最初一次提供给 debounced(防抖动)函数 的参数。 后续调用的 debounced(防抖动)函数返回是最初一次 func 调用的后果。 Lodash debouce参数func  (Function) : 要防抖动的函数。[wait=0]  (number) : 须要提早的毫秒数。[options=]  (Object) : 选项对象。[options.leading=false]  (boolean) : 指定在提早开始前调用。[options.maxWait]  (number) : 设置 func 容许被提早的最大值。[options.trailing=true]  (boolean) : 指定在提早完结后调用。 <template><el-input v-model="value" size="mini" placeholder="请输出.." clearable @keydown.enter="handleSearch" ></el-input></template><script>import _ from 'lodash'export default {data() { return { value: '' }},create() { this.handleSearch = _.debounce(() => { // 获取列表 this.getList(); }, 300);},beforeDestroy() { // 勾销该函数的防抖动调用 this.handleSearch.cancel();},}</script>

December 2, 2021 · 1 min · jiezi

关于vue.js:几道蛮有意思的前端面试题

1.Object.is()与原来的比拟操作符“==”、“===”的区别?两等号判等,会在比拟时进行类型转换;三等号判等(判断严格),比拟时不进行隐式类型转换,(类型不同则会返回false) ;Object.is()在三等号判等的根底上特地解决了NaN、-0和+0,保障-0和+0不再雷同,但Object.is(NaN,NaN)会返回true。Object.is()应被认为有其非凡的用处,而不能用它认为它比其它的相等比照更宽松或严格。2.Virtual DOM的劣势在哪里?其实这道题目面试官更想听到的答案不是上来就说「间接操作/频繁操作DOM的性能差」,如果DOM操作的性能如此不堪,那么jQuery也不至于已经红透半边天。所以面试官其实更想听到VDOM想解决的问题以及为什么频繁的DOM操作会性能差。 首先咱们须要晓得:DOM引擎、JS引擎互相独立,但又工作在同一线程(主线程)。JS代码调用DOM API必须挂起JS引擎、转换传入参数数据、激活DOM引擎,DOM重绘后再转换可能有的返回值,最初激活JS引擎并继续执行若有频繁的DOM APl调用,且浏览器厂商不做"批量解决"优化,引擎间切换的单位代价将迅速积攒若其中有强制重绘的DOM API调用,从新计算布局、从新绘制图像会引起更大的性能耗费。 其次是VDOM和实在DOM的区别和优化: 虚构DOM不会立马进行排版与重绘操作虚构DOM进行频繁批改,而后一次性比拟并批改实在DOM中须要改的局部,最初在实在DOM中进行排版与重绘,缩小过多DOM节点排版与重绘损耗虚构DOM无效升高大面积实在DOM的重绘与排版,因为最终与实在DOM比拟差别,能够只渲染部分3.common.js和es6中模块引入的区别?Common.js是一种模块标准,最后被利用于Nodejs,成为Nodejs 的模块标准。运行在浏览器端的JavaScript因为也短少相似的标准,在ES6进去之前,前端也实现了一套雷同的模块标准(例如: AMD),用来对前端模块进行治理。自ES6起,引入了一套新的ES6 Module标准,在语言规范的层面上实现了模块性能,而且实现得相当简略,无望成为浏览器和服务器通用的模块解决方案。但目前浏览器对ES6 Module兼容还不太好,咱们平时在Webpack 中应用的export和import,会通过Babel转换为CommonJs标准。 在应用上的差异次要有: CommonJs模块输入的是一个值的拷贝,ES6模块输入的是值的援用CommonJS模块是运行时加载,ES6模块是编译时输入接口。CommonJs是单个值导出,ES6 Module能够导出多个CommonJs是动静语法能够写在判断里,ES6 Module动态语法只能写在顶层CommonJs的this是以后模块,ES6 Module的this是undefined4.JS代码中的use strict是什么意思?应用前与应用后的区别在哪?use strict是一种ECMAscript5增加的(严格)运行模式,这种模式使得Javascript 在更严格的条件下运行。 设立"严格模式"的目标,次要有以下几个: 打消Javascript语法的一些不合理、不谨严之处,缩小一些怪异行为;打消代码运行的一些不平安之处,保障代码运行的平安;进步编译器效率,减少运行速度;为将来新版本的Javascript 做好铺垫。区别: 禁止应用with语句。禁止this关键字指向全局对象。对象不能有重名的属性。请用JS判断给定的字符串是否是同构的。思路:能够用JS中的map函数判断字符串的值和索引 代码: const isIsomorphic = (s, t) => { if (s === t || s === '') return true let mapS = new Map(), mapT = new Map() for (let i = 0; i < s.length; i++) { if (mapS.has(s[i]) || mapT.has(t[i])) { if (mapS.get(s[i]) !== mapT.get(t[i])) return false}mapS.set(s[i], i)mapT.set(t[i], i)} return true}最初如果你感觉此文对你有一丁点帮忙,点个赞。或者能够退出我的开发交换群:1025263163互相学习,咱们会有业余的技术答疑解惑 ...

December 2, 2021 · 1 min · jiezi

关于vue.js:vue3-setup使用emit

在应用vue3 setup形式,组件开如时,emit事件须要提前申明。先通过defineEmits对以后组件所有须要用到的emit事件进行申明,实现如下代码。 defineEmits <script setup>const emit = defineEmits(["itemClick"]);//...const itemClick = () => { emit("itemClick", { ...itemdata });};</script>

December 2, 2021 · 1 min · jiezi

关于vue.js:Vue3

Vue3Vue3进去曾经有一段时间了,我也是早早就关注了3,看起来变动有不少。作为一个应用Vue框架的前端,必须去相熟理解一下。 Vue3新个性1.SFC:Composition Api(setup)setup提供了一系列可能在其函数外部应用的api,使得可能很好的将业务逻辑划分开来 setup improvement <script setup>// imported components are also directly usable in templateimport Foo from './Foo.vue'import { ref } from 'vue'// write Composition API code just like in a normal setup()// but no need to manually return everythingconst count = ref(0)const inc = () => { count.value++ }</script><template> <Foo :count="count" @click="inc" /></template>< script setup > setup improvement 使顶层的绑定会被裸露给模板应用组件,范畴里的值也能被间接作为自定义组件的标签名应用无需再注册,而引入的组件将被当作变量来应用递归组件,能够间接在模板应用而无需import定义props与emits必须通过defineProps与defineEmits不同于一般的setup函数,setup中是默认敞开的,如果要将外部属性裸露,则需应用defineEepose函数script setup领有顶层await状态驱动的动静 CSS Css能够通过v-bind绑定变量,且还反对表达式(须要括号),以前都是通过class来进行css的变动,当初通过状态驱动动静css可能带来更好的代码体验。 <script setup>const theme = { color: 'red'}</script><template> <p>hello</p></template><style scoped>p { color: v-bind('theme.color');}</style>生命周期 ...

December 2, 2021 · 1 min · jiezi

关于vue.js:Vue回调方法内获取不到当前组件this元素的解决方案

vue页面应用addEventListener,对页面元素增加事件监听,在addEventListener办法外部无奈获取data定义的变量值。 编写 videoList.vue 页面,页面代码如下所示。 <template> <div class="container"> <div class="video-list"> <div class="remote-video"> <div class="remote-video-item" v-for="pull in pullStreamList"> <video controls="controls" controlslist="nodownload" :disablePictureInPicture="true" autoplay="autoplay" :id="`remote-video-${pull.id}`"> <source src="http://vjs.zencdn.net/v/oceans.mp4" type="video/mp4"> </video> </div> </div> </div> </div></template><script> export default { name: "test", data(){ return{ pullStreamList:[], } }, mounted:function () { let _this = this; _this.pullStreamList.push({"id":"00001","name":"test00001"}); let timer = setInterval(function () { _this.removeRemoteVideo('00001'); clearInterval(timer) },10) }, methods:{ removeRemoteVideo:function (pullId) { let newRemoteVideo = document.getElementById("remote-video-" + pullId); console.log("newRemoteVideo",newRemoteVideo); console.log(" _this.pullStreamList before", this.pullStreamList); newRemoteVideo.addEventListener("play",function () { console.log(" _this.pullStreamList after", this.pullStreamList); }) } } }</script>页面输入_this.intervalList after的值是为undefinded,然而在_this.intervalList before输入的变量的确有内容的,两个this示意不同的对象。 ...

December 2, 2021 · 1 min · jiezi

关于vue.js:vue写的一个拖拽容器

<template> <div class="container" :style="containerStyle" @mousedown="mousedown($event)"> <div class="box-module" v-show="isDown"> <div class="box-line box-left" :style="leftStyle" :data-value="leftWidth"></div> <div class="box-line box-right" :style="rightStyle" :data-value="rightWidth"></div> <div class="box-line box-top" :style="topStyle" :data-value="topWidth"></div> <div class="box-line box-bottom" :style="bottomStyle" :data-value="bottomWidth"></div> </div> <div class="box-slot"> <slot></slot> </div> </div></template><script>export default { name: "Container", props: { left: { type: Number, default: 300 }, top: { type: Number, default: 50 }, }, data () { return { isDown: false, pos: { sx: 0, sy: 0, left: 0, top: 0, width: 0, height: 0, }, box: { width: 0, height: 0 } } }, computed: { containerStyle () { return { left: this.pos.left + 'px', top: this.pos.top + 'px', } }, leftWidth () { return this.pos.left + 'px' }, rightWidth () { return (this.box.width - this.pos.left - this.pos.width) + 'px' }, topWidth () { return this.pos.top + 'px' }, bottomWidth () { return (this.box.height - this.pos.top - this.pos.height) + 'px' }, leftStyle () { return { left: (-this.pos.left) + 'px', top: (this.pos.height / 2) + 'px', width: this.leftWidth, } }, rightStyle () { return { left: this.pos.width + 'px', top: (this.pos.height / 2) + 'px', width: this.rightWidth, } }, topStyle () { return { top: (-this.pos.top) + 'px', left: (this.pos.width / 2) + 'px', height: this.topWidth, } }, bottomStyle () { return { top: this.pos.height + 'px', left: (this.pos.width / 2) + 'px', height: this.bottomWidth, } }, }, created () { this.pos.left = this.left this.pos.top = this.top this.box.width = 3840 this.box.height = 1080 }, mounted () { this.children = this.$children[0] const rect = this.children.$el.getBoundingClientRect() this.pos.width = rect.width this.pos.height = rect.height }, methods: { mouseup () { this.isDown = false document.removeEventListener('mouseup', this.mouseup) document.removeEventListener('mousemove', this.mousemove) }, mousedown (event) { this.isDown = true this.rect = this.children.$el.getBoundingClientRect() this.pos.sx = event.pageX this.pos.sy = event.pageY document.addEventListener('mouseup', this.mouseup, false) document.addEventListener('mousemove', this.mousemove, false) }, mousemove (event) { if (this.isDown) { const dx = event.pageX - this.pos.sx const dy = event.pageY - this.pos.sy this.pos.left = this.rect.left + dx this.pos.top = this.rect.top + dy } }, }, beforeDestroy () { }}</script><style scoped lang="scss">.container{ position: absolute; &:hover { z-index: 999; } .box-slot { position: relative; z-index: 1; } .box-module { position: relative; z-index: 0; } .box-line { position: absolute; background: red; &.box-left { height: 1px; } &.box-right { height: 1px; } &.box-top { width: 1px; } &.box-bottom { width: 1px; } &::after { position: absolute; color: red; font-size: 16px; content: attr(data-value); left: 50%; top: 50%; transform: translate(-50%, -50%); } }}</style>

December 2, 2021 · 2 min · jiezi

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

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

December 2, 2021 · 1 min · jiezi

关于vue.js:vue自定义一个websocket工具函数

备注一个近期在做的我的项目下应用的websocket工具函数(理论利用场景为,某院下的排队叫号零碎,须要应用到websocket连贯,且自定义回调函数并按需解决 )应用步骤大抵如下:我的项目根门路下新建一个websocket.js文件,文件内容如下 let ws = nulllet _data = nulllet _url = nulllet _callback = nulllet hearBeatTimer = nulllet reconnectTimer = nulllet reconnectNum = 0 // 重连次数const time = 3000 // 心跳距离const reconnectTime = 5000 // 重连超时export function webSocket(url = '', data = '', callback = () => {}) { // 初始化 _url = url // 地址 _data = data // 发送音讯 _callback = callback // 回调函数,利用闭包 createWebSocket() // 创立 webSocket}export function getWebSocket() { return ws}export function closeWebSocket() { console.log('敞开WebSocket') if (ws) { ws.onerror = () => {} ws.onclose = () => {} ws.close() } ws = null _data = null _url = null _callback = () => {} // timeoutTimer = null hearBeatTimer = null reconnectTimer = null}function createWebSocket() { console.log('创立WebSocket') if (!_url) return if (ws) { ws.close() ws = null } ws = new WebSocket(_url) ws.onopen = function() { sendMessage() heartBeat() } ws.onmessage = function(e) { console.log('音讯事件:', e) // clearTimeout(timeoutTimer) if (typeof _callback === 'function') { _callback(e) } reconnectNum = 0 heartBeat() } ws.onerror = function() { reconnect() } ws.onclose = function() { reconnect() }}function heartBeat() { if (hearBeatTimer) { clearTimeout(hearBeatTimer) } hearBeatTimer = setTimeout(() => { if (ws && ws.readyState === 1) { // 如果连贯失常 sendMessage() // setTimeoutTimer() } else { reconnect() } }, time)}function sendMessage() { console.log('发送音讯:', _data) if (!ws) return switch (Object.prototype.toString.call(_data)) { case '[object Object]': ws.send(JSON.stringify(_data)) break case '[object String]': ws.send(_data) }}function reconnect() { if (reconnectTimer) { clearTimeout(reconnectTimer) } reconnectTimer = setTimeout(() => { reconnectNum++ console.log('重连WebSocket') console.log('重连次数:', reconnectNum) webSocket(_url, _data, _callback) }, reconnectTime)}window.onbeforeunload = () => { closeWebSocket()}2.在app.vue 下援用并初始化websocket ...

December 1, 2021 · 2 min · jiezi

关于vue.js:混合开发入门-Vue结合AndroidiOS-开发仿京东项目App无密

download:混合开发入门 Vue联合Android/iOS 开发仿京东我的项目App一 为什么使用内部文件当JavaScript脚本代码很简单或多个HTML页面需要使用到JavaScript脚本时,可能将JavaScript脚本的代码编写到一个内部文件中,总体来说使用内部文件有以下长处。易保护将JavaScript编写在多个页面中,在查找谬误或在修改代码时会非常麻烦。如果将JavaScript编写在内部文件中,在保护时会提高保护效率和俭约保护的工夫。重用性使用JavaScript内部文件可能避免重复编写代码。在多个页面中使用雷同的JavaScript时可能将其编写到内部文件中,俭约开发工夫。俭约加载页面工夫把一段JavaScript代码编写到多个页面中,岂但减少了开发工夫,还减少了页面大小和页面加载的工夫。如果把JavaScript编写到内部文件中,当多个页面使用同一个内部文件时,只需要加载一次,俭约了页面加载工夫,放慢了页面浏览速度。二 使用src属性调用内部文件在创建JavaScript脚本的内部文件时不需要使用标记,然而文件的扩展名必须使用.js类型。调用内部文件可能使用标记的src属性。如果JavaScript脚本内部文件保存在本机中,src属性可能是相对路径或是绝对路径。如果JavaScript脚本内部文件保存在其余服务器中,src属性需要指定相对的路径。 div<input type = "button" value="红色" nclick="changcolor(this)"><input type = "button" value="彩色" nclick="changcolor(this)"> css文件为mycss.css: .style{width:600px;height:300px;background-color:red;} people{width:300px;}.card{width:123px;height:444px;}

November 30, 2021 · 1 min · jiezi

关于vue.js:自定义指令实现渐进加载图片

开发背景咱们网站内的所有图片都是从上到下扫描渲染的,如果网速较慢的时候,图片由0到1的整个过程将会呈现较长的耗时,且留有较长的空白工夫,针对这一问题,起初我的做法通常都是应用一张占位图,然而实在图片替换占位图的过程会呈现闪动的景象,于是我应用了渐进加载图片的形式对我的项目进行了优化。 渐进加载的整体流程?页面中的图片能够先加载一个图片的含糊轮廓(小图),随着图片加载时长的减少,图片会逐步变得清晰。 这里咱们须要留神几个问题: 如何使用户无感知的替换新老图片?如果页面内须要渲染多个图片,那咱们岂不是要多增加n个DOM? 理论开发咱们我的项目中图片均是通过oss存储的,所以小图能够通url+参数的模式获取。例如,http://image-demo.oss-cn-hang...,h_100,m_lfit 。如果应用的是别的链接均可自行替换 增加自定义指令,因为我的项目中多个中央均需应用,所以采纳的是全局增加的模式。 import Vue from 'vue'const gradual = Vue.directive('gradual', {bind(el, binding) { instertDom(el, binding)},})export default gradual我的项目中所有须要用到渐进加载的图片咱们均能够先用小图替换。实在图片咱们能够通过指令传值的模式发送进来。 <img v-gradual="{src: $img + item.extend.titleImg}":src="$img + item.extend.titleImg + '?x-oss-process=image/resize,l_50'"alt=""/>加载大小图片的比照 新图片的增加及含糊图片的替换 之前提到的问题一咱们能够通过透明度由1变0的过渡成果,对含糊图片进行暗藏,其中应用的filter:blur()是为了保障含糊图片的像素化不会那么显著。针对问题二,采纳的是img标签的onload事件,在判断大图加载实现后,先对原有DOM增加暗藏成果,而后通过设置定时器的形式删除原有DOM,这里的定时器delay要大于等于过渡动画中的delay,以保障过渡成果全副显示实现。css局部 .gradual .vague{ filter: blur(2px); } .gradual img.gradual-hide_img { opacity: 0; animation: origin 1s ease; } .gradual img.gradual-hide_img { position: absolute; left: 0; top: 0; } @keyframes origin { 0% { transform: scale(1); opacity: 1; } 100% { transform: scale(1.1); opacity: 0; } }js局部 ...

November 30, 2021 · 1 min · jiezi

关于vue.js:模拟-Vuejs-响应式原理

数据驱动开发过程中只须要关注数据,而不须要关系数据如何渲染到视图数据响应式:数据批改时,视图会随之更新,防止 DOM 操作双向绑定:数据扭转,视图扭转;视图扭转,数据扭转公布订阅模式和观察者模式定义了对象间一种一对多的依赖关系,当指标对象的状态产生扭转时,所有依赖它的对象都会失去告诉。观察者模式发布者:具备 notify 办法,当发生变化时调用观察者对象的 update 办法观察者:具备 update 办法 class Subscriber { constructor () { this.subs = [] } add(sub) { this.subs.push(sub) } notify() { this.subs.forEach(handler => { handler.update() }) } } class Observer { constructor (name) { this.name = name; } update() { console.log('接到告诉', this.name); } } const subscriber = new Subscriber(); const jack = new Observer('jack'); const tom = new Observer('tom'); subscriber.add(jack) subscriber.add(tom) subscriber.notify()公布订阅模式公布订阅模式与观察者模式的不同,在发布者和观察者之间引入了事件核心。使得指标对象并不间接告诉观察者,而是通过事件核心来派发告诉。 class EventController { constructor() { this.subs = {} } subscribe(key, fn) { this.subs[key] = this.subs[key] || [] this.subs[key].push(fn) } publish(key, ...args) { if (this.subs[key]) { this.subs[key].forEach(handler => { handler(...args) }); } } } const event = new EventController() event.subscribe('onWork', time => { console.log('下班了', time) }); event.subscribe('offWork', time => { console.log('上班了', time); }); event.subscribe('onLaunch', time => { console.log('吃饭了', time); }); event.publish('offWork', '18:00:00'); event.publish('onLaunch', '20:00:00');总结观察者模式是由具体指标调度,事件触发时发布者会被动调用观察者的办法,所以发布者和观察者之间存在依赖公布订阅模式是由事件核心对立调度,因为发布者和订阅者二者之间没有强依赖关系数据响应式外围原理Vue2当你把一个一般的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并应用 Object.defineProperty 把这些 property 全副转为 getter/setter。Object.defineProperty 是 ES5 中一个无奈 shim 的个性,这也就是 Vue 不反对 IE8 以及更低版本浏览器的起因。 function proxyData(data) { // 遍历 data 对象的所有属性 Object.keys(data).forEach(key => { // 把 data 中的属性,转换成 vm 的 setter/setter Object.defineProperty(vm, key, { enumerable: true, configurable: true, get () { console.log('get: ', key, data[key]) return data[key] }, set (newValue) { console.log('set: ', key, newValue) if (newValue === data[key]) { return } data[key] = newValue // 数据更改,更新 DOM 的值 document.querySelector('#app').textContent = data[key] } }) }) }因为 JavaScript 的限度,Vue 不能检测以下数组的变动: ...

November 30, 2021 · 4 min · jiezi

关于vue.js:VueRouter-实现原理

Hash 和 History 模式Hash 模式http://localhost.com/#/user/id Hash 模式基于锚点,以及 onhashchange 事件。 通过 window.location.href 改变浏览器地址, 如果只扭转 # 前面的地址,不会触发服务端申请,会把 # 后的值作为路由地址当地址发生变化时触发 onhashchange 事件,监听事件并做相应解决切换显示不同的组件History 模式http://localhost.com/user/id History 模式基于 HTML5 中的 History API 通过 history.pushState() 办法扭转浏览器地址,只会扭转浏览器地址而不会向服务端发送申请,并把以后地址记录到浏览器的历史记录中 history.pushState():不会向服务端发送申请,pushState 会在 history 栈中增加一个新的记录history.replaceState(): 不会向服务端发送申请,replaceState 不会增加新的 history 栈记录,而是替换以后的url监听 popstate 事件,能够监听到浏览器历史数据的变动。事件不会在 pushStash 或 replaceStash 中触发,只会在浏览器后退或回退时触发依据以后路由地址找到对应组件从新渲染nginx环境配置 location / { root html; index index.html index.htm; #新增加内容 #尝试读取$uri(以后申请的门路),如果读取不到读取$uri/这个文件夹下的首页 #如果都获取不到返回根目录中的 index.html try_files $uri $uri/ /index.html;}模仿实现创立 VueRouter 插件,静态方法 install 判断插件是否曾经被加载当 Vue 加载的时候把传入的 router 对象挂载到 Vue 实列上(全局混入的目标是拿到 Vue 实列)创立 VueRouter 类 ...

November 30, 2021 · 2 min · jiezi

关于vue.js:Virtual-DOM

虚构 DOM一般 JS 对象形容 DOM 对象DOM 对象:成员多,老本高 虚构 DOM { sel: 'div', //节点的选择器 data: {}, // 一个存储节点属性的对象,对应节点的sel[prop]属性,例如onclick , style text: 'Hello', //如果是文本节点,对应文本节点的textContent,否则为null children: undefined, //存储子节点的数组,每个子节点也是vnode构造 elm: undefined, //对实在的节点的援用 key: 'msg',}为什么应用虚构 DOM保护视图和状态的关系,虚构 DOM 能够维护程序状态,跟踪上一次的状态简单视图状况下晋升渲染性能,通过比拟前后两次差别更新实在 DOM跨平台 浏览器平台渲染 DOM服务端渲染 SSR(Nuxt.js/Next.js)原生利用(Weex/React Native)小程序(mpvue/uni-app)虚构 DOM 库Snabbdom Vue2.x 外部应用的 Virtual DOM 就是革新的 Snabbdom通过模块可扩大源码应用 TypeScriptvirtual-domSnabbdom// 1. 导入模块import { init, h, styleModule, eventListenersModule } from 'snabbdom';// 2. 注册模块const patch = init([ styleModule, eventListenersModule]);// 3. 应用h() 函数的第二个参数传入模块中应用的数据(对象)let vnode = h( 'div', [ h( 'h1', { style: { backgroundColor: 'red' } }, 'Hello World' ), h( 'p', { on: { click: eventHandler } }, 'this is button' )])function eventHandler () { alert('hello')}let app = document.querySelector('#app')patch(app, vnode)init ...

November 30, 2021 · 2 min · jiezi

关于vue.js:Vuejs-源码剖析

1、简述 Vue 首次渲染的过程。 1.Vue 初始化,调用 new Vue() 之前,曾经初始化结束实例成员 _init() 办法$data、$props、$set、$delete、$watch 属性_update、$forceUpdate、$destroy 生命周期相干办法$on、$once、$off、$emit 事件$nextTick、_render 办法静态方法 config、observable、util 对象options 对象,并扩大 components、directives、filters、_base 办法set、delete、nextTick 办法keep-alive 组件Vue.use()、Vue.mixin()、 Vue.extend()、Vue.directive()、 Vue.component()、Vue.filter()平台相干 全局之类:v-model、v-show全局组件:v-transition、v-transition-group全局办法:__patch__、$mount$mountVue.compile()2.实例化 Vue,调用 this._init() 办法vm 的生命周期相干变量初始化,$children/$parent/$root/$refsvm 的事件监听初始化,父组件绑定在以后组件上的事件vm 的编译 render 初始化,$slots/$scopedSlots/_c/$createElement/$attrs/$listenersbeforeCreate 生命钩子回调把 inject 的成员注入到 vm 上初始化 vm 的 _props/methods/_data/computed/watch初始化 provide调用 entry-runtime-with-compiler.js入口文件中的 this.$mountcreated 生命钩子回调3.编译模板,此处有两个 this.$mount 函数entry-runtime-with-compiler.js文件中的 this.$mount,这个$mount() 的核心作用是帮咱们把模板编译成 render 函数 将 /src/platforms/web/runtime/index.js文件中的 this.$mount 中的 $mount 保留后重写判断 options 中是否存在 render 函数,如果存在间接调用 /src/platforms/web/runtime/index.js 中的 $mount不存在则将编译 template 模板 获取 options 中的 template,如果不存在则将获取 el 的 outerHTML 作为模板如果存在的话获取对应 DOM 对象的 innerHTML 作为模板 ...

November 30, 2021 · 2 min · jiezi

关于vue.js:Vuex-数据流管理

组件通信父子组件传值通过 props 向子组件传递数据 Parent <template> <div> <h1>父给子传值</h1> <child title="My journey with Vue"></child> </div></template><script>import child from './Child'export default { components: { child }}</script>Child <template> <div> <h1>Props Down Child</h1> <h2>{{ title }}</h2> </div></template><script>export default { // props: ['title'], props: { title: String }}</script>子父组件传值通过监听子组件事件 Parent <template> <div> <h1>子给父传值</h1> 这里的文字不须要变动 <child :fontSize="hFontSize" @enlargeText="enlargeText"></child> </div></template><script>import child from './Child'export default { components: { child }, data () { return { hFontSize: 1 } }, methods: { enlargeText (size) { this.hFontSize += size } }}</script>Child ...

November 30, 2021 · 3 min · jiezi

关于vue.js:Vue-服务端渲染

什么是服务器端渲染 (SSR)?Vue.js 是构建客户端应用程序的框架。然而能够将组件在服务器端渲染为 HTML 字符串,将它们间接发送到浏览器,最初将这些动态标记"激活"为客户端上齐全可交互的应用程序。 为什么应用服务器端渲染 (SSR)?更好的 SEO,因为搜索引擎爬虫抓取工具能够间接查看齐全渲染的页面。更快的响应工夫,无需期待 JavaScript 加载衡量?开发条件所限波及构建设置和部署的更多要求更多的服务器端负载根本应用装置npm install vue vue-server-renderer --S渲染const Vue = require('vue')const { createRenderer } = require('vue-server-renderer')const app = new Vue({ template: `<div>Hello World</div>`})createRenderer().renderToString(app, (err, html) => { console.log(html);})集成服务器装置 Express npm install express --saveconst Vue = require('vue')const { createRenderer } = require('vue-server-renderer')const express = require('express')const server = express()const app = new Vue({ template: `<div>Hello 小王</div>`})server.get('/', (req, res) => { createRenderer().renderToString(app, (err, html) => { res.end(html) })})server.listen('3000')应用页面模板在下面的案例中咱们会发现中文显示乱码,起因是因为编译后的 HTML 文件短少编码等阐明 ...

November 30, 2021 · 9 min · jiezi

关于vue.js:httplxgongxuanwangcomsszt36htm

POP/POP3协定:(Post Office Protocol)邮件接管协定(默认端口110):遴选公务员当用户计算机与反对POP协定的电子邮件服务器连贯时,把存储在该服务器的电子邮箱中的邮件准确无误地下载到用户的计算机中。http://lx.gongxuanwang.com/lx... POP3属于离线式协定,即不能对邮件进行在线操作,必须下载到本地能力进行解决。POP协定已倒退到第三版,称作POP3。 POP3与SMTP一样都是申请响应协定,命令与响应也都是用NVT ASCII格局的文本示意。POP3响应由一个状态码和其后的附http://lx.gongxuanwang.com/lxzt/lxbszt/84800.html 加信息组成,只有两种状态码:"+OK"(正确)和"-ERR"(失败) IMAP协定(Internet Message Access Protocol)Internet音讯拜访协定(默认端口143): 它是对POP3协定的一种扩大,[遴选公务员](http://lx.gongxuanwang.com/)也是定义了邮件客户端软件和IMAP邮件服务器的通信规定,它运行在TCP/IP协定之上,与POP3的次要区别 是这个IMAP协定能够在线操作,能够不必把用户的所有邮件下载,能够通过客户端间接对服务器上的邮件在线操作http://lx.gongxuanwang.com/

November 29, 2021 · 1 min · jiezi

关于vue.js:基于Vue3-Vite-TS二次封装elementplus业务组件

威❤ itspcool 一起交流学习装置 vue-router,vuexnpm i vue-router@next vuex@nextvue-router在 src 目录下新建 router/index.ts import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'import HelloWorld from '../components/HelloWorld.vue'const routes: Array<RouteRecordRaw> = [ { path: '',redirect: (_) => { return { path: '/home' }},}, { path: '/home',name: 'HelloWorld',component: HelloWorld,}, { 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" */ '../components/About.vue'),}, { ...

November 29, 2021 · 2 min · jiezi

关于vue.js:js-进入全屏-和-退出全屏

//进入全屏 document.documentElement.requestFullscreen();//退出全屏 document.exitFullscreen().then(res=>{ }).catch(err=>{ })

November 29, 2021 · 1 min · jiezi

关于vue.js:vuenextTick使用

vue.$nextTick应用前言在做一个用v-if管制input暗藏显示的性能时,显示后须要设置inpu焦点,然而ref设置焦点时,获取到的却是undefined。 思路查找材料后,发现是因为input关上后立刻就取查看数据导致的。就是说,在关上显示input时,vue并没有马上去更新dom数据,而是先将这个操作放入一个队列中;如果咱们是反复执行的话,队列还会进去反复操作;等同一事件循环中的所有数据变动实现后,再进行解决队列中的数据。 为了在数据更新操作之后操作dom,所以能够在数据变动之后立刻应用vue.$nextTick,这样回调函数会在DOM更新实现后被调用,就能够获取最新的DOM元素。 理解$nextTickvue官网文档的解释为: 在下次 DOM 更新循环完结之后执行提早回调。在批改数据之后立刻应用这个办法,获取更新后的 DOM。 简略的了解就是:当数据更新了,在dom中渲染后,主动执行该函数。 会用到的小知识点宏工作(macrotask) 主代码块,setTimeout,setInterval, setImmediate,MessageChannel,postMessage 微工作(microtask) promise,MutationObserver 工作执行程序以及渲染的执行 macrotask -> microtask -> 渲染 -> macrotask -> microtask -> 渲染 -> ...... 源码剖析const callbacks = []let pending = falselet timerFuncexport function nextTick (cb?: Function, ctx?: Object) { let _resolve callbacks.push(() => { if (cb) { try { cb.call(ctx) } catch (e) { handleError(e, ctx, 'nextTick') } } else if (_resolve) { _resolve(ctx) } }) if (!pending) { pending = true timerFunc() } // $flow-disable-line if (!cb && typeof Promise !== 'undefined') { return new Promise(resolve => { _resolve = resolve }) }}从这段源码中,能够看到它基本上做的事件就是在nextTick的外层定义变量就造成了一个闭包,所以咱们每次调用$nextTick的过程其实就是在向callbacks新增回调函数的过程。 ...

November 29, 2021 · 2 min · jiezi

关于vue.js:后端小伙伴来学前端了VueRouter-路由各种跳转传参小知识

前言学完Vuex方面的操作就该来学学Vue中的路由操作了.... xdm冲 一、装置vue-cli 装置 vue add router 做完这一步根底环境都搭好了。 我的项目中会多一个 文件夹,内容如下: 最初裸露进去,在mian.js 中援用进去就能够了。临时先不细讲。 二、根本路由应用根本路由应用,其实你装置完就曾经有例子啦。 在App组件中 有上面这两行代码,其实就路由跳转的意思。 <router-link to="/">Home</router-link> |<router-link to="/about">About</router-link> |咱们以前是用a标签,这里只是帮咱们封装了。这里配置好的/及/about都是router文件夹下配置好的路由规定,每个门路和哪个组件绝对应。 成果如下: 点击就能跳转. 这是最根底的,看看就完事了,因为咱们应用这种形式挺少的,基本上在路由跳转的过程中都是要做很多事件的. 然而大家发现了没有,只有内容变了,为啥呢? 因为app组件中 <router-view/> 这个代码,意思就是切换路由时,将组件内容放到这里展现。 这最根本的,大家轻易玩玩都会的,咱们不多说。 问个小问题,这个路由跳转的过程中,原来的哪个组件是被暗藏了,还是销毁了呢??? 三、嵌套路由(套娃)效果图: 就是在home和about下别离来个路由,也非常容易。 咱们先加两个组件 咱们再router中进行配置一下。 const routes = [ { path: '/', name: 'Home', component: Home, children: [ { path: '/message', name: 'message', component: () => import(/* webpackChunkName: "about" */ '../components/Message.vue'), } ] }, { path: '/about', name: 'About', component: () => import(/* webpackChunkName: "about" */ '../views/About.vue'), children: [ { path: '/news', name: 'news', component: () => import(/* webpackChunkName: "about" */ '../components/News.vue'), }, ] }]其实也就牵扯到children这一个属性,就是和下级路由造成父子关系啦。套娃两层是这么套,那么套再多就是在外面接着写就完事了。 ...

November 28, 2021 · 3 min · jiezi

关于vue.js:vue实用

页面跳转<router-link to="shopList"> /* 内容 */</router-link>HTML赋值:style="[{height:CustomBar + 'px'}]"

November 27, 2021 · 1 min · jiezi