React Native的Text

用于显示文本的React组件。 文本支持嵌套,样式和触摸处理。 在以下示例中,嵌套标题和正文文本将从styles.baseText继承fontFamily,但标题提供了自己的附加样式。 标题和主体将叠加在一起,因为文字换行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import React, { Component } from 'react';
import { AppRegistry, Text, StyleSheet } from 'react-native';

class TextInANest extends Component {
  constructor(props) {
    super(props);
    this.state = {
      titleText: "Bird's Nestaaa",
      bodyText: 'This is not really a bird nest.'
    };
  }

  render() {
    return (
      <Text style={styles.baseText}>
        <Text style={styles.titleText} onPress={this.onPressTitle}>
          {this.state.titleText}{'\n'}{'\n'}
        </Text>
        <Text numberOfLines={5}>
          {this.state.bodyText}
        </Text>
      </Text>
    );
  }
}

const styles = StyleSheet.create({
  baseText: {
    fontFamily: 'Cochin',
  },
  titleText: {
    fontSize: 20,
    fontWeight: 'bold',
  },
});

// App registration and rendering
AppRegistry.registerComponent('TextInANest', () => TextInANest);

Read on →

React Native的布局

Style样式

使用React Native,不要使用特殊语言或语法来定义样式。 你只需使用JavaScript来设计你的应用程序。 所有的核心组件接受props命名风格。 样式名称和值通常匹配CSS在Web上的工作方式,除了名称被写为backgroundColor而不是像background-color。 样式prop可以是一个普通的旧JavaScript对象。 这是最简单的,我们通常用于示例代码。 您还可以传递样式数组 - 数组中的最后一个样式具有优先级,因此可以使用它来继承样式。 由于组件的复杂性增加,使用StyleSheet.create在一个位置定义多个样式通常更加清晰。 这里有一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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);
一个常见的模式是使你的组件接受一个样式属性,反过来,它被用于样式子组件。 你可以使用它来使样式“级联”他们在CSS中的方式。 Read on →

React Native的State

有两种类型的数据控制组件:props和state。 props由父节点设置,它们在组件的整个生命周期中都是固定的。 对于要改变的数据,我们必须使用状态。 一般来说,你应该在构造函数中初始化状态,然后当你想改变它时调用setState。 例如,假设我们想让文本一直闪烁。 文本本身在创建闪烁组件时设置一次,因此文本本身是一个props。 “文本是否当前打开或关闭”随时间改变,所以应保持状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import React, { Component } from 'react';
import { AppRegistry, Text, View } from 'react-native';

class Blink extends Component {
  constructor(props) {
    super(props);
    this.state = {showText: true};

    // Toggle the state every second
    setInterval(() => {
      this.setState({ showText: !this.state.showText });
    }, 1000);
  }

  render() {
    let display = this.state.showText ? this.props.text : ' ';
    return (
      <Text>{display}</Text>
    );
  }
}

class BlinkApp extends Component {
  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>
    );
  }
}

AppRegistry.registerComponent('BlinkApp', () => BlinkApp);
在实际应用中,您可能不会使用计时器设置状态。 您可以在从服务器收到新数据或用户输入时设置状态。 您还可以使用状态容器(如Redux)来控制数据流。 在这种情况下,您将使用Redux来修改状态,而不是直接调用setState。 Read on →

React Native的Props

大多数组件可以在创建时使用不同的参数进行自定义。 这些创建参数称为props。 例如,一个基本的React Native组件是Image。 当您创建图像时,可以使用prop命名source来控制其显示的图像。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import React, { Component } from 'react';
import { AppRegistry, Image } from 'react-native';

class Bananas extends Component {
  render() {
    let pic = {
      uri: 'https://upload.wikimedia.org/wikipedia/commons/d/de/Bananavarieties.jpg'
    };
    return (
      <Image source={pic} style=/>
    );
  }
}

