H5开发,一般是指移动端的页面开发。移动端可分为app和普通浏览页面。从嵌入的环境来归类:可以分为app、微信H5及手机浏览器里面打开的页面。
以前粗略的涉略过h5开发的一些知识,感觉H5并不是很难。在这半年内,接手并完成了两个微信H5项目(一期)的过程中,发觉h5开发过程中需要注意的细节有很多,碰到的兼容问题也有一些。在这里我先总结下,H5项目的一些思路及碰到的难点和解决方法。
在刚接到H5项目时,因为前端有很多框架,所有需要先确定使用什么技术。对于用vue和还是react,考虑到项目的规划时间和对框架的熟练度。这两个H5的项目我都用react来完成。
webpack+react+react-dom+react-route+redux+axios +Java+mysql ,一个完整的技术栈。
比较基础的前端开发环境搭建(webpack+react…),各位可以参考我前面写的文章。由于webpack的技术更新及部分代码优化,基础配置里面有些东西需要稍微调整下。
比如:
1. nodeJs 的指令更改
以前安装一个模块的指令:

npm install url-loader file-loader --save-dev

现在更改为:

npm install url-loader file-loader -S -D
  1. Happypack 插件将不再支持cache
new Happypack({
    id:"happybabel",
    loaders:['babel-loader'],
    threadPool:happypackThreadPool,
    cache:true,   **//需要删除这句cache的配置**
    verbose:true
})
  1. 在webpack plugins 里面添加配置使用(生产)环境的插件
new webpack.DefinePlugin({
  "process.env": { 
     NODE_ENV: JSON.stringify("production") 
   }
})

4.为了降低最后打包的压缩体积,把devtool:’eval-soure-map’ 改成 devtool:false。
配置css-loader将css文件进行压缩:

{
    test:/\.css$/,        
    use:ExtractTextPlugin.extract({//使用ExtractTextPlugin 插件
        fallback:"style-loader",//用于开发环境
        use:[{loader:"css-loader",options:{minimize:true}},"postcss-loader"]
    }),

}

5.简化redux 和action的代码
以前旧代码请参考:

redux 以前的代码:
   const reducer = (state = defaultState, action) => {     
    switch (action.type) {//通过action的返回值来选择更新哪个state的状态
        case 'AlterMain':
            return  Object.assign({},state,{ mainText:action.payload});
        case 'AlterTopic':
            return  Object.assign({},state,{ topicText:action.payload});
        default:
            return state;
    }
};
精简为:
const reducer = (state = defaultState, action) => {
    if (action.type.indexOf("@@redux") != -1) {
        return state;
    } else {
        var ob = {};
        ob[action.type] = action.payload;
        return Object.assign({}, state, ob);
    }
};
action 旧代码:
const actions = {
 changeText:function(num){
     console.log("调用actions");
      switch(num){
      case 1:
      return {type:'AlterMain',payload:"mainContainer had been changed"};
      case 2:
       return {type:'AlterTopic',payload:"topicContainer had been changed"};
       default:
       return action;
   }
}
};
export default actions;

优化为:
const actions = {
 changeInfo:(infotype,string)=>{   
    if(infotype == ""){
      return action;
    }else{
      return {type:infotype,payload:string};
    }
},
};
export default actions;

现在转入主要内容。
h5 开发,第一个面临的难题是像素问题,移动端的像素有物理像素及逻辑像素的说法,同一个像素在不同的手机,显示的大小都不一致。而且PC端浏览器的最小像素为1px,但手机端却可以显示出0.5px甚至可能更小。
一、这个像素问题要怎么解决?
h5 里面有个视口(viewport)这个标签。这个视口标签就设定逻辑像素和物理像素的比值。initial-scale=1表示1倍的关系。user-scalabe=no,表示不允许用户更改当前页面的比例。

根据网上推荐的方案,通过 docEl.clientWidth 获取移动端网页的可见区域的宽度,把可见区域分成320小分,然后规定根字体占10(pc端默认字号为10px)小分,单位取px。

(function (doc, win) {
    var docEl = doc.documentElement,
        resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
    recalc = function () {
        var clientWidth = docEl.clientWidth;
        if (!clientWidth) return;
        docEl.style.fontSize = 10 * (clientWidth / 320) + 'px';       
    }; 
    if (!doc.addEventListener) return;
    win.addEventListener(resizeEvt, recalc, false);
    doc.addEventListener('DOMContentLoaded', recalc, false);
})(document, window);

上面这个js,在react的app..js 引入。当代码成功运行,可以看到根字体的大小。

h5微信开发框架 微信h5项目_H5

当根字体确定下来之后,后面所有设计到尺寸的地方都以跟父元素的百分比或者用以根字体的比例关系设定(以rem)。如果用rem做单位,需要所有指定尺寸的地方都需要 用UI图纸标注的尺寸除以根字体大小。如果每次尺寸都用人工转换,这个将会是个很浪费时间一件事。为了解决这个费力不讨好的问题,我启用了less。less只需要在整个文档前面设定一个根字体大小的变量(比如:@rootFontSize:23.4375),后面所有涉及到尺寸的地方直接除以这个变量就好。例子:设置div 的高度 height:44rem/@rootFontSize。 这样div设定的高度就等同于图纸(设计尺寸比例1:1的关系)上的44px。

二、 Object.assign() 兼容问题
以前碰到一个这样的现象:引入redux成功后,项目在pc端谷歌 浏览器上调试页面可以正常渲染。但如果在安卓模拟机和实体手机的环境下,页面就变成了空白。后来经过排查,发现object.assign 存在移动端兼容性问题。
这个兼容问题怎么解决?
网上有现成的方案:引入polyfill 文件,重新定义object.assign。

if (typeof Object.assign != 'function') {
    // Must be writable: true, enumerable: false, configurable: true
    Object.defineProperty(Object, "assign", {
      value: function assign(target, varArgs) { // .length of function is 2
        'use strict';
        if (target == null) { // TypeError if undefined or null
          throw new TypeError('Cannot convert undefined or null to object');
        }

        var to = Object(target);

        for (var index = 1; index < arguments.length; index++) {
          var nextSource = arguments[index];

          if (nextSource != null) { // Skip over if undefined or null
            for (var nextKey in nextSource) {
              // Avoid bugs when hasOwnProperty is shadowed
              if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
                to[nextKey] = nextSource[nextKey];
              }
            }
          }
        }
        return to;
      },
      writable: true,
      configurable: true
    });
  }

这篇就先到这。解决了移动端刚开始碰到的两个问题,处理好这个两个问题,移动端页面和pc页面开发的区别就不会很大了。
下一篇讲微信相关的知识及使用微信模块碰到的一些棘手的问题。