BccSafe's Blog Fight for a future

React移动端搭脚手架日记

来了个新项目,移动端的WebApp,自己尝试着搭建了一个脚手架出来 (因为项目催得紧,一直没有时间写,拖到现在)

  1. TypeScript 2 + Webpack + React

    在hot reload上用了React-Hot-Loader3,目前还没出正式版,参考了https://github.com/tomduncalf/typescript-react-template,其他和之前用es6没有太大差别,开发时因为需要HRM,TypeScript转换成es6,再由babel转换成es5,部署时TypeScript就直接转换成es5

  2. webpack DLLPlugin

    项目中将使用react全家桶,意味着将引入大量的包,DLLPlugin能够前置这些依赖包的构建,来提高build和rebuild的构建效率。

  3. 各种Loaders

    主要是css,sass-loader + postcss-loader,配合Autoprefixer为CSS添加浏览器特定的前缀

  4. 用typescript来写redux

    参考了http://jaysoo.ca/2015/09/26/typed-react-and-redux/

大致就是这样,有些细节和待优化的点后续补上

github地址:https://github.com/bccsafe/React-WebApp-Boilerplate

ios10,Android6下pushState导致的微信分享签名失败问题

react写的webapp,在微信里用js sdk发现在ios 10,Android6 下签名挂了,一直提示invalid signature,但是低版本的android就可以

研究了下发现是pushState导致的,签名时我们生成签名时用的url和微信取出来的url不一致导致的,比如进页面是home页,然后进了一个详情页,此时我们需要调用分享接口,这个时候我们认为url是详情页的url,但微信认为是home页的url,这就导致了问题

解决办法就是进入页面的时候将url保存起来,分享的时候用

保存进入页面最初的URL,假设为INIT_URL

根据客户端的不同:

安卓:在准备分享前(或发生URL跳转后)使用当前URL进行wx.config, 如果失败,则尝试使用INIT_URL注册

iOS:在准备分享前(或发生URL跳转后)使用INIT_URL进行wx.config, 如果失败,则尝试使用当前URL注册

参考:https://segmentfault.com/q/1010000002520634

react+redux+es6上线问题小记

最近在折腾react全家桶,项目用react+redux+es6开发,写了几个页面后准备上线,发现在chrome和iphone6上工作正常,但是到了安卓机上只给一个白屏,网页的标题倒是出来了

一度崩溃后开始找工具调试,用DebugGap发现并没有报错,页面上只有一个给react插入的DOM节点,显然ReactDOM.render这个方法没有生效

google…

发现是babel只是将es6转换成es5,而部分安卓上浏览器对es5的支持还不够,比如promise

解决办法:import 'babel-polyfill'

Babel includes a polyfill that includes a custom regenerator runtime and core.js.

This will emulate a full ES6 environment. This polyfill is automatically loaded when using babel-node and babel/register.

BccBrowser V3.0

DcefBrowser的CEF3版本近期更新到了3.2623.1401,算是个比较大的更新,顺手把BccBrowser也更新了

这个版本解决了多个之前的遗留问题,比如输入法框显示不正确,滚轮速度太快

以后DcefBrowser的内核可能不会再更新了,因为2623将是最后一个支持xp的版本,在中国这个问题可能短时间内还解决不了

下载地址: https://pan.baidu.com/s/1pLTdegN

Download URL: https://www.dropbox.com/s/3obznlfsbbvtoir/BccBrowser%20V3.0%202016-08-21.zip?dl=0

AngularJs1-ES6-Webpack 项目搭建

这份代码存在多个问题,Angular 1.x和webpack结合存在很多问题,暂时放弃...

关键字:AngularJs1, ES6, SASS, gulp, Webpack, livereload

一. 项目目录

├── gulpfile.js 存放gulp相关的配置

├── index.html 入口html

├── package.son 存放npm相关的配置

├── webpack.config.js 存放webpack相关的配置

├── css 存放scss代码

├── dist 存放打包了的js,css文件

├── js 存放es6代码

│   ├── index.js 入口文件

│   ├── compontent 组件

│       ├── module 模块组件

│       ├── CommonDirective.js 通用组件

│       └── index.js 入口文件

│   ├── config app配置

│       └── routing.js 路由

│   ├── module 模块

│       ├── test 测试模块

│       	├── index.js 入口文件

│       	├── routing.js 路由

│       	└── TestController.js 控制器

│   └── index.js 入口文件

├── view 存放html代码

│   ├── module 模块

│       ├── test 测试模块

│       	└── test.html 模版

└────

二. package.json

{
  "name": "AngularJs1-ES6-Webpack",
  "version": "0.0.1",
  "description": "A simple Demo using ES6, AngularJs1 and webpack",
  "devDependencies": {
    "angular": "~1.3.0",
    "angular-ui-router": "^0.2.14",
    "babel-core": "^6.10.4",
    "babel-loader": "^6.2.4",
    "babel-preset-es2015": "^6.9.0",
    "css-loader": "^0.23.1",
    "extract-text-webpack-plugin": "^1.0.1",
    "gulp": "^3.9.0",
    "gulp-util": "^3.0.7",
    "ng-annotate-loader": "~0.0.4",
    "node-sass": "^3.8.0",
    "raw-loader": "^0.5.1",
    "sass-loader": "^4.0.0",
    "style-loader": "^0.13.1",
    "webpack": "^1.13.1",
    "webpack-dev-server": "^1.12.1"
  },
  "author": "BccSafe",
  "license": "MIT"
}