AppRegistry.registerComponent('Bananas', () => Bananas);
注意{pic}被大括号括起来,以将变量pic嵌入到JSX中。 你可以把任何JavaScript表达式放在大括号内JSX。 你自己的组件也可以使用props。 这样,您可以在应用程序的许多不同位置创建单个组件,每个位置的属性略有不同。 只需在render函数中引用this.props。 这里有一个例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import React, { Component } from 'react';
import { AppRegistry, Text, View } from 'react-native';

class Greeting extends Component {
  render() {
    return (
      <Text>Hello {this.props.name}!</Text>
    );
  }
}

class LotsOfGreetings extends Component {
  render() {
    return (
      <View style=>
        <Greeting name='Rexxar' />
        <Greeting name='Jaina' />
        <Greeting name='Valeera' />
      </View>
    );
  }
}

AppRegistry.registerComponent('LotsOfGreetings', () => LotsOfGreetings);
使用名称作为props,我们可以自定义Greeting组件,因此我们可以为每个问候重复使用该组件。 此示例还在JSX中使用Greeting组件,就像内置组件一样。 做到这一点的力量是什么使React这么酷 - 如果你发现自己希望有一组不同的UI原语来工作,你只是发明新的。 Read on →

JSX从0到1

什么是JSX。我们先看一段代码,考虑这个变量声明:

1
const element = <h1>Hello, world!</h1>;
这个有趣的标签语法既不是字符串也不是HTML。 它被称为JSX,它是JavaScript的语法扩展。 我们建议使用它与React来描述UI应该是什么样子。 JSX可以提醒你一个模板语言,但它伴随着JavaScript的全部力量。 JSX产生React“元素”。 我们将在下一节中探讨将它们渲染到DOM。 下面,你可以找到JSX的基础知识,让你开始。

在JSX中嵌入表达式

您可以通过将其包含在大括号中来在JSX中嵌入任何JavaScript表达式。 例如,2 + 2,user.name和formatName(user)都是有效的表达式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function formatName(user) {
  return user.firstName + ' ' + user.lastName;
}

const user = {
  firstName: 'Harper',
  lastName: 'Perez'
};

const element = (
  <h1>
    Hello, {formatName(user)}!
  </h1>
);

ReactDOM.render(
  element,
  document.getElementById('root')
);
我们将JSX拆分为多行以提高可读性。 虽然这不是强制性的,但当执行此操作时,我们还建议将其括在括号中,以避免自动分号插入的陷阱。

JSX是一个表达式

编译后,JSX表达式成为常规JavaScript对象。这意味着您可以在if语句和for循环中使用JSX,将其分配给变量,将其接受为参数,然后从函数中返回:

1
2
3
4
5
6
function getGreeting(user) {
  if (user) {
    return <h1>Hello, {formatName(user)}!</h1>;
  }
  return <h1>Hello, Stranger.</h1>;
}

Read on →

React.js 项目指南

React 是一种声明性、高效和灵活的JavaScript库来构建用户界面。

React 组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class ShoppingList extends React.Component {
  render() {
    return (
      <div className="shopping-list">
        <h1>Shopping List for {this.props.name}</h1>
        <ul>
          <li>Instagram</li>
          <li>WhatsApp</li>
          <li>Oculus</li>
        </ul>
      </div>
    );
  }
}

// Example usage: <ShoppingList name="Mark" />
组件告诉React你想提供的,然后React会在你数据更新时高效更新和提供正确组件。 在这里,ShoppingList 是一个React组件类或者React组件类型。一个组件包含的参数成为props,并且通过render方法返回一个层级视图来显示。 render 方法返回一个描述关于你想render的,并且React采用描述返回给屏幕。特别是,render会返回一个React元素,一个render什么的轻量级描述。许多React开发者使用一个特殊的语法称之为JSX,可以更方便的编写这些结构。div标记在编译时被转化成了React.createElement(‘div’)。
1
2
3
4
return React.createElement('div', {className: 'shopping-list'},
  React.createElement('h1', ...),
  React.createElement('ul', ...)
);
可以将任何 JavaScript 表达式放在大括号内 JSX 内。React的每个元素是一个真正的 JavaScript 对象,可以存储在一个变量或在程序中传递。 ShoppingList组件只能在内置的DOM组件提供,但是你能自己组合一个定制的React组件。通过。每个组件都包含因此他能独立操作,允许你构建复杂的UI通过简单的组件。

