[RN] 02 - Overview: React Native Practice of 50 lectures

觀看筆記:零基礎 React Native 實戰開發視頻 50講html

本篇效果:RN入門,總體認識react


 

基本原理 # 1

 

React到RN # 2

一個簡單的例子android

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 */
'use strict';
import React, {
  AppRegistry,
  Component,
  StyleSheet,
  Text,
  View
} from 'react-native';
# 引入組件
class DongFang extends Component { render() {
return ( <View style={styles.container}> <Text style={styles.welcome}> Welcome to React Native!東方耀的第5課 </Text> <Text style={styles.instructions}> To get started, edit index.android.js </Text> <Text style={styles.instructions}> Shake or press menu button for dev menu </Text> </View> ); } }
# 樣式表 系統api const styles
= StyleSheet.create({ container: { # 可伸縮的表 flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, welcome: { fontSize: 20, textAlign: 'center', margin: 10, }, instructions: { textAlign: 'center', color: '#333333', marginBottom: 5, }, }); AppRegistry.registerComponent('DongFang', () => DongFang);

 

flexbox佈局 # 3,4,5

UI利器:彈性盒子佈局,主流瀏覽器都支持。git

講義:http://www.cnblogs.com/dfy888/p/5374329.htmlgithub

參考:阮一峯: Flex 佈局教程:語法篇chrome

參考:阮一峯Flex 佈局教程:實例篇json

 

JSX入門 # 6

jsx是個語法糖;react-native

(1) 轉換 解析器 html --> js,而後在瀏覽器運行。 api

(2) 執行js表達式。html with js --> js數組

(3) 執行js表達式。屬性 --> js

(4) 執行js表達式。延展屬性 --> js,使用ES6語法。

(5) 以字符串的形式完整顯示HTML,藉助_html屬性

(6) 樣式style的使用,好比顏色,字體大小。

(7) 事件綁定 - button

 

ReactJS代碼結構 # 7

React.createClass: 建立組件類的方法。

React.render: 將制定組件渲染到制定的DOM節點。【會被ReactDOM.render替代】

 

ReactJS組件生命週期 # 8

Ref: React Native Component Lifecycle【簡潔,清晰】

如圖,能夠把組件生命週期大體分爲三個階段:

    • 第一階段:是組件第一次繪製階段,如圖中的上面虛線框內,在這裏完成了組件的加載和初始化;
    • 第二階段:是組件在運行和交互階段,如圖中左下角虛線框,這個階段組件能夠處理用戶交互,或者接收事件更新界面;
    • 第三階段:是組件卸載消亡的階段,如圖中右下角的虛線框中,這裏作一些組件的清理工做。

 

生命週期 調用次數 可否使用 setSate()
建立階段,處理props的默認值
getDefaultProps 1(全局調用一次)

實例化階段,React.render(<HelloMessage 啓動以後

State:ReactJS內部監聽state屬性的變化,一旦發生變化,主動觸發組件的render方法更新虛擬DOM結構, which is 真實的DOM結構映射成一個json數據結構。

getInitialState 1
componentWillMount 1
render >=1
componentDidMount 1
更新階段,根據用戶操做行爲進行相應的頁面結構的調整。
componentWillReceiveProps >=0
shouldComponentUpdate >=0
componentWillUpdate >=0
componentDidUpdate >=0
銷燬階段,取消事件綁定、移除虛擬DOM等。
componentWillUnmount 1

 

ReactJS組件通訊 # 9

父子組件之間的通訊方式?

Ref: http://blog.csdn.net/p106786860/article/details/52408875 【代碼實例】

var Parent=React.craeteClass({
  click:function() {
    this.refs.child.getDOMNode().stype.color="red";
  },
  render:function() {
    return (
      <div onClick={this.click} >Parent is :
      <Child name={this.props.name} ref="child"></Child>
      </div> );   #子組件 調用 父組件
  }
});
var Child=React.craeteClass({
  render:function() {
    return <span> {this.props.name} </span>
  }
});
ReactDOM.render(<Parent name="React語法基礎" />, document.getElementById('example'));

 

Ref: react native 之子組件和父組件之間的通訊

*** 父組件 --> 子組件 ***

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *  父組件傳遞給子組件
 *  父組件把值或者navigator傳給子組件,而後在子組件裏面實現push和顯示
 */

import React, { Component } from 'react';
import ChildOne from './ChildOne'
import {
    AppRegistry,
    StyleSheet,
    Text,
    View
} from 'react-native';

export default class HomeOne extends Component {
    render() {
        return (
// 相似:調用函數,將參數傳入子函數,將參數看做一種通訊方式
<ChildOne navigatorPush = {this.props.navigator} passValue = '我是一個父組件傳給子組件的值'/> ); } } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, welcome: { fontSize: 20, textAlign: 'center', margin: 10, }, instructions: { textAlign: 'center', color: '#333333', marginBottom: 5, }, });

子組件,childOne的代碼:經過 this.props.屬性名 使用傳過來的值。

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *  父組件傳遞給子組件
 */

import React, { Component } from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    View,
    navigator,
} from 'react-native';
import OneDetails from
'./OneDetails'
export default class ChildOne extends Component { render() { return ( <View style={styles.container}> <Text style={styles.welcome} onPress={()=>this.pushOneDetails()}> 我是子組件ONE </Text> <Text> {this.props.passValue}  # 直接獲取 </Text> </View> ); } pushOneDetails = ()=>{ this.props.navigatorPush.push({    component: OneDetails    })   } } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, welcome: { fontSize: 20, textAlign: 'center', margin: 10, }, instructions: { textAlign: 'center', color: '#333333', marginBottom: 5, }, });

 

*** 父組件 --> 子組件 ***

子組件經過定義一個屬性直接把事件傳遞給主組件。

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *  子組件傳遞給父組件
 */

import React, { Component } from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    View
} from 'react-native';


export default class ChildTwo extends Component {
 static defaultProps = {
        two: '我是子組件傳給主組件的值' };
    render() {
        return (
                <Text style={styles.welcome} onPress={()=>this.passMenthod()}>
                    我是子組件TWO
                </Text>
        );
    }
 passMenthod = () =>{
        this.props.pushDetails() }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
    },
    welcome: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
    },
    instructions: {
        textAlign: 'center',
        color: '#333333',
        marginBottom: 5,
    },
});

