前端星2020_4_11课程笔记

前端工程化

  • 规范化

    • 流程控制 git git flow

    • 编写规范

  • 模块化

    核心需求 避免变量污染

    • CSS模块化
    • JS模块化
  • 组件化

    对于UI和逻辑的封装

  • 自动化

    将重复费时的操作交给工具

    • 初始化 cli
    • 构建 webpack
    • 测试 jest
    • 部署 jenkins

JS动画

  • js的原生接口Animation
  • 月影介绍的各种原生实现 当然会更灵活 因为本质就是代码实现数学公式QAQ 本来不想抄下来 但是据说要回收课程资格5555 抄一份当手册好了

通用的抽象接口 线性++:

function update({target}, count) {
  target.style.transform = `rotate(${count++}deg)`;
}

class Ticker {
  tick(update, context) {
    let count = 0;
    requestAnimationFrame(function next() {
      if(update(context, ++count) !== false) {
        requestAnimationFrame(next);
      }
    });
  }
}

const ticker = new Ticker();
ticker.tick(update, {target: block});

通用的抽象接口 角度 时间:

function update({target}, {time}) {
  target.style.transform = `rotate(${360 * time / 2000}deg)`;
}

class Ticker {
  tick(update, context) {
    let count = 0;
    let startTime = Date.now();
    requestAnimationFrame(function next() {
      count++;
      const time = Date.now() - startTime;
      if(update(context, {count, time}) !== false) {
        requestAnimationFrame(next);
      }
    });
  }
}

const ticker = new Ticker();
ticker.tick(update, {target: block})

通用的接口 canvas:

function update({context}, {time}) {
  context.clearRect(0, 0, 512, 512);
  context.save();
  context.translate(100, 100);
  context.rotate(time * 0.005);
  context.fillStyle = '#00f';
  context.fillRect(-50, -50, 100, 100);
  context.restore();
}

class Ticker {
  tick(update, context) {
    let count = 0;
    let startTime = Date.now();
    requestAnimationFrame(function next() {
      count++;
      const time = Date.now() - startTime;
      if(update(context, {count, time}) !== false) {
        requestAnimationFrame(next);
      }
    });
  }
}

Timing 的实现:

class Timing {
  constructor({duration, easing} = {}) {
    this.startTime = Date.now();
    this.duration = duration;
    this.easing = easing || function(p){return p};
  }
  get time() {
    return Date.now() - this.startTime;
  }
  get p() {
    return this.easing(Math.min(this.time / this.duration, 1.0));
  }
}

class Ticker {
  tick(update, context, timing) {
    let count = 0;
    timing = new Timing(timing);
    requestAnimationFrame(function next() {
      count++;
      if(update(context, {count, timing}) !== false) {
        requestAnimationFrame(next);
      }
    });
  }
}

后面的具体例子就是数学公式结合前面的通用接口,找几个例子来记一下

贝塞尔轨迹:

前端星2020_4_11课程笔记_第1张图片

function bezierPath(x1, y1, x2, y2, p) {
  const x = 3 * x1 * p * (1 - p) ** 2 + 3 * x2 * p ** 2 * (1 - p) + p ** 3;
  const y = 3 * y1 * p * (1 - p) ** 2 + 3 * y2 * p ** 2 * (1 - p) + p ** 3;
  return [x, y];
} //轨迹的数学公式

function update({target}, {timing}) {
  const [px, py] = bezierPath(0.2, 0.6, 0.8, 0.2, timing.p);
  target.style.transform = `translate(${100 * px}px, ${100 * py}px)`;
}

const ticker = new Ticker();
ticker.tick(update, {target: block}, {
  duration: 2000,
  easing: p => p * (2 - p),
});

周期运动:实际上周期运动的timing发生了变化

class Timing {
  constructor({duration, easing, iterations = 1} = {}) {
    this.startTime = Date.now();
    this.duration = duration;
    this.easing = easing || function(p){return p};
    this.iterations = iterations;
  }
  get time() {
    return Date.now() - this.startTime;
  }
  get finished() {
    return this.time / this.duration >= 1.0 * this.iterations;
  }
  get op() {
    let op = Math.min(this.time / this.duration, 1.0 * this.iterations);
    if(op < 1.0) return op;
    op -= Math.floor(op);
    return op > 0 ? op : 1.0;
  }
  get p() {
    return this.easing(this.op);
  }
}

用promise来写连续运动Ticker 其实目标就是使用promise做流程控制

class Ticker {
  tick(update, context, timing) {
    let count = 0;
    timing = new Timing(timing);
    return new Promise((resolve) => {
      requestAnimationFrame(function next() {
        count++;
        if(update(context, {count, timing}) !== false && !timing.finished) {
          requestAnimationFrame(next);
        } else {
          resolve(timing);
        }
      });      
    });
  }
}

下面就是上面promise trick的应用 小球弹跳

const down = lerp(setValue, {top: 100}, {top: 300});
const up = lerp(setValue, {top: 300}, {top: 100});

(async function() {
  const ticker = new Ticker();

  // noprotect
  while(1) {
    await ticker.tick(down, {target: block},
      {duration: 2000, easing: p => p * p});
    await ticker.tick(up, {target: block},
      {duration: 2000, easing: p => p * (2 - p)});
  }
})();

前端性能优化

1. 性能评估方法

RAIL模型
关键指标:

  • 100ms内响应用户输入 Response
  • 10ms 动画一帧 Animation
  • 主线程空闲时间最大化 Idle
  • 1000ms交互内容展现 Load
    chrome DevTools

2. 实际例子

针对浏览器渲染流程:页面是怎么样展示出来的?

JS->Style(这一步的输出是渲染树)->Layout(计算 产出盒模型)->paint(栅格化)->Composite(渲染层合并)

Layout 和 paint 是可以不出现的 所以会有各种场景

  • 火焰图的使用
  • 加载优化

    • 资源效率优化
    • 图片优化
    • 字体优化
    • 关键渲染路径优化
  • 渲染优化

    • JS执行优化
    • 避免大型复杂布局
    • 渲染层合并

你可能感兴趣的:(chrome,javascript,前端)