实例

通过下面的例子来讲解React: Read on →

React Native开发Redux

Redux是一个可预测的javascript应用程序的状态容器。 它可以帮助您编写行为一致,在不同环境(客户端,服务器和本机)中运行的应用程序,并且易于测试。 此外,它提供了一个伟大的开发者体验,如实时代码编辑结合一个时间旅行调试器。

您可以与React或任何其他视图库一起使用Redux。 它是微小的(2kB,包括依赖)。 从其创建者学习Redux:Redux学习入门

开发经验

我在工作在我的React Europe谈话时写了Redux,名为“Hot Reloading with Time Travel”。 我的目标是创建一个状态管理库,具有最少的API,但完全可预测的行为,所以可以实现日志记录,热重新加载,时间旅行,通用应用程序,记录和重放,没有任何从开发人员买入。

影响

Redux演化了Flux的想法,但通过从Elm提取线索来避免其复杂性。 无论您是否使用过它们,Redux只需要几分钟的时间就可以开始使用。

安装

安装稳定版本:

1
npm install --save redux
这假设你使用npm作为你的包管理器。 最常见的是人们使用Redux作为CommonJS模块的集合。 这些模块是在WebpackBrowserify或Node环境中导入redux时得到的。 如果你喜欢生活在边缘,使用Rollup,我们也支持。 如果你不使用模块bundler,它也没关系。 redux npm包包括在dist文件夹中预编译的生产和开发UMD版本。 它们可以直接使用而无需捆绑器,因此与许多流行的javascript模块加载器和环境兼容。 例如,可以将UMD构建作为script标记放在页面上,或者告诉Bower安装它。 UMD构建使Redux可用作window.Redux全局变量。 Redux源代码是在ES2015中编写的,但我们将CommonJS和UMD构建预编译为ES5,因此它们可在任何现代浏览器中使用。 您不需要使用Babel或模块捆绑包来开始使用Redux

互补包

很可能,您还需要React绑定开发人员工具

1
2
npm install --save react-redux
npm install --save-dev redux-devtools
请注意,与Redux本身不同,Redux生态系统中的许多软件包不提供UMD构建,因此我们建议使用 Webpack Browserify之类的CommonJS模块捆绑软件,以获得最舒适的开发体验。

要点

应用程序的整个状态存储在单个存储中的对象树中。 改变状态树的唯一方法是发出一个动作,一个描述发生了什么的对象。 要指定动作如何转换状态树,您需要编写纯reducer。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import { createStore } from 'redux'

/**
 * This is a reducer, a pure function with (state, action) => state signature.
 * It describes how an action transforms the state into the next state.
 *
 * The shape of the state is up to you: it can be a primitive, an array, an object,
 * or even an Immutable.js data structure. The only important part is that you should
 * not mutate the state object, but return a new object if the state changes.
 *
 * In this example, we use a `switch` statement and strings, but you can use a helper that
 * follows a different convention (such as function maps) if it makes sense for your
 * project.
 */
function counter(state = 0, action) {
  switch (action.type) {
  case 'INCREMENT':
    return state + 1
  case 'DECREMENT':
    return state - 1
  default:
    return state
  }
}

// Create a Redux store holding the state of your app.
// Its API is { subscribe, dispatch, getState }.
let store = createStore(counter)

// You can use subscribe() to update the UI in response to state changes.
// Normally you'd use a view binding library (e.g. React Redux) rather than subscribe() directly.
// However it can also be handy to persist the current state in the localStorage.

store.subscribe(() =>
  console.log(store.getState())
)

// The only way to mutate the internal state is to dispatch an action.
// The actions can be serialized, logged or stored and later replayed.
store.dispatch({ type: 'INCREMENT' })
// 1
store.dispatch({ type: 'INCREMENT' })
// 2
store.dispatch({ type: 'DECREMENT' })
// 1
Read on →

