css module

困扰问题

CSS全局作用域问题

CSS的规则都是全局的,任何一个组件的样式规则,都对整个页面有效。相信写css的人都会遇到样式冲突(污染)的问题。

  • class命名写长一点吧,降低冲突的几率
  • 加个父元素的选择器,限制范围
  • 重新命名个class吧,比较保险

规范化

BEM,OOCSS,SMACSS

BEM:block-element-modify, 解决css命名重复
OOCSS: 类, 解决css 重用

但存在以下问题:

  • JS CSS之间依然没有打通变量,css没有局部作用域
  • 复杂的命名

CSS in JS

  • 样式代码也会出现大量重复。
  • 不能利用成熟的 CSS 预处理器(或后处理器)

使用JS 来管理样式模块
使用JS编译原生的CSS文件,使其具备模块化的能力

CSS Modules 能最大化地结合现有 CSS 生态(预处理器/后处理器等)和 JS 模块化能力

1
// webpack.config.js
css?modules&localIdentName=[name]__[local]-[hash:base64:5]

/* components/Button.css */
.normal { /* normal 相关的所有样式 */ }

// components/Button.js
import styles from './Button.css';
buttonElem.outerHTML = `<button class=${styles.normal}>Submit</button>`
 
<button class="button--normal-abc53">Submit</button>

CSS Modules 实现了以下几点:

  • 所有样式都是局部作用域 的,解决了全局污染问题
  • class 名生成规则配置灵活,可以此来压缩 class 名
  • 更好的压缩
  • 只需引用组件的 JS 就能搞定组件所有的 JS 和 CSS

存在问题:

  • 无法使用伪类,媒体查询等

prefetch


相对subresource 优先级最底


优先级最高 预先请求资源, 但不解析


预先请求资源, 并且解析, 但不改变dom,
不是所有资源都会下载,下载类型的,音频视频,ajax(post, put, deleted),https,弹窗


预先解析dns


预先下载js

axios

axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,它本身具有以下特征:

从浏览器中创建 XMLHttpRequest
从 node.js 发出 http 请求
支持 Promise API
拦截请求和响应
转换请求和响应数据
取消请求
自动转换JSON数据
客户端支持防止 CSRF/XSRF
浏览器兼容性

bind实现

1
Function.prototype.bind = function (context) {
    if (typeof this !== "function") {
      throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
    }

    var self = this;
    var args = Array.prototype.slice.call(arguments, 1);
    var fNOP = function () {};

    var fbound = function () {
        self.apply(this instanceof self ? this : context, args.concat(Array.prototype.slice.call(arguments)));
    }

    fNOP.prototype = this.prototype;
    fbound.prototype = new fNOP();

    return fbound;
}

防抖

1
function debounce(func, wait = 300, immediate) {

    var timeout, result;

    var debounced = function () {
        var context = this;
        var args = arguments;

        if (timeout) clearTimeout(timeout);
        if (immediate) {
            // 如果已经执行过,不再执行
            var callNow = !timeout;
            timeout = setTimeout(function(){
                timeout = null;
            }, wait)
            if (callNow) result = func.apply(context, args)
        }
        else {
            timeout = setTimeout(function(){
                result = func.apply(context, args)
            }, wait);
        }
        return result;
    };

    debounced.cancel = function() {
        clearTimeout(timeout);
        timeout = null;
    };

    return debounced;
}

前端路由实现

前端路由原理

先按一定的规则, 实现hash表, key是路径, value是处理页面渲染的回调。
然后通过监听事件,来循环hash表,执行相应的回调函数。

location.hash + hashchange事件

通过location.hash, location.assign(), location.replace()来改变hash
然后通过监听hashchange来做相应的处理

浏览器兼容好

history.pushState() + popState事件

通过pushState() 来想history state 栈中添加新的url
然后history.go(), history.back(),来触发页面跳转
然后通过popstate监听url的改变

浏览器兼容相对差点

new原理

用new Object() 的方式新建了一个对象 obj
获取出去第一个参数
将 obj 的原型指向构造函数,这样 obj 就可以访问到构造函数原型中的属性
使用 apply,改变构造函数 this 的指向到新建的对象,这样 obj 就可以访问到构造函数中的属性
返回 obj

1
function objectFactory() {
    var obj = new Object(),
    Constructor = [].slice.call(arguments);
    obj.__proto__ = Constructor.prototype;
    var ret = Constructor.apply(obj, arguments);
    return typeof ret === 'object' ? ret : obj;
}

节流

每隔一段时间,只执行一次事件。

有两种主流的实现方式,一种是使用时间戳,一种是设置定时器。

使用时间戳
当触发事件的时候,我们取出当前的时间戳,然后减去之前的时间戳(最一开始值设为 0 ),如果大于设置的时间周期,就执行函数,然后更新时间戳为当前的时间戳,如果小于,就不执行。

1
function throttle(func, wait) {
    var context, args;
    var previous = 0;

    return function() {
        var now = +new Date();
        context = this;
        args = arguments;
        if (now - previous > wait) {
            func.apply(context, args);
            previous = now;
        }
    }
}

使用定时器。
设置一个定时器,再触发事件的时候,如果定时器存在,就不执行,直到定时器执行,然后执行函数,清空定时器,这样就可以设置下个定时器。

1
function throttle(func, wait) {
    var timeout;
    return function() {
        context = this;
        args = arguments;
        if (!timeout) {
            timeout = setTimeout(function(){
                timeout = null;
                func.apply(context, args)
            }, wait)
        }

    }
}

css js兼容性

!important (功能有限)随着IE7对!important的支持, !important 方法现在只针对IE6的兼容.
例如:

1
#example {
	width: 100px !important; /* IE7+FF */
	width: 103px; /* IE6 */
}

移动开发知识

app应用前端开发要注重meta标签
webkit内核中有一些私有的meta标签,这些meta标签在开发webapp时起到非常重要的作用 。

//去除Android平台中对邮箱地址的识别怎么做

//作用是让普通移动网页被添加到主屏幕后

舍弃CSS float属性
在项目开发过程中可以会遇到内容排列显示的布局,假如你遇见这样的视觉稿,建议你放弃float,可以直接使用display:inline-block。

利用CSS3边框背景属性
在app的前端开发中,这个按钮有圆角效果,有内发光效果还有高光效果,这样的按钮使用CSS3写是无法写出来的,当然圆角可以使用CSS3来写,但高光和内发光却无法使用CSS3编写, 这个时候你不妨使用-webkit-border-image来定义这个按钮的样式。

使用webkit-box
webkit为display属性提供了一个webkit-box的值,做到盒子模型灵活控制。

很多属性极限突破可以使用缩放,倾斜这种手段来hack,比如最小字体,比如各种自己画的伪类图标。
能css画的不要用图。
能flex布局的不要用浮动,不要用绝对定位(不利于页面布局的扩展)