Vue

今天在项目开发时,由于素材都是存在本地了,然后还没压缩,导致小程序项目超出了2MB,然后无法编译了,就了解了一下分包,在采取分包后,顺利解决!本篇文章中,小程序采用的是Uniapp框架,和原生小程序中的分包流程相同,只不过无需修改manifest.json文件。分包简介在微信小程序中,默认只有一个主包,在项目打包时,所有的资源(页面及资源等)都被放到了主包中。造成的问题:在小程序中,主包的体积最大只可以达到2MB,如果超出了2MB,则不通过了。对于以上的问题,可以采取分包,分包就相当于将指定的页面及资源,单独放在一个包中,不在放到主包中,从而减少主包的体积。分包的上限及条件:开发者可以分N个包,但是要求每个包不允许超过2MB,整个小程序所有分包大小不能超过20MB。分包的好处:主包中一般存放的都是Tabbar页面,如果将非Tabbar页面从主包中移除,则可以加快加载速度。分包中的内容,默认不加载,只有需要用到它时,再去现场加载,当然,可以通过分包预下载去提前加载分包中的内容。使用分包-uniapp注意:如果是Tabbar页面,或者是多个分包需要用到的公共资源,请放到主包中。分包可以访问主包中的资源,而主包不允许访问分包中的资源。假设:现在有一个用户端[公共的],一个管理端[需要权限],我们可以将用户端放到主包中,将管理端的内容分成一个包。因为用户在进入小程序时,默认进入的都是用户端,没必要将管理端的资源也加载上,只有当拥有权限并且在切换到管理端时,我们在去加载管理端的内容。//当前文件结构树[未分包],默认都存放到pages中,当分包后,pages中的内容就是主包的内容。pages:|-...//假设用户端页面有N个,这里就不写了|-backStage/index/index.vue:管理端首页|-backStage/xxxxx/index.vue:管理端第二页/*分包准备:1.新建一个文件夹,和pages同级,*每个文件夹相当于一个分包*,并将静态资源命名为static然后放到分包的根目录下。2.在该分包下新建一个pages文件夹,该文件夹中存储页面文件夹。3.然后将分包中的内容,从主包中移走。*///主包pages:|-...//用户端的内容//管理端分包backStagePackage:|-pages:管理端页面|-index/index.vue:管理端首页|-xxxxx/index.vue:管理端第二页|-static:静态资源然后打开manifest.json文件,在mp-weixin节点中的根节点下,添加配置:"optimization":{"subPackages":true}接着打开pages.json配置分包:在和pages同级节点下,添加subPackages字段,值为数组,它用于配置分包。它的每一个元素是一个对象,每个元素及为一个分包。使用管理端分包为例,首先在数组中添加一个对象,对象中拥有:root,pages,name,independent字段。root属性:它的值为分包文件夹的名称,即:backStagePackage。pages属性:它的值为一个数组,每一个元素填写分包中的页面路径即可(不需要加上分包名)。name属性:分包别名,分包预下载时可以使用。independent属性:是否开启独立分包,默认不开启(false)。"subPackages":[{"root":"backStagePackage","pages":["pages/index/index","pages/xxxxx/index"]}]

2022-7-14 135 0
2022-6-12 183 0
Vue

