分类
webpack

如何使用webpack优化我们的项目

使项目更加合理

让项目兼容性更强

需要下载

    "babel-core": "^6.26.3",
    "babel-loader": "^7.1.5",
    "babel-plugin-transform-runtime": "^6.23.0",
    "babel-preset-env": "^1.7.0",
    "babel-preset-stage-2": "^6.24.1",

webpack.config.js

module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /(node_modules|bower_components)/,
                loader: 'babel-loader',
            }
        ]
    }

.babelrc

{
  "plugins": [
    [
      "transform-runtime",
      {
        "polyfill": false
      }
    ]
  ],
  "presets": [
    [
      "env",
      {
        "modules": false
      }
    ],
    "stage-2"
  ]
}

使项目加载速度更快

查看我们项目加载情况

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
 plugins: [
        new BundleAnalyzerPlugin(),
    ],

代码压缩分割

optimization: {
    splitChunks: {
      chunks: 'async', // initial 对入口文件拆分 all都包括
      minSize: 30000, // 小于这个数不拆分
      minChunks: 1, // 引入次数必须大于等于这个数才拆分
      maxAsyncRequests: 5, // 动态加载的js最多被拆分成5分
      maxInitialRequests: 3, // 入口文件最多拆分成三分
      automaticNameDelimiter: '~', // 名称分隔符
      name: true, // 默认是chunk的名字通过分隔符分割
      cacheGroups: { // 缓存组
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10 // 默认优先级
        },
        default: { // 其他第三方代码
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true // 已经拆分出来的代码是否被重用
        }
      }
    }
  }

多设置一个入口来分割代码

 entry: {
    index: './src/index.js',
    another: './src/another-module.js'
  },
分类
CSS

css加载优化

不参与首屏渲染的css异步加载

<link rel="stylesheet" href="/path/to/my.css" media="print" onload="this.media='all'">

media=“print”是打印时的css,因此它不会立刻加载,但是我们又希望加载后的css应用于所有屏幕,所以会有onload=”this.media=’all'”

将某一段css提升至很高的优先级

<link rel="preload" href="/path/to/my.css" as="style">

使用的是预加载技术

qi ye wei xin jie tu 16005895378073 1024x591 - css加载优化

根据不同的屏幕分辨率加载不同的css

<link rel="stylesheet" href="index.css" media="all" />
<link rel="stylesheet" href="mobile.css" media="(max-width:44.9375rem)" />
<link rel="stylesheet" href="table.css" media="(min-width: 45rem)" />

不同的页面加载不同的css

这方面vue做的很好,进入一个vue的路由,它将加载该路由下所有组件的style处的css,因此我们可以尝试减少公有的css,将特定使用的css放入组件内。

分类
解决方案

路由控制解决方案

权限,路由

lu you kong zhi liu cheng tu 647x1024 - 路由控制解决方案
路由控制流程图
deng lu yi ge you quan xian de ye mian 647x1024 - 路由控制解决方案
登录一个有权限的页面

q1: 在哪里进行路由拦截?

每次路由跳转之前进行拦截

// @/router/index.js
import Vue from 'vue';
import Router from 'vue-router';
// 页面路由
import routes from './routes';
// 路由拦截函数
import { routerBeforeEachFunc } from '@/config/interceptors/router';

Vue.use(Router);
const routerInstance = new Router({
  routes,
});
// 注入拦截器
routerInstance.beforeEach(routerBeforeEachFunc);
export default routerInstance;

main.js

// 获取@/router/index.js的routerInstance
import router from './router';
new Vue({
  router,
  render: h => h(App),
}).$mount('#app');

q2:是否需要控制这个判断有必要吗?

可有可无,这是作为一个框架来思考,或许某些项目不需要对路由进行控制,也没有菜单按钮权限管理等需求,就这可设置配置项为不需要控制路由。

q3:检查是否处理过权限与路由这个判断会以怎样的方式触发两种情况?

这个判断是以store中的一个属性值来判断的,默认值为false,因此会有这两种情况:1.已经登录过,在路由之间进行跳转。2.曾经登录过。重新打开浏览器,输入路由地址。

q4:如何存储token?

localStorage

q5:在有token的情况下,如何会因为异常跳转到login页?

调用用户接口失败或调动菜单接口失败

q6:在login页,怎样判断是重定向的路由还是就是在login的路由?

const redirect = decodeURIComponent(from.query.redirect || to.path);

q7:是否有权限函数做了什么?