三. AngularJs ES6写法

1) 路由

//routing.js
import TestController from './TestController.js';

export default function routing($stateProvider) {
	'ngInject';
	
    $stateProvider.state('test', {
        url: '/test',
        templateUrl: "view/module/test/test.html",
        controller: TestController
    });
}

//index.js
import 'angular';
import angularUIRouter from 'angular-ui-router';
import routing from './config/routing.js';

let myApp = angular.module("myApp", [angularUIRouter]);

myApp.config(routing);

2) Controller(Service, Factory同理)

//TestController.js
class TestController {

    constructor($rootScope, $scope, $stateParams){
        'ngInject';

        $scope.testValue = "this value from the Class TestController"; 
    }

}

export default TestController;

//index.js
import 'angular';
import angularUIRouter from 'angular-ui-router';
let testModule = angular.module('testModule', [angularUIRouter]);

export default testModule = testModule.name;

3) Directive

//CommonDirective
class CommonDirective {

    constructor(){
        'ngInject';

        this.template = '<div>I\'m a directive!</div>';
        this.restrict = "E";
    }

}

export default CommonDirective;

//index.js
import 'angular';
import CommonDirective from './CommonDirective.js';

let CommonCptModule = angular.module('CommonCptModule', []);

CommonCptModule.directive('commonDirective', () => new CommonDirective);

export default CommonCptModule = CommonCptModule.name;

四. gulp+webpack 实现打包调试

1) 判断process.env.NODE_ENV的值来区分是开发还是发布

gulp.task('set-dev-node-env', () => {
	return process.env.NODE_ENV = 'development';
});

gulp.task('set-prod-node-env', () => {
    return process.env.NODE_ENV = 'production';
});

if (process.env.NODE_ENV === 'production') {
		myConfig.plugins.push(new ExtractTextPlugin("style.css", {allChunks: true}));
}

2) Webpack模块加载器(Loaders)

loaders 用于转换应用程序的资源文件,他们是运行在nodejs下的函数 使用参数来获取一个资源的来源并且返回一个新的来源(资源的位置),例如:你可以使用loader来告诉webpack去加载一个coffeescript或者jsx

用到了babel-loader, css-loader, style-loader, sass-loader, raw-loader来完成html, es6, sass的加载, ng-annotate-loader用于添加 AngularJS依赖注入

3) Webpack开发服务器 webpack-dev-server

Webpack提供了一个基于Node.js Express框架的开发服务器,它是一个静态资源Web服务器,对于简单静态页面或者仅依赖于独立服务的前端页面,都可以直接使用这个开发服务器进行开发。在开发过程中,开发服务器会监听每一个文件的变化,进行实时打包,并且可以推送通知前端页面代码发生了变化,从而可以实现页面的自动刷新。

对HTML, Es6, SCSS文件的更改将可以不需要刷新自动更新,这点很爽

gulp.task('server', ['set-dev-node-env', 'webpack', 'myWatch'], (callback) => {
	var myConfig = Object.create(webpackConfig);
	myConfig.devtool = 'eval';
	myConfig.debug = true;
	myConfig.entry.unshift("webpack-dev-server/client?http://localhost:8080/", "webpack/hot/dev-server");

	new WebpackDevServer(webpack(myConfig), {
		publicPath: '/',
		stats: {
			colors: true
		},
		hot: true
	}).listen(8080, 'localhost', (err) => {
		if(err) throw new gutil.PluginError('webpack-dev-server', err);
		gutil.log('[webpack-dev-server]', 'http://localhost:8080/webpack-dev-server/index.html');
	});
});

查看完整代码

React Native IOS开发试水

忙了一段时间,没更新Blog,上来分享个React Native开发的天气APP,是我这学期IOS课的期末作业,没用OC的原因是想尝试下RN,之前接触的太少

上图,分别是主界面,城市列表,搜索界面,仿了苹果自带的天气APP

weatherMainView


weatherCityList


weatherSearch

初次上手RN,界面布局用了FlexBox,js方面用了最新的ES6,RN支持最新的写法,import/export处理各模块的依赖关系很爽,html则是JSX,第一次使不太习惯吧。

大概花了三天时间,整个过程还是比较有趣的,js开发原生IOS应用很棒!

AngularJS控制器继承自另一控制器

AngularJS里控制器继承,常用的就是作用域嵌套作用域。默认情况下,当前作用域中无法找到某个属性时,就会在父级作用域中进行查找,若找不到直至查找到$rootScope。

但有些情况下,rootScope下就是我们的controller,不可能将大量的公用属性方法写到rootScope里去。

