前端总结1

一、css

1、Flex 布局

参考:http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html

1)flex-direction属性决定主轴的方向(即项目的排列方向)

它可能有4个值。

  • row(默认值):主轴为水平方向,起点在左端。
  • row-reverse:主轴为水平方向,起点在右端。
  • column:主轴为垂直方向,起点在上沿。
  • column-reverse:主轴为垂直方向,起点在下沿。

.top-banner {
  text-align: center;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

2)flex-grow属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。

如果所有项目的flex-grow属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。

3)flex-shrink属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。

 如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小。

4)flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。

5)flex 规定了弹性元素如何伸长或缩短以适应flex容器中的可用空间。这是一个简写属性,用来设置 flex-growflex-shrink 与 flex-basis,默认值为0 1 auto

 默认情况下,元素不会缩短至小于内容框尺寸,若想改变这一状况,请设置元素的min-width与 min-height属性。

flex 属性可以指定1个,2个或3个值。

单值语法: 值必须为以下其中之一:

  • 一个无单位数(<number>): 它会被当作<flex-grow>的值。
  • 一个有效的宽度(width)值: 它会被当作 <flex-basis>的值。
  • 关键字noneautoinitial.

双值语法: 第一个值必须为一个无单位数,并且它会被当作 <flex-grow> 的值。第二个值必须为以下之一:

  • 一个无单位数:它会被当作 <flex-shrink> 的值。
  • 一个有效的宽度值: 它会被当作 <flex-basis> 的值。

三值语法:

  • 第一个值必须为一个无单位数,并且它会被当作 <flex-grow> 的值。
  • 第二个值必须为一个无单位数,并且它会被当作  <flex-shrink> 的值。
  • 第三个值必须为一个有效的宽度值, 并且它会被当作 <flex-basis> 的值。

 

二、js

1、Promise 对象

参考:http://es6.ruanyifeng.com/#docs/promise

Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejected

const p = Promise.reject('出错了');
// 等同于
const p = new Promise((resolve, reject) => reject('出错了'))

p.then(null, function (s) {
  console.log(s)
});
// 出错了

Promise 实例具有then方法,也就是说,then方法是定义在原型对象Promise.prototype上的。它的作用是为 Promise 实例添加状态改变时的回调函数。前面说过,then方法的第一个参数是resolved状态的回调函数,第二个参数(可选)是rejected状态的回调函数。then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。Promise.prototype.catch方法是.then(null, rejection).then(undefined, rejection)的别名,用于指定发生错误时的回调函数。

getJSON('/posts.json').then(function(posts) {
  // ...
}).catch(function(error) {
  // 处理 getJSON 和 前一个回调函数运行时发生的错误
  console.log('发生错误!', error);
});

上面代码中,getJSON方法返回一个 Promise 对象,如果该对象状态变为resolved,则会调用then方法指定的回调函数;如果异步操作抛出错误,状态就会变为rejected,就会调用catch方法指定的回调函数,处理这个错误。另外,then方法指定的回调函数,如果运行中抛出错误,也会被catch方法捕获。一般来说,不要在then方法里面定义 Reject 状态的回调函数(即then的第二个参数),总是使用catch方法。

// bad
promise
  .then(function(data) {
    // success
  }, function(err) {
    // error
  });

// good
promise
  .then(function(data) { //cb
    // success
  })
  .catch(function(err) {
    // error
  });

上面代码中,第二种写法要好于第一种写法,理由是第二种写法可以捕获前面then方法执行中的错误,也更接近同步的写法(try/catch)。因此,建议总是使用catch方法,而不使用then方法的第二个参数。一般总是建议,Promise 对象后面要跟catch方法,这样可以处理 Promise 内部发生的错误。catch方法返回的还是一个 Promise 对象,因此后面还可以接着调用then方法。

 

三、webpack

1、代码分离

参考:https://webpack.docschina.org/guides/code-splitting/

https://router.vuejs.org/zh/guide/advanced/lazy-loading.html

代码分离是 webpack 中最引人注目的特性之一。此特性能够把代码分离到不同的 bundle 中,然后可以按需加载或并行加载这些文件。代码分离可以用于获取更小的 bundle,以及控制资源加载优先级,如果使用合理,会极大影响加载时间

1)入口起点

这是迄今为止最简单、最直观的分离代码的方式。不过,这种方式手动配置较多,并有一些隐患。

// webpack.config.js
module.exports = {
  entry: {
    index: './src/index.js',
    another: './src/another-module.js'
  }
};

隐患:如果入口 chunk 之间包含一些重复的模块,那些重复模块都会被引入到各个 bundle 中;这种方法不够灵活,并且不能动态地将核心应用程序逻辑中的代码拆分出来。

分离 app(应用程序) 和 vendor(第三方库) 入口:在 webpack < 4 的版本中,通常将 vendor 作为单独的入口起点添加到 entry 选项中,以将其编译为单独的文件(与 CommonsChunkPlugin 结合使用)。而在 webpack 4 中不鼓励这样做。而是使用 optimization.splitChunks 选项,将 vendor 和 app(应用程序) 模块分开,并为其创建一个单独的文件。不要 为 vendor 或其他不是执行起点创建 entry

2)防止重复