父組件這邊直接經過子組件的屬性來接受事件,從而在主組件這邊push和pop。

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *  子組件傳遞給父組件
 *  子組件把事件或值傳遞給父組件,而後在父組件push和顯示
 */

import React, { Component } from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    View
} from 'react-native';
import ChildTwo   from './ChildTwo'
import TwoDetails from './TwoDetails'
export default class HomeTwo extends Component { // 構造 constructor(props) { super(props); // 初始狀態 this.state = { value:'' }; } render() { return ( <View style={styles.container}> <ChildTwo pushDetails = {()=>this.pushDetails()} /> <Text> {ChildTwo.defaultProps.two} </Text> </View> ); } pushDetails = ()=>{ this.props.navigator.push({ component:TwoDetails }) } } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, welcome: { fontSize: 20, textAlign: 'center', margin: 10, }, instructions: { textAlign: 'center', color: '#333333', marginBottom: 5, }, });

 

整體感受,須要一個系統的文章來學習,以上關於通訊這塊,仍是很零碎,須要看書上的相關章節來系統地增強認識。

 

 

狀態、屬性、樣式

繼續細細分析【props】和【state】in: [RN] Try a little bit of React Native

 

咱們使用兩種數據來控制一個組件:props和state。

    • props: 在父組件中指定,並且一經指定,在被指定的組件的生命週期中則再也不改變。 
    • state: 對於須要改變的數據,咱們須要使用state。

 

  • 關於屬性:props

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react';
import {
  Platform,
  StyleSheet,
  Text,
  View,
  Image
} from 'react-native';

export default class App extends Component {
  render() {
let pic
= { uri: 'https://upload.wikimedia.org/wikipedia/commons/d/de/Bananavarieties.jpg' }; // 以下:pic 被一個 控件所引用 return ( <Image source={pic} style={{width: 193, height: 110}}/> );
} }
<Image/>

 

{pic} 括號把JSX語句嵌入其中,括號裏多是表達式也能夠是js變量,因此,這一切 均可以是 動態的。

例以下面這代碼:

import React, { Component } from 'react';
import { AppRegistry, Text, View } from 'react-native';

// 建立了一個 Greeting 對象 class Greeting extends Component { render() {
return ( <Text>Hello {this.props.name}!</Text> );
} } class LotsOfGreetings extends Component { render() {
return ( <View style={ {alignItems: 'center'} }> <Greeting name='Rexxar' /> <Greeting name='Jaina' /> <Greeting name='Valeera' /> </View> ); }
} AppRegistry.registerComponent(
'LotsOfGreetings', () => LotsOfGreetings);

  

  • 關於狀態:state 

1 .props是在父組件中指定,一經指定,在被指定的生命週期中則再也不改變

2 .對於須要改變的數據,咱們須要使用state

3 .須要在constructor中初始化state,而後在須要修改時調用setState方法。 

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow 此代碼可直接運行
 */

import React, { Component } from 'react';
import {
  Platform,
  StyleSheet,
  Text,
  View
} from 'react-native';