我们在vue-router中定义了一些路由,某些路由需要权限的判定(页面权限,按钮权限),当拦截的路由符合权限判定的条件时,判断它是否有页面权限和按钮权限,而获取菜单权限时同时会获取到按钮权限,我们通过按钮权限进行一一比对得出该页面,该用户最终的权限。

分类
regex

正则表达式-判断不具有某些字段的字符串

做了一个安全中心项目,里面有一些密码验证,比较难的部分就是验证是否不具有某些字段的字符串了。

/^((?!boy|gril).)*$/

解析

/^((?!boy|gril).)*$/

这个星星举足轻重,有了它我们才能从开始到结尾,每一个位置都进行一次正则判定。

/^((?!boy|gril).)*$/

这个小点举足轻重,有了它才有了占位符,有了占位符才能做零宽度负预测先行断言(负前瞻,向后看看是否是我们不想要的内容,若是我们不想要的内容,则不通过此次正则判定)

/^((?!boy|gril).)*$/

负前瞻

/^((?!boy|gril).)*$/

如果没有开始它无法进行负预测,如果没有结尾它只要有一个位置符合后面没有boy或gril就会生效。

执行过程

  • 在^处判定后方是否有boy或gril,无保留占位符,
  • 在^.处判定后方是否有boy或gril
  • ……
  • 在^….$处判定后方是否有boy或gril,无,执行结束

在上方的某个步骤中判定中出现了boy或gril,则不符合正则的条件,跳出并返回false

(完)

2020-10-27补充

上述正则判断的是字符串在不具有boy的同时也不具有girl,要是我们想要判断的是可以有girl和boy但两者只能出现一个。

第一种情况,先遇到boy后不遇到gril

/^(?=(.boy))\1((?!gril).)$/

第二种情况,先遇到gril后不遇到boy

/^(?=(.gril))\1((?!boy).)$/

最终情况,遇到boy后不遇到gril或者遇到gril后不遇到boy结合在一起

/^((?=(.boy))\1((?!gril).)|(?=(.gril))\1((?!boy).))$/

分类
svg

数据大屏边框(1)续

第一次对数据大屏边框的尝试是对svg的基础运用。其中会造成各种问题导致无法在项目中实用。这次会在前一次的基础上做的一些优化。

数据大屏边框(1)

效果图

此次的优化项

1.动画

开头的动画采用smil(同步多媒体集成语言)动画的形式,每一个svg属性下都可以采用一个或多个smil动画。且由于同步的特性,一个动画的开始可以由另一个动画的结束为触发。第一个动画的开始采用了这一段代码。

<animate id="a1" attributeName="fill" restart="never" begin="indefinite" to="rgba(19,101,233,.4)" fill="freeze" dur="3s"></animate>
<script>
    document.addEventListener('click', function() {
        document.getElementById('a1').beginElement();
    })
</script>

而动画的效果是基于stroke,stroke-dasharray,stroke-dashoffset这三个属性。

 <path d="M 673 300 L 678 300 L 678 320 L 673 320 z" fill="transparent" stroke="rgb(14,80,191)" stroke-width="2"  stroke-dasharray="100,100" stroke-dashoffset="100" stroke-linejoin="round">
            <animate attributeName="stroke-dashoffset" dur="1s" to="0" begin="a2.end + 2.6" fill="freeze"></animate>
        </path>

以这段代码为例,首先这是一个小方块,它的初始状态里有stroke-dasharray=“100,100”,stroke-dasharray是将描边以虚线的形式展现,作用是100长度实线,100长度虚线,100长度实线,100长度虚线。。。显然,这个path组成的小方块并没有100那么长,但是没关系,只要比它实际的长度长就可以,这个实际的长度测算方式是在html页面中我们所能看到的长度,如果它被放大,那么实际的长度也会变大。而stroke-dashoffset的作用是偏移量,数值为正向左偏移。因此就变成了初始状态下,我们看不到东西的情况。

其次动画的状态也需要说明。attributeName=”stroke-dashoffset” – 动画改变的属性,fill=“freeze”-动画结束后以冻结的方式,不会回到初始状态。

2.适配各种大小

ui姐姐给出的设计稿是一张图片,因此每个元素的尺寸都是固定的,但是实际上我们的展示内容不可能与设计图的大小完全一致。所以需要加一些属性。

viewBox=“0 0 697 462”以x=0,y=0为基点,697为宽度,462为高度。

preserveAspectRatio=”none”,大小改变后的等比例收缩方式,none说明不按照等比例收缩

3.大小按等比例缩放后描边大小会跟着改变,但是不想让它改变

设置style属性

 path{
            vector-effect: non-scaling-stroke;
 }

(完)