SplitChunksPlugin 插件可以将公共的依赖模块提取到已有的 entry chunk 中,或者提取到一个新生成的 chunk。

3)动态导入

当涉及到动态代码拆分时,webpack 提供了两个类似的技术。第一种,也是推荐选择的方式是,使用符合 ECMAScript 提案 的 import() 语法 来实现动态导入

动态地加载模块。调用 import() 之处,被作为分离的模块起点,意思是,被请求的模块和它引用的所有子模块,会分离到一个单独的 chunk 中

// 在注释中我们提供了 webpackChunkName。这样会将拆分出来的 bundle 命名为如mainPage.xxxx.js
export default new Router({
  mode: process.env.VUE_APP_ROUTE_MODE,
  base: process.env.BASE_URL,
  routes: [
    {
      path: '/',
      redirect: '/main'
    }, {
      path: '/main',
      component: AppMain,
      redirect: '/main/index',
      children: [{
        path: 'index',
        name: 'index',
        component: () => import(/* webpackChunkName: "mainPage" */ './views/Index'), // 首页
        meta: { title: '首页' }
      }, {
        path: 'prdRank',
        name: 'prdRank',
        component: () => import(/* webpackChunkName: "mainPage" */ './views/PrdRank'), // 游戏库
        meta: { title: '游戏库' }
      }, {
        path: 'orderList',
        name: 'orderList',
        component: () => import(/* webpackChunkName: "mainPage" */ './views/OrderList'), // 我的订单
        meta: { title: '我的订单' }
      }]
    }, {
      path: '/prdList',
      name: 'prdList',
      component: () => import(/* webpackChunkName: "prdPage" */ './views/PrdList') // 商品列表
    }, {
      path: '/prdDetail',
      name: 'prdDetail',
      component: () => import(/* webpackChunkName: "prdPage" */ './views/PrdDetail'), // 商品详情
      meta: { title: '商品详情' }
    }
  ]
})

webpackChunkName:新 chunk 的名称。

当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。结合 Vue 的异步组件和 Webpack 的代码分割功能,轻松实现路由组件的懒加载。

 把组件按组分块:有时候我们想把某个路由下的所有组件都打包在同个异步块 (chunk) 中。只需要使用 命名 chunk,一个特殊的注释语法来提供 chunk name (需要 Webpack > 2.4)。Webpack 会将任何一个异步模块与相同的块名称组合到相同的异步块中。

4)预取/预加载模块

在声明 import 时,使用下面这些内置指令,可以让 webpack 输出 "resource hint(资源提示)",来告知浏览器:

  • prefetch(预取):将来某些导航下可能需要的资源
  • preload(预加载):当前导航下可能需要资源

与 prefetch 指令相比,preload 指令有许多不同之处:

  • preload chunk 会在父 chunk 加载时,以并行方式开始加载。prefetch chunk 会在父 chunk 加载结束后开始加载。
  • preload chunk 具有中等优先级,并立即下载。prefetch chunk 在浏览器闲置时下载。
  • preload chunk 会在父 chunk 中立即请求,用于当下时刻。prefetch chunk 会用于未来的某个时刻。
  • 浏览器支持程度不同。

 2、缓存

  我们使用 webpack 来打包模块化的应用程序,webpack 会生成一个可部署的 /dist 目录,然后把打包后的内容放置在此目录中。只要 /dist 目录中的内容部署到 server 上,client(通常是浏览器)就能够访问网站此 server 的网站及其资源。而最后一步获取资源是比较耗费时间的,这就是为什么浏览器使用一种名为 缓存 的技术。可以通过命中缓存,以降低网络流量,使网站加载速度更快,然而,如果我们在部署新版本时不更改资源的文件名,浏览器可能会认为它没有被更新,就会使用它的缓存版本。通过必要的配置,以确保 webpack 编译生成的文件能够被客户端缓存,而在文件内容变化后,能够请求到新的文件。webpack 提供了一种使用称为 substitution(可替换模板字符串) 的方式,通过带括号字符串来模板化文件名。其中,[contenthash]substitution 将根据资源内容创建出唯一 hash。当资源内容发生变化时,[contenthash] 也会发生变化

  将第三方库(library)(例如 lodash 或 react)提取到单独的 vendor chunk 文件中,是比较推荐的做法,这是因为,它们很少像本地的源代码那样频繁修改。因此通过实现以上步骤,利用 client 的长效缓存机制,命中缓存来消除请求,并减少向 server 获取资源,同时还能保证 client 代码和 server 代码版本一致。

// webpack.config.js
optimization: {
    splitChunks: {
      cacheGroups: {
        vendors: {
          name: 'chunk-vendors',
          test: /[\\\/]node_modules[\\\/]/,
          priority: -10,
          chunks: 'initial'
        }
     }
  } }

而 vendor hash 发生变化是我们要修复的。幸运的是,可以使用两个插件来解决这个问题。第一个插件是 NamedModulesPlugin,将使用模块的路径,而不是一个数字 identifier。虽然此插件有助于在开发环境下产生更加可读的输出结果,然而其执行时间会有些长。第二个选择是使用 HashedModuleIdsPlugin,推荐用于生产环境构建

posted @ 2019-10-23 09:25  Colorful_coco  阅读(207)  评论(0编辑  收藏  举报