0%

window.requestAnimationFrame() 方法会告诉浏览器你想运行一个动画,并要求浏览器在下次重绘(repaint)之前调用一个函数来更新动画。

你应该在准备更新屏幕上的动画时调用这个方法。它将使你的动画函数在下次重绘之前调用。回调执行的频率通常为每秒60次,但一般会与屏幕的刷新率相匹配。当在后台的 tab 或者隐藏的 iframe 中运行时,回调执行的频率会降低以提高性能与电池寿命。

window.requestAnimationFrame(callback);

window.requestAnimationFrame()

判断浏览器是否支持 webp 格式的图片

var isWebpSupport = false;

function detectWebpSupport() {
  if (isWebpSupport) return;

  try {
    isWebpSupport = window.localStorage && window.localStorage.getItem('isWebpSupport');
  } catch (e) {}

  if (isWebpSupport) return;

  var img = new Image();
  img.src = 'data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
  img.onload = function() {
    if (img.height === 2) {
      isWebpSupport = true;
      try {
        window.localStorage && window.localStorage.setItem('isWebpSupport', true);
      } catch (e) {}
    }
  };
}

detectWebpSupport();    // 检查是否支持 webp

根据 webp 的支持情况替换图片的 url

$http.get('/api/list').then(res => res.data).then(data => {
    let items = data.items;
    if (isWebpSupport) {
      items = items.map(item => {
        item.img = item.img.replace(/\-thumb$/, '-thumbwebp');    // 使用七牛云服务处理图片 http://developer.qiniu.com/code/v6/api/kodo-api/image/imageview2.html
        return item;
      });
    }
    return items;
  }
}).catch(err => {
  console.error(err);
});

附:localStorage.getItemimg.onload 性能比较

function test1() {
  var start = window.performance.now();
  var img = new Image();
  img.src = 'data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
  img.onload = function() { console.log(window.performance.now() - start); }
}

function test2() {
  var start = window.performance.now();
  window.localStorage.getItem('isWebpSupport');
  console.log(window.performance.now() - start);
}
// localStorage 为同步调用

相差一个数量级

onload vs localStorage

StyleSheet.create 方法进行修改

/* from js/common/F8StyleSheet.js */

import {StyleSheet, Platform} from 'react-native';

export function create(styles) {
  const platformStyles = {};
  Object.keys(styles).forEach((name) => {
    let {ios, android, ...style} = {...styles[name]};
    if (ios && Platform.OS === 'ios') {
      style = {...style, ...ios};
    }
    if (android && Platform.OS === 'android') {
      style = {...style, ...android};
    }
    platformStyles[name] = style;
  });
  return StyleSheet.create(platformStyles);
}

使用示例:

/* from js/common/F8SegmentedControl.js */
var styles = F8StyleSheet.create({
  container: {
    flexDirection: 'row',
    backgroundColor: 'transparent',
    ios: {
      paddingBottom: 6,
      justifyContent: 'center',
      alignItems: 'center',
    },
    android: {
      paddingLeft: 60,
    },
  },
  button: {
    borderColor: 'transparent',
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: 'transparent',
    ios: {
      height: HEIGHT,
      paddingHorizontal: 20,
      borderRadius: HEIGHT / 2,
      borderWidth: 1,
    },
    android: {
      paddingBottom: 6,
      paddingHorizontal: 10,
      borderBottomWidth: 3,
      marginRight: 10,
    },
  },
  label: {
    letterSpacing: 1,
    fontSize: 12,
    color: 'white',
  },
  deselectedLabel: {
    color: 'rgba(255, 255, 255, 0.7)',
  },
});

参考

@mixin retina {
  @media
    only screen and (-webkit-min-device-pixel-ratio: 2),
    only screen and (min--moz-device-pixel-ratio: 2),
    only screen and (-o-min-device-pixel-ratio: 2/1),
    only screen and (min-device-pixel-ratio: 2),
    only screen and (min-resolution: 192dpi),
    only screen and (min-resolution: 2dppx) {
    @content;
  }
}

@mixin print {
  @media print {
    @content;
  }
}