codingecho / react-native-start Goto Github PK
View Code? Open in Web Editor NEWreact-native start with windows 7 system
react-native start with windows 7 system
不包含IOS、Android原生开发的知识
**定义:**类XML的JavaScript语法扩展
var Avatar = React.createClass({
render: function() {
return (
<div>
<ProfilePic filename={this.props.filename} />
<ProfileLink {...this.props} />
</div>
);
}
});
var ProfilePic = React.createClass({
render: function() {
return (
<img src={'http://s.amazeui.org/media/i/demos/' + this.props.filename} />
);
}
});
var ProfileLink = React.createClass({
render: function() {
return (
<a href={'http://s.amazeui.org/media/i/demos/' + this.props.filename}>
{this.props.filedesc}
</a>
);
}
});
ReactDOM.render(
<Avatar filename="bing-2.jpg" filedesc="晚霞" />,
document.getElementById('demo'));
ReactDOM.render(
<Avatar filename="bing-3.jpg" filedesc="里约内热卢" />,
document.getElementById('demo2'));
这里不列举所有的ES6新特性,只选择常用的进行描述。
let
ES6新增了let
命令,用来声明变量。它的用法类似于var
,但是所声明的变量,只在let
命令所在的代码块内有效。
{
let a = 10;
var b = 1;
}
console.log(a); // ReferenceError: a is not defined.
console.log(b); // 1
const
const 声明一个只读的常量。一旦声明,常量的值就不能改变。
'use strict';
const PI = 3.1415;
console.log(PI); // 3.1415
// 尝试赋值
PI = 3; // TypeError: "PI" is read-only
reqire('react-native'); // 老的写法(类似reqire.js)
import ReactNative from 'react-native'; // 作用类似于Java中的import
var {
StyleSheet,
View,
Text,
AppRegistry,
Image,
} = ReactNative;
/* 等价于 */
var StyleSheet = ReactNative.StyleSheet;
var View = ReactNative.View;
var Text = ReactNative.Text;
var AppRegistry = ReactNative.AppRegistry;
var Image = ReactNative.Image;
Promise是异步编程的一种解决方案,是传统的解决方案(回调函数和事件)的替代方案
var Util = {
//post请求
post: function (url, data, callback) {
var fetchOptions = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
};
// fetch 返回一个Promise对象
fetch(url, fetchOptions)
.then((response) => response.text())
.then((responseText) => {
callback(JSON.parse(responseText));
});
}
};
ES5之前
function Point(x,y){
this.x = x;
this.y = y;
}
Point.prototype.toString = function () {
return '(' + this.x + ', ' + this.y + ')';
}
ES6
//定义类
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
// 静态方法,调用方式:Point.classMethod();
static classMethod() {
return 'hello';
}
// 静态属性
static z:0
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}
继承
class ColorPoint extends Point {
constructor(x, y, color) {
super(x, y); // 调用父类的constructor(x, y)
this.color = color;
}
toString() {
return this.color + ' ' + super.toString(); // 调用父类的toString()
}
}
ES6的class只是面向对象编程的语法糖,升级了ES5的构造函数的原型链继承的写法,
并没有解决模块化问题。module功能就是为了解决这个问题而提出的。
// CommonJS模块
let { stat, exists, readFile } = require('fs');
// 等同于
let _fs = require('fs');
let stat = _fs.stat, exists = _fs.exists, readfile = _fs.readfile;
// ES6模块
import { stat, exists, readFile } from 'fs';
导出变量
// 写法一
export var m = 1;
// 写法二
var m = 1;
export {m};
// 写法三
var n = 1;
export {n as m};
导出function和class
// 报错
function f() {}
export f;
// 正确
export function f() {};
// 正确
function f() {}
export {f};
// person.js
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;
export {firstName, lastName, year};
// main.js
import {firstName, lastName, year} from './person'; // 不用加扩展名“.js”
function setName(element) {
element.textContent = firstName + ' ' + lastName;
}
export default命令,为模块指定默认输出。
// export-default.js
export default function () {
console.log('foo');
}
/*
上面代码是一个模块文件export-default.js,它的默认输出是一个函数。
其他模块加载该模块时,import命令可以为该匿名函数指定任意名字。
*/
// import-default.js
import customName from './export-default';
customName(); // 'foo'
...
)和箭头函数(Lambda表达式)扩展运算符可以将一个数组转为用逗号分隔的参数序列。
function add(x, y) {
return x + y;
}
var numbers = [4, 38];
add(...numbers) // 42
JSX 中的延展属性
var props = {};
props.foo = 'x';
props.bar = 'y';
var component = <Component {...props} />;
// 等价于
var component = <Component foo='x' bar='y' />;
ES6允许使用“箭头”(=>)定义函数
var f = () => 5;
// 等同于
var f = function () { return 5 };
var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {
return num1 + num2;
};
npm的全称是Node Package Manager,是一个NodeJS包管理和分发工具。类似的
有cnpm(淘宝的npm),rnpm(React npm),anpm(Atom npm)
npm install express # 本地安装
npm install express -g # 全局安装
npm install express --save # 安装并添加到依赖(package.json)
npm i express # 简写 npm install express
DOM遍历是昂贵的,所以用变量来缓存需要复用的对象。
// bad
if ($('#userName').length) {
var userName = $('#username');
// ...
$('#username').val();
}
// good
var $userName = $('#userName');
if ($userName.length) {
var userName = $userName.val();
// ...
$userName.val(userName);
}
区分普通JavaScript变量和jQuery变量,变量前加美元符$
,如上面示例中的:$userName
!!!更好的做法!!!
并不是所有的元素都有val()
方法,有时候需要text()
方法,所以
HTML这样写:
<input type="text" id="txtUserName" name="userName" />
JavaScript就可以写为:
var $txtUserName = $('txtUserName'),
userName = $txtUserName.val();
// bad
$userName = $('#userName');
if ($userName.length) {
var userName = $userName.val();
// ...
$userName.val(userName);
}
// good
var $userName = $('#userName');
// bad
var first = $('#first');
var second = $('#second');
// better - we use to put $ symbol before jQuery-manipulated objects
var $first = $('#first');
var $second = $('#second');
var value = $first.val();
var $first = $('#first'),
$second = $('#second'),
value = $first.val(),
k = 3,
cookiestring = 'SOMECOOKIESPLEASE',
myArray = {},
i,
j;
// bad
$first.click(function () {
$first.css('border', '1px solid red');
$first.css('color', 'blue');
});
$first.hover(function () {
$first.css('border', '1px solid red');
});
// better(比上面的写法要好点)
$first.on('click', function () {
$first.css('border', '1px solid red');
$first.css('color', 'blue');
});
$first.on('hover', function () {
$first.css('border', '1px solid red');
});
// good
function changeStyle() {
// 这样的写法同样不好
$first.css('border', '1px solid red');
$first.css('color', 'blue');
/*
* // 更好的写法,定义一个CSS样式,比如:.checked
* $first.css('checked');
*/
}
function tiggerHoverStyle() {
$first.css('border', '1px solid red');
}
$first.on('click', changeStyle)
.on('hover', tiggerHoverStyle);
// bad
$second.html(value);
$second.on('click', function () { alert('hello everybody'); });
$second.fadeIn('slow');
$second.animate({ height: '120px' }, 500);
// good
$second.html(value);
$second.on('click', function () {alert('hello everybody');}).fadeIn('slow').animate({ height: '120px' }, 500);
// bad
$second.html(value);
$second.on('click', function () { alert('hello everybody'); }).fadeIn('slow').animate({ height: '120px' }, 500);
// good
$second.html(value);
$second.on('click', function () {
alert('hello everybody'); })
.fadeIn('slow')
.animate({ height: '120px' }, 500);
// bad
function initVar($myVar) {
if (!$myVar) {
$myVar = $('#selector');
}
}
// good
function initVar($myVar) {
$myVar = $myVar || $('#selector');
}
// good
function getValue($myVar) {
var val;
$myVar = $myVar || $('#selector');
val = $myVar && $myVar.val();
}
// bad
if (collection.length > 0) {
//..
}
// better
if (collection.length) {
//..
}
// bad
var $container = $('#container'),
$containerLi = $('#container li'),
$element = null;
$element = $containerLi.first();
// ... a lot of complicated things
// better
var $container = $('#container'),
$containerLi = $container.find('li'),
$element = null;
$element = $containerLi.first().detach();
// ...a lot of complicated things
$container.append($element);
// bad
$('#id').data(key, value);
// better (faster)
$.data('#id', key, value);
// bad
var $container = $('#container'),
$containerLi = $('#container li'),
$containerLiSpan = $('#container li span');
// better (faster)
var $container = $('#container'),
$containerLi = $container.find('li'),
$containerLiSpan = $containerLi.find('span');
// bad
$('.container > *');
// better
$('.container').children();
When you leave off the selector, the universal selector (*) is still implied.
// bad
$('.someclass :radio');
// better
$('.someclass input:radio');
别画蛇添足,耗时且代码不美观。
// bad
$('div#myid');
$('div#footer a.myLink');
// better
$('#myid');
$('#footer .myLink');
// bad
$('#outer #inner');
// better
$('#inner');
(不要使用已经过时的方法)
// bad - live is deprecated
$('#stuff').live('click', function () {
console.log('hooray');
});
// better
$('#stuff').on('click', function () {
console.log('hooray');
});
(1)坚持使用CDN来加载jQuery,这种别人服务器免费帮你托管文件的便宜干嘛不占呢
<script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/jquery-2.1.4.min.js" type="text/javascript"><\/script>')</script>
(2)安全起见,最好还是提供一个本地备份以便在无法从远程CDN服务器获取jQuery时网站也能工作,如上面代码所示。详情见此。
(3)使用裸协议的URL(也就是说去掉http:
或者https:
),如上面代码展示的那样。
(4)如果可能,尽量将你的JavaScript
和jQuery
代码放到页面底部。详情移步这里。
(5)该使用哪个版本?
如果你想兼容IE678请不要用2.x
的版本针对极少数不用考虑兼容性的幸运儿,极力推荐使用最新版本的jQuery
当从CDN服务器加载jQuery时,最好把版本写全(比如1.11.0而不是1.11或者直接写个1)千万莫重复加载
(6)如果你同时还使用了其他JS框架诸如Prototype
, MooTools
, Zepto
云云,因为他们也使用了$
符号,所以你就不要再用美刀符号来进行jQuery 编码了,而请用'jQuery'代替。并且调用$.noConflict()保证不会有冲突出现。
(7)要检测浏览器对一些新特性是否支持,请用Modernizr
。
(1)jQuery
类型的变量最好加个$
前缀。
(2)时常将jQuery选择器返回的内容存进变量以便重用
var $products = $('div.products'); // 慢
var $products = $('.products'); // 快
(3)使用驼峰命名
var orderList;
(1)尽量ID选择器。其背后机理其实是调用原生的document.getElementById()
,所以速度较其他选择器快。
(2)使用类选择器时不要指定元素的类型。
var $products = $('div.products'); // 慢
var $products = $('.products'); // 快
(3)ID父亲容器下面再查找子元素请用.find()方法。这样做快的原因是通过id选择元素不会使用Sizzle引擎。详情看这里
(4)多级查找中,右边尽量指定得详细点而左边则尽量简单点。
// 丑陋
$('div.data .gonzalez');
// 优化后
$('.data td.gonzalez');
(5)避免冗余。详情或者查看性能比较
$('.data table.attendees td.gonzalez');
// 好的方式:去掉了中间的冗余
$('.data td.gonzalez');
(6)指定选择的上下文。
// 劣质的代码:因为需要遍历整个DOM来找到.class
$('.class');
// 高品代码:因为只需在指定容器范围内进行查找
$('.class', '#class-container');
(7)不要使用万能选择器。查看具体阐释
$('div.container > *'); // 差
$('div.container').children(); // 棒
8.警惕隐式的万能选择器。省略的情况下其实使用的就是*
号通配符。
$('div.someclass :radio'); // 差
$('div.someclass input:radio'); // 棒
9.ID已经表示唯一了,背后使用的是document.getElementById()
,所以不要跟其他选择器混搭了。
$('#outer #inner'); // 脏
$('div#inner'); // 乱
$('.outer-container #inner'); // 差
$('#inner'); // 干净利落,后台只需调用document.getElementById()
(1)操作任何元素前先将其从文档卸载,完了再贴回去。
var $myList = $("#list-container > ul").detach();
//...一大堆对$myList的处理
$myList.appendTo("#list-container");
(2)代码里将HTML组织好后再一次性贴到DOM中去。具体来说,性能比较
// 这样不好
var $myList = $("#list");
for (var i = 0; i < 10000; i++) {
$myList.append("<li>" + i + "</li>");
}
// 这样好
var $myList = $("#list");
var list = "";
for (var i = 0; i < 10000; i++) {
list += "<li>" + i + "</li>";
}
$myList.html(list);
// 但这样更好var array = [];
for (var i = 0; i < 10000; i++) {
array[i] = "<li>" + i + "</li>";
}
$myList.html(array.join(''));
(3)不要处理不存在的元素。
// 无良的做法:jQuery后台要跑完三个函数后才会知道这个元素其实根本不存在
$("#nosuchthing").slideUp();
// 应该这样
var $mySelection = $("#nosuchthing");
if ($mySelection.length) {
$mySelection.slideUp();
}
(1)一个页面只写一个文档ready事件的处理程序。这样代码既清晰好调试,又容易跟踪代码的进程。
(2)不要用匿名函数来做事件的回调。匿名函数不易调试维护测试和复用。或许你想较真,看看这里吧
// 不要这样
$("#myLink").on("click", function(){
//...
});
// 这样
function myLinkClickHandler() {
//...
}
$("#myLink").on("click", myLinkClickHandler);
3.处理文档ready事件的回调也不要用匿名函数,匿名函数不易调试维护测试和复用
$(function () {
// ...
}); // 糟糕的做法:无法利用此函数也无法为其写测试用例
// 好的做法
$(initPage);
// 或 $(document).ready(initPage);
function initPage() {
// 这里你可以进行程序的初始化了
}
// 自己的写法
(function ($) {
var MyApp = {};
MyApp.init = function () {
console.log('初始化工作');
};
$(MyApp.init);
}(jQuery));
(4)进一步,最好也将ready事件的处理程序放到外部文件中引入到页面,而页面中内嵌的代码只需调用即可。
<script src="my-document-ready.js"></script>
<script>
// 初始化一些必要的全局变量
$(document).ready(initPage); // 或 $(initPage);
</script>
(5)千万不要写内联到HTML的JS代码,这是调试的梦魇!应该总是用jQuery来绑定事件自带程序,这样也方便随时动态地取消绑定。
<a id="myLink" href="#" onclick="myEventHandler();">my link</a> <!--不好 -->
$("#myLink").on("click", myEventHandler); // GOOD
6.如果可能尽量在绑定事件处理程序时使用一个命名空间,这样可以方便地取消绑定而不会影响其他绑定。
$("#myLink").on("click.mySpecialClick", myEventHandler); // 不错
// 之后,让我们优雅地解除绑定
$("#myLink").unbind("click.mySpecialClick");
(1) 直接用$.ajax()
而不要去用$.getJson()
或 $.get()
,因为jQuery
内部还是将其转为前者
(2)不要对HTTPS站点使用HTTP去发起请求,最好干脆就不要指定(将HTTP或者HTTPS从你的URL中移除)
(3)不要在链接里面嵌参数,请使用专门的参数设置来传递
// 不易阅读的代码
$.ajax({
url: "something.php?param1=test1¶m2=test2",
//....
});
// 更易阅读
$.ajax({
url: "something.php",
data: {
param1: test1,
param2: test2
}
});
(4)尽量指明数据类型以便你自己清楚要处理什么样的数据(见下方会提到的Ajax
模板)
(5)对于异步动态加载的内容,最好使用代理来绑定事件处理程序。这样的好处是对于之后动态加载的元素事件同样有效。
$('#parent-container').on('click', 'a', delegatedClickHandlerForAjax);
(6)使用Promise
模式
$.ajax({
//...
}).then(successHandler, failureHandler);
// 抑或
var jqxhr = $.ajax({
// ...
});
jqxhr.done(successHandler);
jqxhr.fail(failureHandler);
(7)标准的Ajax
模板一分。追寻根源
var jqxhr = $.ajax({
url: url,
type: 'GET', // 默认为GET,你可以根据需要更改
cache: true, // 默认为true,但对于script,jsonp类型为false,可以自行设置
data: {}, // 将请求参数放这里.
dataType: 'json', // 指定想要的数据类型
jsonp: 'callback', // 指定回调处理JSONP类型的请求
statusCode: { // 如果你想处理各状态的错误的话
404: handler404,
500: handler500
}
});
jqxhr.done(successHandler);
jqxhr.fail(failureHandler);
(1)保持一个始终如一风格统一的动画实现
(2)紧遵用户体验,不要滥用动画特效
(1)始终选择一个有良好支持,完善文档,全面测试过并且社区活跃的插件
(2)注意所用插件与当前使用的jQuery版本是否兼容
(3)一些常用功能应该写成jQuery插件。一分jQuery插件的编写模板
(1)除了用变量将jQuery选择器返回的结果保存,还可以利用好链式调用。
$("#myDiv").addClass("error").show();
(2)当链式调用多达3次以上或代码因绑定回调略显复杂时,使用换行和适当的缩进来提高代码的可读性。
$("#myLink")
.addClass("bold")
.on("click", myClickHandler)
.on("mouseover", myMouseOverHandler)
.show();
(3)对于特别长的调用最好还是用变量保存下中间结果来简化代码。
(1)使用对象字面量来传递参数
// 糟糕:调用了三次attr
$myLink.attr('href', '#').attr('title', 'my link').attr('rel', 'external');
// 不错,只调用了一次attr
$myLink.attr({
href: '#',
title: 'my link',
rel: 'external'
});
(2)不要将CSS与jQuery杂揉
$('#mydiv').css({'color':red, 'font-weight':'bold'}); // 不好
/* 不错 */
.error {
color: red;
font-weight: bold;}
$('#mydiv').addClass('error');
(3)时刻关注官方Changelog
,不要使用摒弃了的方法。点此查看所有废弃的方法
(4)适时地使用原生JavaScript。一些与此有关的性能比较
$("#myId"); // 多少还是会逊色于`document.getElementById("myId")`
REFERENCE
原文:Coding Standards & Best Practices http://lab.abhinayrathore.com/jquery-standards/
Revision: 2015.11.02
注意:该文档为windows7下Android实践随笔。
这里介绍的热更新服务由ReactNative中文网提供,使用之前请先注册
原文请戳这里
首先你应该有一个基于React Native开发的应用,我们把具有package.json的目录叫做你的"应用根目录"。
如果你还没有初始化应用,请参阅开始使用React Native。
所以我们也假设你已经拥有了开发React Native应用的一切环境,包括Node.js、npm、XCode、Android SDK等等。
如果你之前没安装过,你还必须安装Android NDK,并设置环境变量ANDROID_NDK_HOME,指向你的NDK根目录(例如/Users/tdzl2003/Downloads/android-ndk-r10e)。
在你的项目根目录下运行以下命令:
npm install -g react-native-update-cli rnpm
npm install --save react-native-update
rnpm link react-native-update
说明:
npm install -g react-native-update-cli rnpm
这一句在每一台电脑上仅需运行一次(因为全局安装)。
rnpm link react-native-update
(这句的作用简单的看来就是在项目的Java代码中添加包引用,可以在执行前后查看
MainActivity.java的区别)
mac 可能遇到无读写权限等问题
注意
如果访问极慢或者显示网络失败,请使用淘宝镜像:
npm config set registry https://registry.npm.taobao.org --global
npm config set disturl https://npm.taobao.org/dist --global
Windows平台请注意
// TODO:IOS 暂未实践,实践后更新文档
在工程target的Build Phases->Link Binary with Libraries中加入libz.tbd、libbz2.1.0.tbd
在你的AppDelegate.m文件中增加如下代码:
// ... 其它代码
#import "RCTHotUpdate.h"
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
#if DEBUG
// 原来的jsCodeLocation
jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios&dev=true"];
#else
jsCodeLocation=[RCTHotUpdate bundleURL];
#endif
// ... 其它代码
}
在你的MainActivity中增加如下代码:
// ... 其它代码
import cn.reactnative.modules.update.UpdateContext;
public class MainActivity extends ReactActivity {
@Override
protected String getJSBundleFile() {
return UpdateContext.getBundleUrl(this);
}
// ... 其它代码
}
在项目根目录(如:D:\Java\AndroidStudio\React-Native\HelloRN
)下运行以下命令:
cd /d D:\Java\AndroidStudio\React-Native\HelloRN
pushy login
email: <输入你的注册邮箱>
password: <输入你的密码>
操作示例结果:
C:\Users\ML>cd /d D:\Java\AndroidStudio\React-Native\HelloRN
D:\Java\AndroidStudio\React-Native\HelloRN>pushy login
email: [email protected]
password: ********
Welcome, mlwills.
这会在项目文件夹下创建一个.update
文件,注意不要把这个文件上传到Git
等CVS
系统上。
你可以在.gitignore
末尾增加一行.update
来忽略这个文件。
注意:迄今为止免费用户最多只可以创建3
个应用
登录之后可以创建应用。注意iOS平台和安卓平台需要分别创建:
pushy createApp --platform ios
App Name: <输入应用名字>
pushy createApp --platform android
App Name: <输入应用名字>
两次输入的名字可以相同,这没有关系。
如下:
D:\Java\AndroidStudio\React-Native\HelloRN>pushy createApp --platform android
App Name: HelloRN
Created app 1145
D:\Java\AndroidStudio\React-Native\HelloRN>pushy createApp --platform ios
App Name: HelloRN
Created app 1146
如果你已经在网页端或者其它地方创建过应用,也可以直接选择应用:
pushy selectApp --platform android
970 IReactNative
1101 IReactNative
Total 2 android apps
Enter appId: <输入应用前面的编号>
(如果选取ios应用就改变后面的参数为ios:pushy selectApp --platform ios
)
选择或者创建过应用后,你将可以在文件夹下看到update.json
文件,其内容类似如下形式:
{
"ios": {
"appId": 1,
"appKey": "<一串随机字符串>"
},
"android": {
"appId": 1101,
"appKey": "<一串随机字符串>"
}
}
{
"android": {
"appId": 1145,
"appKey": "_fZxhBVRAfsklFcuSv9Z5UoiK_p3kdEs"
},
"ios": {
"appId": 1146,
"appKey": "DyuRMeip_-vIN4PbP70-t0Ln6iP4BJa6"
}
}
你可以安全的把update.json
上传到Git
等CVS
系统上,与你的团队共享这个文件,它不包含任何敏感信息。当然,他们在使用任何功能之前,都必须首先输入pushy login
进行登录。
至此应用的创建/选择就已经成功了。下一步,你需要给代码添加相应的功能,请参阅添加热更新功能
本文是根据生成已签名的APK
在Windows 7 系统上的实践,如果非Windows系统可以查看原文。
在此介绍生成签名秘钥的两种方法(人选其一)
keytool
生成Android Studio
生成
keytool
,一个密钥与证书管理工具,安装Java
后可以在JDK的bin
可以找到。
Android Studio 等IDE自带的生成工具要比命令行方便,如果你安装了Android Studio等工具可以
忽略该方法。
windows在DOS命令行中输入
keytool -genkey -v -keystore app-release-key.keystore -alias app-key-alias -keyalg RSA -keysize 2048 -validity 10000
然后根据提示,输入自己的内容即可,如下所示
C:\Users\ML> keytool -genkey -v -keystore app-release-key.keystore -alias app-key-
alias -keyalg RSA -keysize 2048 -validity 10000
输入密钥库口令:
再次输入新口令:
您的名字与姓氏是什么?
[Unknown]: mlwills
您的组织单位名称是什么?
[Unknown]: GZZTWLKM
您的组织名称是什么?
[Unknown]: GZZTWLKM
您所在的城市或区域名称是什么?
[Unknown]: 昆明
您所在的省/市/自治区名称是什么?
[Unknown]: 云南/昆明市/盘龙区
该单位的双字母国家/地区代码是什么?
[Unknown]: CN
CN=mlwills, OU=GZZTWLKM, O=GZZTWLKM, L=昆明, ST=云南/
昆明市/盘龙区, C=CN是否正确?
[否]: 是
正在为以下对象生成 2,048 位RSA密钥对和自签名证书 (SHA256withRSA) (有效期为 10,00
0 天):
CN=mlwills, OU=GZZTWLKM, O=GZZTWLKM, L=昆明,
ST=云南/昆明市/盘龙区, C=CN
输入 <app-key-alias> 的密钥口令
(如果和密钥库口令相同, 按回车):
再次输入新口令:
[正在存储app-release-key.keystore]
注意:记得记录相应的秘钥名称、别名、密码,后面将会使用到
完成之后,可以在相应的目录下(示例中为:C:\Users\ML>
)找到签名秘钥
app-release-key.keystore
。
步骤如下:
Build
-->Generate Signed APK
-->Create New
jks
),填写其它信息,点击【OK】完成注意:同样要记住名称、别名和密码(密码太多可以设置成一致)
选择一种方法生成秘钥,然后将其拷贝到React Native项目中的android\app\
路径下
(如:D:\Java\AndroidStudio\React-Native\HelloRN\android\app
)
说明:以项目HelloRN为例
打开(HelloRN\android\gradle.properties
)
添加如下内容(#
是注释符)
#以下是秘钥配置信息
#采用keytool生成的keystore秘钥(使用请删除前面的#注释)
#MYAPP_RELEASE_STORE_FILE=app-release-key.keystore
#MYAPP_RELEASE_KEY_ALIAS=app-release-key-alias
#MYAPP_RELEASE_STORE_PASSWORD=yourpassword
#MYAPP_RELEASE_KEY_PASSWORD=yourpassword
#采用Android Studio 生成的jks秘钥
MYAPP_RELEASE_STORE_FILE=app-release-key.jks
MYAPP_RELEASE_KEY_ALIAS=app-release-key-alias
MYAPP_RELEASE_STORE_PASSWORD=yourpassword
MYAPP_RELEASE_KEY_PASSWORD=yourpassword
注意:可能存在多个gradle配置文件,请注意别找错
打开HelloRN\android\app\build.gradle
找到android{ /*之前已经有很过配置项*/}
,把以下内容添加到其中:
...
android {
...
defaultConfig { ... }
// 添加 signingConfigs >>>
signingConfigs {
release {
storeFile file(MYAPP_RELEASE_STORE_FILE)
storePassword MYAPP_RELEASE_STORE_PASSWORD
keyAlias MYAPP_RELEASE_KEY_ALIAS
keyPassword MYAPP_RELEASE_KEY_PASSWORD
}
}
// 添加 signingConfigs <<<
buildTypes {
release {
...
// 在buildTypes中添加如下的配置
signingConfig signingConfigs.release
}
}
}
...
示例的完整android
配置如下(添加部分做了详细的说明)
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
applicationId "com.hellorn"
minSdkVersion 16
targetSdkVersion 22
versionCode 1
versionName "1.0"
ndk {
abiFilters "armeabi-v7a", "x86"
}
}
/* add by mlwills@20160520 */
signingConfigs {
release {
storeFile file(MYAPP_RELEASE_STORE_FILE)
storePassword MYAPP_RELEASE_STORE_PASSWORD
keyAlias MYAPP_RELEASE_KEY_ALIAS
keyPassword MYAPP_RELEASE_KEY_PASSWORD
}
}
/* add by mlwills end */
splits {
abi {
reset()
enable enableSeparateBuildPerCPUArchitecture
universalApk false // If true, also generate a universal APK
include "armeabi-v7a", "x86"
}
}
buildTypes {
release {
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
/* add by mlwills@20160520 */
signingConfig signingConfigs.release
}
}
// applicationVariants are e.g. debug, release
applicationVariants.all { variant ->
variant.outputs.each { output ->
// For each separate APK per architecture, set a unique version code as described here:
// http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits
def versionCodes = ["armeabi-v7a":1, "x86":2]
def abi = output.getFilter(OutputFile.ABI)
if (abi != null) { // null for the universal-debug, universal-release variants
output.versionCodeOverride =
versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
}
}
}
}
只要在项目的android 目录下运行以下命令:
gradlew assembleRelease
如:cd /d D:\Java\AndroidStudio\React-Native\HelloRN\android && gradlew assembleRelease
打包成功之后就可以在android\app\build\outputs\apk
下找到app-release.apk
本示例在D:\Java\AndroidStudio\React-Native\HelloRN\android\app\build\outputs\apk\
如果你希望改变JavaScript代码包或者资源文件被打包的方式(譬如你想改变这些文件存放的目录或者整个工程的文件结构),
你可以读一下android/app/build.gradle看看你可以做什么配置来应用这些修改。
注意:笔者在践行时没有react.gradle,升级RN之后也没有,而且升级存在风险,请谨慎操作!!!
那我们这样做:
(1)在android/app/src/main/
下建立assets
文件夹(如果有该文件夹或之前运行过RN创建了该文件夹,可以省略该步骤)
(2)在项目根目录下(D:\Java\AndroidStudio\React-Native\HelloRN\
)运行一下命令进行JS打包
react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/
C:\Users\ML>cd /d D:\Java\AndroidStudio\React-Native\HelloRN
D:\Java\AndroidStudio\React-Native\HelloRN>react-native bundle --platform androi
d --dev false --entry-file index.android.js --bundle-output android/app/src/main
/assets/index.android.bundle --assets-dest android/app/src/main/res/
...
transformed 359/359 (100%)
[11:37:48] <END> find dependencies (13471ms)
bundle: start
bundle: finish
bundle: Writing bundle output to: android/app/src/main/assets/index.android.bund
le
bundle: Done writing bundle output
bundle: Copying 5 asset files
bundle: Done copying assets
(3)生成APK
在RN项目的android目录下运行
gradlew assembleRelease
本机执行如下:
cd /d D:\Java\AndroidStudio\React-Native\HelloRN\android && gradlew assembleRelease
至此一个带签名的React Native APK 就打包成功了。
在把发行版本公布之前,你应该做一次最终测试。输入以下命令可以在设备上安装发行版本:
cd /d D:\Java\AndroidStudio\React-Native\HelloRN\android && gradlew installRelease
注意:
installRelease
命令只能在你完成了上面的签名配置之后才可以使用。Proguard
是一个Java字节码混淆压缩工具,它可以移除掉React Native Java(和它的依赖库中)中没有被使用到的部分,
最终有效的减少APK
的大小。
**重要:**启用Proguard之后,你必须再次全面地测试你的应用。
Proguard有时候需要为你引入的每个原生库做一些额外的配置。参见app/proguard-rules.pro
文件。
要启用Proguard
,编辑android/app/build.gradle
文件:
默认值为false
,改为true
/**
* Run Proguard to shrink the Java bytecode in release builds.
*/
def enableProguardInReleaseBuilds = true
再次生成APK,可以看到原先7.4MB的压缩包变为了6.79MB。(比我想象的要差点!)
React Native 官方组件一览表(截止至20160520)
组件类型 | 个数 |
所有组件 | 32 |
通用组件 | 19 |
IOS组件 | 9 |
Android组件 | 4 |
组件 | 说明 | |
ActivityIndicatorIOS | 加载指示器(菊花) | |
DatePickerIOS | 日期选择器 | |
DrawerLayoutAndroid | 侧边栏 | |
Image | 图片 | |
ListView | 列表视图 | |
MapView | 地图 | |
Modal | 模态框 | |
Navigator | 导航 | 不易使用 |
NavigatorIOS | IOS导航 | 各种视图切换就靠它 |
PickerIOS | IOS的下拉控件 | |
Picker | 普通下拉控件 | |
ProgressBarAndroid | Android的Loading | |
ProgressViewIOS | 进度条 | UIProgressView |
RefreshControl | 下拉时出现的Loading | 配合ScrollView使用 |
ScrollView | 滚动视图 | 上滑、下滑全靠它 |
SegmentedControlIOS | IOS的单选框 | |
Slider | 范围选择组件 | 常用数值范围 |
SliderIOS | IOS范围选择组件 | |
StatusBar | 用于控制应用状态栏的组件 | |
Switch | 开关 | |
TabBarIOS | IOS选项卡 | 常用于首页 |
TabBarIOS.Item | IOS选项卡项 | |
Text | 文本组件 | 用于显示文本,文本不能游离在其它组件中 |
TextInput | 文本输入框 | |
ToolbarAndroid | Android工具栏 | |
TouchableHighlight | 点击触摸时高亮 | |
TouchableNativeFeedback | ||
TouchableOpacity | 触摸时透明 | |
TouchableWithoutFeedback | 触摸时无响应 | |
View | 视图 | 作用类似于Web中的div |
ViewPagerAndroid | Android翻页视图 | |
WebView | 渲染一个原生的Web视图 | 可以加载html页面 |
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.