比如说有多个类似的页面,都有面包屑,搜索栏,工具栏,表格等元素,面包屑表格这种元素考虑做成directive,那么必然会有许多类似的配置需要从controller传到组件里去,也会产生很多工具类方法用于处理数据等,这时候在每个页面的controller里重复写相同的代码显然很难看,就需要用到继承。

在StackOverflow上找到了解决方案,原来AngularJS已经考虑到这种情况了,提供了$controller

var app = angular.module('angularjs-starter', []); 
app.controller('ParentCtrl ', function($scope) {
  // I'm the sibling, but want to act as parent
});
app.controller('ChildCtrl', function($scope, $controller) {
  $controller('ParentCtrl', {$scope: $scope}); //This works
});

StackOverflow链接

ECMAScript继承对象的若干方法

以下内容均整理自《JavaScript高级程序设计》第六章 面向对象的程序设计

  • 原型链
function SuperType(){
    this.property = true;
}
SuperType.prototype.getSuperValue = function(){
    return this.property;
};
function SubType(){
    this.subproperty = false;
}
//继承了 SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function (){
    return this.subproperty;
};
var instance = new SubType();
alert(instance.getSuperValue());//true
function SuperType(){
    this.colors = ["red", "blue", "green"];
}
function SubType(){
//继承了 SuperType
    SuperType.call(this);
}
var instance1 = new SubType();
instance1.colors.push("black");
alert(instance1.colors);    //"red,blue,green,black"
var instance2 = new SubType();
alert(instance2.colors);    //"red,blue,green"
  • 借用构造函数
function SuperType(){
    this.colors = ["red", "blue", "green"];
}
function SubType(){
//继承了 SuperType
    SuperType.call(this);
}
var instance1 = new SubType();
instance1.colors.push("black");
alert(instance1.colors);    //"red,blue,green,black"
var instance2 = new SubType();
alert(instance2.colors);    //"red,blue,green"
function SuperType(name){
    this.name = name;
}
function SubType(){
//继承了 SuperType,同时还传递了参数 SuperType.call(this, "Nicholas");
//实例属性
    this.age = 29;
}
var instance = new SubType();
alert(instance.name);    //"Nicholas";
alert(instance.age);     //29
  • 组合继承
function SuperType(name){
	this.name = name;
	this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
    alert(this.name);
};
function SubType(name, age){
//继承属性 SuperType.call(this, name);
    this.age = age;
}
//继承方法
SubType.prototype = new SuperType(); 
SubType.prototype.constructor = SubType; 
SubType.prototype.sayAge = function(){
    alert(this.age);
};
var instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
alert(instance1.colors);//"red,blue,green,black"
instance1.sayName();//"Nicholas";
instance1.sayAge();//29
var instance2 = new SubType("Greg", 27);
alert(instance2.colors);//"red,blue,green"
instance2.sayName();//"Greg";
instance2.sayAge();//27
  • 原型式继承
function object(o){
	function F(){} 
	F.prototype = o;
	return new F();
}
var person = {
    name: "Nicholas",
    friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = object(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");
var yetAnotherPerson = object(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
alert(person.friends);   //"Shelby,Court,Van,Rob,Barbie"
var person = {
    name: "Nicholas",
    friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = Object.create(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");
var yetAnotherPerson = Object.create(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
alert(person.friends); //"Shelby,Court,Van,Rob,Barbie"
  • 寄生式继承
function createAnother(original){ 
	var clone = object(original); //通过调用函数创建一个新对象
	clone.sayHi = function(){ //以某种方式来增强这个对象
		alert("hi");
	};
	return clone; //返回这个对象
}
var person = {
    name: "Nicholas",
    friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = createAnother(person);
anotherPerson.sayHi(); //"hi"
  • 寄生组合式继承
function SuperType(name){
    this.name = name;
    this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
    alert(this.name);
};
function SubType(name, age){
    SuperType.call(this, name);
    this.age = age;
}
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
    alert(this.age);
};
function inheritPrototype(subType, superType){
    var prototype = object(superType.prototype);
    prototype.constructor = subType;
    subType.prototype = prototype;
}
function SuperType(name){
    this.name = name;
    this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
    alert(this.name);
};
function SubType(name, age){
    SuperType.call(this, name);
    this.age = age;
}
inheritPrototype(SubType, SuperType);
SubType.prototype.sayAge = function(){
    alert(this.age);
}

总结

原型式继承可以在不必预先定义构造函数的情况下实现继承,其本质是执行对给定对象的浅复制。而复制得到的副本还可以得到进一步改造。

组合继承是JavaScript中最常用的继承模式,instanceof 和 isPrototypeOf()都能够用于识别基于组合继承创建的对象。

寄生式继承与原型式继承非常相似,也是基于某个对象或某些信息创建一个对象,然后增强对象,最后返回对象。为了解决组合继承模式由于多次调用超类型构造函数而导致的低效率问题,可以将这个模式与组合继承一起使用。

寄生组合式继承集寄生式继承和组合继承的优点与一身,是实现基于类型继承的最有效方式。