class Blink extends Component {
constructor(props) { super(props);
this.state = { showText: true };
// 調用計時器方法
// 每1000毫秒對showText狀態作一次取反操做 setInterval(() => { this.setState({ showText: !this.state.showText }); }, 1000); }
render() {
// 根據當前showText的值決定是否顯示text內容 let display = this.state.showText ? this.props.text : ' '; return ( <Text>{display}</Text> ); }
}
// main export default class App extends Component<Props> { render() { return ( <View> <Blink text='I love to blink' /> <Blink text='Yes blinking is so great' /> <Blink text='Why did they ever take this out of HTML' /> <Blink text='Look at me look at me look at me' /> </View> ); } }

 

  • 關於樣式:style

一個View能夠有多個樣式屬性,他們以數組形勢共存,

固然若是多個樣式出現重複,排在右邊的會覆蓋以前的,具體狀況咱們看一例子:

import React, { Component } from 'react';
import { AppRegistry, StyleSheet, Text, View } from 'react-native';

class LotsOfStyles extends Component {
  render() {
    return (
      <View>
        <Text style={styles.red}>just red</Text>
        <Text style={styles.bigblue}>just bigblue</Text>
        <Text style={[styles.bigblue, styles.red]}>bigblue, then red</Text>
        <Text style={[styles.red, styles.bigblue]}>red, then bigblue</Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  bigblue: {
    color: 'blue',
    fontWeight: 'bold',
    fontSize: 30,
  },
  red: {
    color: 'red',
  },
});

AppRegistry.registerComponent('LotsOfStyles', () => LotsOfStyles);

 

 

JSX實戰 # 10,11

  • 調試五步驟

(1). 啓動js服務器。

 

(2). 肯定手機鏈接可靠。

(3). 加載代碼。

 

(4). 設置爲與本地同一網段:Dev Settings。 

 

(5). 點擊Debug server host & port for device,設置ip地址。

 

Reload JS:手動刷新

Debug JS:遠端調試工具,須要chrome。

Enable Live Reload:自動刷新

檢查元素

Enable Perf Monitor

Dev Settings

 

原理:包服務器,手機端調試依賴這個bundle,也涉及到熱更新。

 

F12進入開發者模式,而後經過瀏覽器調試,這是Google的牛逼之處。【Debug JS】

固然,Facebook的RN也提供了在線手機上的簡單版本的frond-end調試。【檢查元素】

 

 

發佈六步驟

(1). 建立密鑰

keytool -genkey -v -keystore my-release-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000

 生成了用於應用發佈的祕鑰: my-release-key.keystore

 

(2). bundle文件

在工程目錄下將index.android.bundle下載並保存到assets資源文件中。

首先,建立文件夾:./android/app/src/main/assets;而後,執行命令:

curl -k "http://localhost:8081/index.android.bundle" > android/app/src/main/assets/index.android.bundle

 

(3). 配置gradle中的簽名

 

(4). 在build.gradle中設置密鑰的屬性

接下來,使簽名生效:添加一行,以下:

 

(5). 爲減少發佈包的大小,修改以下屬性爲true

若是是涉及到第三方庫,會修改app/proguard-rules.pro。在此,先保持默認配置。

 

(6). gradle打包併發布

在android目錄下執行,便自動編譯打包。

gradle assembleRelease

執行成功後在下面的目錄中會生成對應的release的兩個版本。

 

 

如何生成APK?

From: 無簽名的:https://www.jianshu.com/p/32a99c273be1

From: 有簽名的:React Native發佈APP之簽名打包APK ----> 生成的位置是./android/app/目錄下

"Android要求全部的APP都須要進行數字簽名後,纔可以被安裝到相應的設備上。"

 

注意事項:
1. 在開發環境下,爲方便調試,APP會在啓動時從JS Server服務器將index.android.bundle文件加載到APP。 
2. 簽名打包後的APP變成了生產環境,此時APP會默認從本地加載 index.android.bundle文件,因爲經過Android Studio打包的APK沒有將index.android.bundle文件打包進apk,因此會因缺乏index.android.bundle文件而沒法啓動。

 

Step 1:

RN主目錄:

keytool -genkey -v -keystore my-release-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000 [注:在產生的時候須要提供密鑰和存儲密碼,後續會用到] mv my-release-key.keystore android/app/

 

Step 2: 

android/gradle.properties文件:

MYAPP_RELEASE_STORE_FILE = my-release-key.keystore  // 簽名文件
MYAPP_RELEASE_KEY_ALIAS = my-key-alias
MYAPP_RELEASE_STORE_PASSWORD = xx
MYAPP_RELEASE_KEY_PASSWORD = xx

[注意替換xx爲你本身設置的密鑰和存儲密碼]

 

Step 3:

android/app/build.gradle文件:

... android { ... defaultConfig { ... } 

signingConfigs { release { storeFile
file(MYAPP_RELEASE_STORE_FILE) storePassword MYAPP_RELEASE_STORE_PASSWORD keyAlias MYAPP_RELEASE_KEY_ALIAS keyPassword MYAPP_RELEASE_KEY_PASSWORD } }
buildTypes { release { ... signingConfig signingConfigs.release } } }

 

Step 4: 
 cd android/
./gradlew assembleRelease
相關文章
相關標籤/搜索