1.优化前先分析依赖//首先安装依赖npminstallwebpack-bundle-analyzer--save-dev//然后在vue.config.js中进行引入constBundleAnalyzerPlugin=require('webpack-bundle-analyzer').BundleAnalyzerPlugin;//然后添加如下代码configureWebpack:{plugins:[newBundleAnalyzerPlugin({analyzerMode:'server',analyzerHost:'127.0.0.1',analyzerPort:8888,reportFilename:'report.html',defaultSizes:'parsed',openAnalyzer:true,generateStatsFile:false,statsFilename:'stats.json',statsOptions:null,logLevel:'info'}),]}当打包或者运行时,会在本地8888端口展示依赖情况,然后自行分析。2.采用路由懒加载在写路由时,不要将所有的组件都一下加载全,应该使用import()进行懒加载。这样只有当访问这个路由时,才会加载对应的模块。cosntroutes=[{path:"/home",component:()=>import('@/view/Home')//使用import进行懒加载}];3.进行GZIP压缩需要在Webpack中构建gz文件,然后在Nginx中启用gzip。//首先安装依赖npminstallcompression-webpack-plugin@1.1.12//然后在vue.config.js中进行引入constCompressionWebpackPlugin=require('compression-webpack-plugin');//然后添加以下代码configureWebpack:{plugins:[newCompressionWebpackPlugin({filename:'[path].gz[query]',algorithm:'gzip',test:/\.js$|\.json$|\.css/,threshold:10240,//只有大小大于该值的资源会被处理minRatio:0.8,//只有压缩率小于这个值的资源才会被处理})]}然后在Nginx中进行以下配置,启用GZIP。#开启gzip。gzipon;#开启后如果能找到.gz文件,直接返回该文件,不会启用服务端压缩。gzip_staticon;#文件大于指定size才压缩,以kb为单位。gzip_min_length1;#用于识别http协议的版本,早期的浏览器不支持gzip压缩,用户会看到乱码,所以为了持前期版本加了此选项,目前此项基本可以忽略gzip_http_version1.1;#压缩级别,1-9,值越大压缩比越大,但更加占用CPU,且压缩效率越来越低。gzip_comp_level9;#压缩的文件类型。gzip_typestext/cssapplication/javascriptapplication/json;使用CDN引入资源在打包时,会将import导入的东西,打包成js文件,然后该文件就会很大.如果我们的服务器带宽很小,那么还要加载这些资源就很慢,这样的话我们可以使用cdn的方式,去让用户请求其他服务器获取资源。我们需要在index.html中进行使用link或者script标签的方式去引入对应的资源。然后在vue.config.js中进行配置。//Key:和package中的名称一样,value:全局变量名//一定要将Vue引入[通过cdn,也要在这里进行配置],因为有些文件依赖着它。configureWebpack:{externals:{'vue':"Vue",'element-ui':"ELEMENT",'axios':'axios','jquery':'$','vue-router':'VueRouter','vuex':'Vuex'}}

2022-5-30 179 0
2022-5-28 125 0
Vue