在现有iOS工程加入React-Native

React-Native在iOS工程的集成

当我们想在现有的iOS开发工程中加入React-Native这个模块的时候,我们需要做一些准备工作。<我假设已经安装了homebrew>安装需要的工具:npm

1
brew install npm
一般来说只要有这个就可以,但是鉴于npm 每次都要npm install React-Native并且时间很慢,我们可以辅助使用Yarn,这个工具也是Facebook出品的,这个打React-Native的效率比npm install 高很多。 安装好了npm之后,我们创建一个package.json文件,内容如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{
  "name": "honer",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "update": "echo '{\"presets\":[\"react-native\"],\"plugins\":[\"transform-decorators-legacy\",[\"react-native-css-class\",{\"pragma\":\"CSS\"}]]}' > .babelrc && mkdir bundle && npm i",
    "start": "node node_modules/react-native/local-cli/cli.js start",
    "build": "rm -rf ./bundle/* && react-native bundle --platform ios --entry-file ./ReactComponent/index.ios.js --bundle-output ./bundle/main.jsbundle --assets-dest ./bundle/  --dev false",
    "test": "jest"
  },
  "dependencies": {
    "react": "15.3.2",
    "react-native": "0.36.1"
  },
  "jest": {
    "preset": "jest-react-native"
  },
  "devDependencies": {
    "babel-jest": "16.0.0",
    "babel-plugin-react-native-css-class": "git+https://github.com/qq4647805/babel-plugin-react-native-css-class.git",
    "babel-plugin-transform-decorators-legacy": "^1.3.4",
    "babel-plugin-transform-runtime": "^6.15.0",
    "babel-preset-react-native": "1.9.0",
    "jest": "16.0.2",
    "jest-react-native": "16.1.0",
    "react-test-renderer": "15.3.2"
  }
}
通过终端进入工程根目录下,如果这时安装了Yarn。在终端输入yarn,回车一按,自动查找需要安装的packages
1
2
3
4
5
6
7
8
9
10
11
RickdeMacBook-Pro:xueba_ios_2016 Wenba$ yarn
yarn install v0.16.1
info No lockfile found.
[1/4] 🔍  Resolving packages...
warning jest > jest-cli > istanbul-api > fileset > minimatch@2.0.10: Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
warning Unmet peer dependency "whatwg-fetch@^1.0.0".
[4/4] 📃  Building fresh packages...
success Saved lockfile.
  Done in 19.62s.
如果没有安装Yarn,安装了npm的话,只要键入 npm install 就会安装packages 然后我们去修改iOS工程的podfile文件,在所在的target多增加这个pod
1
2
3
4
5
6
7
8
pod 'React', :path => './node_modules/react-native', :subspecs => [
  'Core',
  'RCTImage',
  'RCTNetwork',
  'RCTText',
  'RCTWebSocket',
  # Add any other subspecs you want to use in your project
]
在iOS工程目录下执行Pod install。等待安装完成。此时React-Native模块已经加入到我们iOS的工程里了。 Read on →

破壳微信之旅

砸壳前期准备

一个越狱设备,一台Mac设备。 1、openssh
修改ssh -> congifure prot 修改ssh的密码

2、adv-cmds cycript 安装在越狱设备上

3、ssh root@192.168.1.8 (设备的IP)

4、ps -e | grep WeChat

1
2
3
4
5
6
Phone:~ root# 825 ??         0:08.66 /var/mobile/Applications/20EC6C4E-F75C-4FA5-8457-DFF4C2C4E9BC/WeChat.app/WeChat
Phone:~ root# 832 ttys000    0:00.01 grep WeChat
  Phone:~ root# cycript -p 825
  cy# [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask][0]
  cy#"file:///var/mobile/Applications/20EC6C4E-F75C-4FA5-8457-DFF4C2C4E9BC/Documents/"
  DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib /var/mobile/Applications/20EC6C4E-F75C-4FA5-8457-DFF4C2C4E9BC/WeChat.app/WeChat