1.安装npminstallvee-validate@2.0.02.引入该插件需要使用Vue.use引入,我们可以新建一个plugin文件夹,然后在里面进行引入。importVuefrom'vue';importVeeValidatefrom'vee-validate';此时,我们还没使用Vue.use()进行引入,我们可以先进行配置。constconfig={errorBagName:'errors',//为收集错误的对象起一个变量名,它存在每个组件的this中,如果和页面中的产生冲突,则可以更改这里delay:100,//表示获取输入信息的时间[毫秒]locale:'zh_CN',//验证消息的默认语言,一定要将这里写成zh_CN,否则自定义验证规则返回的验证消息是英文的。strict:true,//表示没有设置规则的表单不进行验证events:'input',//默认[input],input表示当输入时和表单失去焦点时都进行验证,blue表示当失去焦点时在验证。};然后进行引入。Vue.use(VeeValidate,config);3.基本使用此时,我们只能使用vee-validate提供的内置验证规则,用法如下。<!--1.我们必须为表单提供一个name属性,否则vee-validate不知道这个表单是哪一个。2.需要使用v-validate指令,来选择验证规则,我们可以输入单个也可以输入多个,可以使用字符串也可以使用对象形式。2.1(重要):如果使用字符串的方式,则需要在最""里面再写一个单引号将规则包住,否则会将规则名当成一个变量,第一个就是这样。--><inputname="age"v-validate="'required'"->单个规则写法v-validate="'required|between:1,120'"->多个规则写法,每个规则使用|管道符分隔v-validate="{required:true,between:[1,120]}"->对象写法,将需要的规则置true即可,此时不需要在里面包一层单引号了,如果其中的值是多个[例如between],则将值写成数组即可。/><!--1.这里是提示错误信息的,当使用该插件后,每个组件上都拥有了一个errors的计算属性[在config中可以修改该变量名]。2.errors是一个数组,里面存储的是错误信息,我们通过v-show来控制它是否显示,如果没有错误has()则返回一个false,那么该span就不显示。3.如果有错误了,那么has()则会返回一个true,那么我们就通过first()方法,拿到errors数组中的第一条错误信息来展示。4.注意(重要):在has()以及first()中,函数的参数值,都需要填写你校验关联表单的name值。--><spanclass="error-msg"v-show="errors.has('age')">{{errors.first('age')}}</span>所有内置规则:after{target}-比target要大的一个合法日期,格式(DD/MM/YYYY)alpha-只包含英文字符alpha_dash-可以包含英文、数字、下划线、破折号alpha_num-可以包含英文和数字before:{target}-和after相反between:{min},{max}-在min和max之间的数字confirmed:{target}-必须和target一样date_between:{min,max}-日期在min和max之间date_format:{format}-合法的format格式化日期decimal:{decimals?}-数字,而且是decimals进制digits:{length}-长度为length的数字dimensions:{width},{height}-符合宽高规定的图片email-不解释ext:[extensions]-后缀名image-图片in:[list]-包含在数组list内的值ip-ipv4地址max:{length}-最大长度为length的字符mimes:[list]-文件类型min-max相反mot_in-in相反numeric-只允许数字regex:{pattern}-值必须符合正则patternrequired-不解释size:{kb}-文件大小不超过url:{domain?}-(指定域名的)url4.将验证消息修改为中文我们首先将中文包引入进来,也需要将vee-validate下的Validator通过{Validator}方式引入进来。importzh_CNfrom'vee-validate/dist/locale/zh_CN';importVeeValidate,{Validator}from'vee-validate';//把这个代码,将最顶部相同的代码替换掉即可。然后创建一个对象:dict,该对象里有一个messages属性[值也是对象]。然后使用VeeValidate.Validator.localize(语言,dict对象)方法进行调用即可。vardict={messages:{...zh_CN.messages}};VeeValidate.Validator.localize("zh_CN",dict);5.修改字段名:此时,返回的验证消息显示的是phone,我们应该将它替换成显示手机号。我们只需要在dict对象中添加以下属性:attributes[它的值也是一个对象]。该对象中的key,就是你input中对应的name属性值。vardict={messages:{...zh_CN.messages,//在这里可以进行重写required:(field,args)=>`${filed}是一个必填内容!`},attributes:{phone:"手机号",code:"验证码"}};6.自定义验证规则:使用Validator.extend(规则名称,规则配置对象)方法可以自定义验证规则。在对象中,一共有两个必须定义的属性,它们都是一个函数。getMessage(field,args):返回的错误信息。field:字段名称,使用的是dict.attributes中的。args:在规则后携带的值。validate(value,args):验证规则,必须返回一个true或者false,或者是Promise实例。value:控件内输入的内容。该函数如果返回的是true,则代表着验证通过。该函数如果返回的是false,则代表不通过,那么就会执行getMessages函数,进行返回错误信息。//手机号验证规则Validator.extend('mobile',{getMessage:field=>`${field}格式不正确!`,validate:value=>/^[1][3-9][\d]{9}$/.test(value)//test是验证正则的,通过返回true});7.提交时验证是否通过在我们提交表单时,应该去判断所有字段都已经验证通过了。/*在提交时,应该先调用该方法,如果都已经验证通过,则返回一个true,否则返回false。*/constvaliRes=awaitthis.$validator.validateAll();if(!valiRes)return;//.......

2022-5-28 114 0
Vue

事件委托1.需求:在三级联动菜单中,我们一共有一千多个内容,并且需要点击其中的一个内容,就需要去跳转路由。2.解决分析:在渲染时为组件绑定上@click事件、使用事件委托。3.分析绑定@click:如果为每一个内容都绑定一个@click,那么就相当于添加了一千多个回调函数,对性能很不友好,但是可以实现功能。4.分析事件委托:如果我们为三级联动菜单的父元素添加一个点击事件,同样,也可以解决该问题,并且,采用该方式只需要添加一个@click,通过查找触发源去判断执行哪些操作。在JavaScript中,拥有事件冒泡的机制,当点击一个子元素时,触发父元素的事件,然后在爷爷元素触发事件,直到触发到祖元素的事件。在祖元素的点击事件回调函数中,拥有一个event属性,该属性是一个对象,里面有一个target属性,该属性存储的就是触发源头的DOM信息,这样就知道点击的哪个元素,从而触发了祖元素的事件。然后我们在通过自定义属性或者标签名,去判断该执行哪些操作。5.事件委托和事件冒泡:事件委托是利用事件冒泡的机制,它们并不一样。6.事件委托的缺点:如果在向上冒泡时,突然被某一层给把事件冒泡阻止掉了[event.stopPropagation],那么就不会冒泡到祖元素了,接着事件委托对应的处理函数也就不会执行了。对于不支持冒泡的事件,无法向上级传递。

2022-5-3 92 0
Vue

1.说明在编程式路由导航当中,如果重复点击一个链接[路由导航],那么就会抛出一个NavigationDuplicated异常,该异常并不会影响我们的程序执行。在声明式路由导航中,不会出现这种情况。这种情况只会在vue-router@3.1.0+版本出现,因为它引入了primise。目前@3.1.1版本,官方已经修复了此问题。2.为什么会出现这样的错误router.push(location,onComplete?,onAbort?)router.replace(location,onComplete?,onAbort?)以上是路由跳转的两个函数,注意看它的第二个和第三个参数,在官方文档中是这么写的:当导航跳转成功完成之后,会执行onComplete回调,它相当于resolve。当导航到相同的路由,或者此次路由未导航成功之前,又导航到其他路由时就会执行onAbort回调,它相当于reject。在@3.1.0+后,可以省略这两个参数,如果忽略了,那么就会返回一个Promise。如果填写了这两个参数,返回的就是undefined。那么,当没有传递第二个和第三个参数时,并且点击的是同一个导航,就会返回reject。当返回reject后,我们并未捕获这个错误,然后控制台就会报红。解决办法【3.3为最优方法】3.0:降级处理,使用#3.1.1版本。3.1:在调用方法时,传递上第二个和第三个参数。this.$router.push("/search",()=>{},()=>{});3.2:在push后链式调用catch()方法,捕获错误。注意:不能使用try…catch的形式去捕获,这种捕获方式只能捕获同步方法的错误。this.$router.push("/search").catch((err)=>{});3.3:对push和replace方法进行二次封装,在router->index.js中封装即可。//保存一份原有的方法letoriginPush=VueRouter.prototype.push;letoriginReplace=VueRouter.prototype.replace;//修改原型上的函数内容,如果传递了resolve和reject则使用传递的,否则默认处理内容为空//在调用原有的push时[相当于调用上面保存的那一份],应该让VueRouter实例调用,应该修改上下文。VueRouter.prototype.push=function(location,resolve,reject){if(resolve&&reject){originPush.call(this,resolve,reject)}else{originPush.call(this,location,(res)=>{},(err)=>{});}}VueRouter.prototype.replace=function(location,resolve,reject){if(resolve&&reject){originReplace.call(this,resolve,reject)}else{originReplace.call(this,location,(res)=>{},(err)=>{});}}

Vue

.sync修饰符:注意:该修饰符在Vue3.0版本中已经取消了,被替换成了v-model。1、简介:在一般情况下,当父组件给子组件传递一个自定义属性后,例如传递的自定义属性是一个字符串,那么我们在子组件中是不可以直接进行修改的,如果修改的话,就会报错。但是我们可以在父组件中为这个子组件的实例上绑定一个自定义事件,当子组件触发该自定义事件时,在去修改父组件中的数据,从而达到想要的效果。当我们使用.sync修饰符时,就相当于为被传递的自定义属性值,添加了一个双向绑定,从而就可以在子组件中,去直接修改父组件中的数据。2、未使用.sync修饰符修改父组件数据:顺序:首先在父组件中,为子组件传递数据,以及绑定自定义事件(changeText)。然后点击子组件中的按钮,触发自身实例上的自定义事件,从而修改父元素数据。页面:在父组件中,为子组件传递数据,以及绑定自定义事件。在changeText事件中,$event的值是$emit()触发事件时传递的值,然后这个值,就赋值给data中的text了,从而达到了子给父传值的效果。<divid="app"><test:prop-text='text'@changeText='text=$event'></test></div>子组件:接收父组件传递的自定义属性,在点击按钮时,触发changeText事件,并携带值。lettest={template:`<div><p>{{propText}}</p><button@click='changeText'>修改propText</button></div>`,props:["propText"],methods:{changeText(){this.$emit("propText","text的值被子组件修改咯!~");}}}父组件:注册子组件。constvm=newVue({el:"#app",data:{text:"我现在展示的是App组件的内容~"},components:{test},});3、使用.sync修饰符修改父组件数据-传递字符串:页面:对比第2行代码:在:prop-text后添加了.sync修饰符。并且将绑定的自定义事件删除了。<divid="app"><test:prop-text.sync='text'></test></div>子组件:对比第10行代码,触发的事件名需要写成以下格式,其中update:是固定的。update:在props中接收的属性名当触发该事件时,就会去寻找组件自身实例上prop-text属性绑定的值,然后去修改它。lettest={template:`<div><p>{{propText}}</p><button@click='changeText'>修改propText</button></div>`,props:["propText"],methods:{changeText(){this.$emit("update:propText","text的值被子组件修改咯!~");}}}父组件:constvm=newVue({el:"#app",data:{text:"我现在展示的是App组件的内容~"},components:{test},});

2022-4-1 536 0