5、砸开 class-dump –arch armv7 WeChat.decrypted -S -s -H -o /Users/Rick/Documents/ios/isere/WeChatHeader

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
mach-o decryption dumper

DISCLAIMER: This tool is only meant for security research purposes, not for application crackers.

[+] detected 32bit ARM binary in memory.
[+] offset to cryptid found: @0x15a4c(from 0x15000) = a4c
[+] Found encrypted data at address 00004000 of length 45400064 bytes - type 1.
[+] Opening /private/var/mobile/Applications/20EC6C4E-F75C-4FA5-8457-DFF4C2C4E9BC/WeChat.app/WeChat for reading.
[+] Reading header
[+] Detecting header type
[+] Executable is a FAT image - searching for right architecture
[+] Correct arch is at offset 16384 in the file
[+] Opening WeChat.decrypted for writing.
[+] Copying the not encrypted start of the file
[+] Dumping the decrypted data into the file
[+] Copying the not encrypted remainder of the file
[+] Setting the LC_ENCRYPTION_INFO->cryptid to 0 at offset 4a4c
[+] Closing original file
[+] Closing dump file

看到这些log就能看到砸开所有的文件,下面是我砸开的微信定义函数文件

Read on →

面向对象之数据抽象

OO Programming

Java中的编程主要基于构建数据类型。 这种编程风格被称为面向对象编程,因为它围绕着对象的概念,对象是一个保存数据类型值的实体。 对于Java的原始类型,我们主要局限于对数字进行操作的程序,但是对于引用类型,我们可以编写操作字符串,图片,声音或者在Java标准库中或在我们的书站上可用的数百个其他抽象中的任何一个 。 比预定义数据类型的库更重要的是,Java编程中可用的数据类型范围是开放式的,因为您可以定义自己的数据类型。 1. 数据类型。 数据类型是一组值和一组对这些值的操作。 2. 抽象数据类型。 抽象数据类型是其内部表示对客户端隐藏的数据类型。 3. 对象。 对象是可以接受数据类型值的实体。 对象的特征在于三个基本属性:对象的状态是来自其数据类型的值; 对象的身份将一个对象与另一个对象区分开; 对象的行为是数据类型操作的影响。 在Java中,引用是访问对象的机制。 4. 应用程序编程接口(API)。 为了指定抽象数据类型的行为,我们使用一个应用程序编程接口(API),它是构造函数和实例方法(操作)的列表,并对每个函数的效果进行非正式描述,如本计数器的API一样:

5. 客户。 客户端是使用数据类型的程序。 6. 实现。 实现是实现API中指定的数据类型的代码。

使用抽象数据类型。

客户端不需要知道数据类型是如何实现的,以便能够使用它。 1. 创建对象。 每个数据类型值存储在对象中。 要创建(或实例化)单个对象,我们使用关键字new调用构造函数。 每次客户端使用new时,系统为对象分配内存空间,初始化其值,并返回对对象的引用。

2. 调用实例方法。 实例方法的目的是对数据类型值进行操作。 实例方法具有静态方法的所有属性:参数通过值传递,方法名称可以重载,它们可能具有返回值,并且它们可能导致副作用。 他们有一个额外的属性,表征他们:每个调用与一个对象相关联。

3. 使用对象。 声明给了我们可以在代码中使用的对象的变量名。 要使用给定的数据类型,我们: * 声明类型的变量,用于引用对象 * 使用关键字new来调用创建类型对象的构造函数 * 使用对象名称来调用实例方法,作为语句或表达式 例如,Flips.java是一个Counter.java客户端,它接受命令行参数T并模拟T硬币翻转。 4. 分配语句。 具有引用类型的赋值语句创建引用的副本(并且不创建新对象)。 这种情况称为别名:两个变量都指向相同的对象。 别名是Java程序中常见的错误来源,如以下示例所示:

1
2
3
4
5
Counter c1 = new Counter("ones");
c1.increment();
Counter c2 = c1;
c2.increment();
StdOut.println(c1);

代码打印字符串“2 ones”。