React组件的"新vs老"指的是组件的两个不同版本,一个是使用了函数组件(Function Component)或类组件(Class Component)的旧版本,另一个是使用了React Hooks的新版本。

以下是使用React类组件和函数组件的例子:

类组件(旧)




import React from 'react';
 
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }
 
  componentDidMount() {
    document.title = `you clicked ${this.state.count} times`;
  }
 
  componentDidUpdate() {
    document.title = `you clicked ${this.state.count} times`;
  }
 
  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Click me
        </button>
      </div>
    );
  }
}

函数组件(旧)




import React, { useState, useEffect } from 'react';
 
function MyComponent() {
  const [count, setCount] = useState(0);
 
  useEffect(() => {
    document.title = `you clicked ${count} times`;
  });
 
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>
  );
}

而使用Hooks的新版本可能会是这样:




import React, { useState, useEffect } from 'react';
 
function MyComponent() {
  const [count, setCount] = useState(0);
 
  useEffect(() => {
    document.title = `you clicked ${count} times`;
  }, [count]);
 
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>
  );
}

在这里,useStateuseEffect是两个最常用的Hooks,分别用于管理组件的状态和响应式副作用。

从上面的例子可以看出,使用Hooks的新版本代码更加简洁,组件内的逻辑更加集中,没有类组件中的this和生命周期函数的复杂性。这是因为Hooks提供了一种更灵活的方式来复用状态逻辑在不同的组件之间,同时也让组件内部的逻辑更容易理解和维护。




import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { Contacts } from 'expo';
 
export default class ContactsScreen extends React.Component {
  state = {
    contacts: [],
  };
 
  componentDidMount() {
    this.getContactsAsync();
  }
 
  getContactsAsync = async () => {
    const { status } = await Permissions.askAsync(Permissions.CONTACTS);
    if (status === 'granted') {
      const { data } = await Contacts.getContactsAsync({});
      this.setState({ contacts: data });
    }
  };
 
  render() {
    return (
      <View style={styles.container}>
        {this.state.contacts.map((contact) => (
          <View key={contact.id} style={styles.contact}>
            <Text style={styles.name}>{contact.name}</Text>
            <Text style={styles.email}>{contact.email}</Text>
          </View>
        ))}
      </View>
    );
  }
}
 
const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
  },
  contact: {
    marginVertical: 5,
    padding: 10,
    backgroundColor: '#f9f9f9',
    borderBottomWidth: 1,
    borderColor: '#eee',
  },
  name: {
    fontSize: 18,
    fontWeight: 'bold',
  },
  email: {
    fontSize: 16,
  },
});

这段代码使用React Native和Expo来展示用户的联系人列表。它首先请求获取联系人的权限,然后异步获取联系人数据,并将其存储在状态中。最后,在渲染方法中,它遍历这些联系人并为每个联系人显示其名字和邮件地址。这个例子展示了如何在移动应用程序中简单而有效地管理联系人信息。

React 18 引入了一些新的基础API和改进,其中最显著的是新的JSX转换,它使用 react/jsx-runtimereact/jsx-dev-runtime ,这使得JSX转换在开发和生产模式下更加高效。

以下是一个简单的React组件示例,展示了如何在React 18中使用新的JSX转换:




// 引入jsx转换
import { jsx as jsxTransform } from 'react/jsx-runtime';
 
// 自定义组件
function HelloWorld() {
  return <h1>Hello, world!</h1>;
}
 
// 使用jsxTransform标识来编译JSX
const element = jsxTransform(HelloWorld, {});
 
// 渲染到DOM
ReactDOM.createRoot(document.getElementById('root')).render(element);

注意:在实际的React 18项目中,你不需要显式地引入 jsxTransform,因为项目配置(通常是 babel 配置)会自动处理JSX。上面的代码是为了演示如何直接使用JSX转换。




import React from 'react';
import { View, Text } from 'react-native';
import { useInAppPayments } from 'react-native-square-in-app-payments';
 
const PaymentScreen = () => {
  const { loading, error, createPaymentRequest, onPaymentResult } = useInAppPayments();
 
  if (loading) {
    return <Text>正在加载...</Text>;
  }
 
  if (error) {
    return <Text>错误: {error.message}</Text>;
  }
 
  // 创建付款请求
  const paymentRequest = createPaymentRequest({
    currencyCode: 'USD',
    countryCode: 'US',
    total: {
      label: '总金额',
      amount: '100', // 以分为单位
      pending: false
    }
  });
 
  // 处理付款结果
  const handlePaymentResult = (result) => {
    if (result.userCancelled) {
      console.log('用户取消了支付');
    } else {
      console.log('支付成功', result.payment);
    }
  };
 
  // 触发支付
  const requestPayment = () => {
    onPaymentResult(paymentRequest, handlePaymentResult);
  };
 
  return (
    <View>
      <Text onPress={requestPayment}>触发支付</Text>
    </View>
  );
};
 
export default PaymentScreen;

这个代码示例展示了如何在React Native应用中使用Square的In-App Payments插件来请求用户的支付。它首先检查加载状态和错误,然后创建一个付款请求,并处理用户的支付结果。最后,它提供了一个可供用户触发支付流程的按钮。

React Native 新架构是指使用新的工具和库来提升开发体验,如JSI(JavaScript Interface)和Turbo Modules。

JSI 是一个桥接原生模块与 JavaScript 的接口,它允许 JavaScript 直接调用原生模块的方法。

Turbo Modules 是轻量级的模块化插件,它们可以直接导入到 JavaScript 环境中,无需编译原生代码。

以下是如何在 React Native 项目中使用 JSI 的简单示例:

  1. 安装 C++ 依赖,在项目根目录执行:



npm install react-native-reanimated
npx pod-install
  1. 创建一个新的 C++ 文件,例如 NativeModuleExample.cpp,并实现你的原生模块:



#include <jsi/jsi.h>
#include <memory>
 
using namespace facebook;
 
namespace example {
 
// 实现一个简单的原生函数
std::string helloWorld() {
  return "Hello, world!";
}
 
// 创建一个 JSI 对象
std::shared_ptr<jsi::Function> createJSIFunction(jsi::Runtime& runtime) {
  auto helloWorld = [](jsi::Runtime& runtime)
    return jsi::String::createFromUtf8(runtime, example::helloWorld());
  };
 
  return jsi::Function::createFromHostFunction(
      runtime,
      jsi::PropNameID::forAscii(runtime, "helloWorld"),
,
      helloWorld
  );
}
 
} // namespace example
  1. react-native 模块中注册你的 JSI 函数:



#include <ReactCommon/CallInvokerHolder.h>
#include <jsi/jsi.h>
 
namespace example {
 
void installJSI(jsi::Runtime& runtime) {
  std::shared_ptr<jsi::Function> helloWorld = createJSIFunction(runtime);
  runtime.global().setProperty(runtime, "helloWorld", std::move(helloWorld));
}
 
} // namespace example
 
extern "C" __attribute__((used))
void install(jsi::Runtime& runtime) {
  // 注册你的 JSI 函数
  example::installJSI(runtime);
}
  1. 在你的 React Native 应用中使用这个 JSI 函数:



import React, { useEffect } from 'react';
import { NativeModules, Text, View } from 'react-native';
 
export default function App() {
  useEffect(() => {
    const { helloWorld } = NativeModules;
    const result = helloWorld();
    console.log(result); // 输出: Hello, world!
  }, []);
 
  return (
    <View>
      <Text>JSI Example</Text>
    </View>
  );
}

确保你的原生模块已经正确注册,并且在 JavaScript 中可以访问。这个例子展示了如何创建一个原生函数并通过 JSI 在 JavaScript 中使用它。




import { CarPlay } from 'react-native-carplay';
 
// 初始化CarPlay
CarPlay.initialize({
  displayName: 'My CarPlay App',
  supportsAudio: true,
  supportsVideo: true,
});
 
// 监听CarPlay连接状态变化
CarPlay.addEventListener('connection', (event) => {
  if (event.connected) {
    console.log('CarPlay connected');
  } else {
    console.log('CarPlay disconnected');
  }
});
 
// 在CarPlay上播放音频
CarPlay.playAudio('https://example.com/audio.mp3');
 
// 在CarPlay上播放视频
CarPlay.playVideo('https://example.com/video.mp4');
 
// 在CarPlay上显示信息
CarPlay.showAlert({
  title: 'Notification',
  message: 'You have an incoming call.',
  buttonText: 'Answer',
  buttonAction: () => {
    console.log('Answer button tapped');
  },
});
 
// 结束播放
CarPlay.endPlayback();

这个代码示例展示了如何在React Native应用中初始化CarPlay,监听连接状态变化,并在连接成功后播放音频和视频以及显示信息。在实际应用中,你需要确保你的设备支持CarPlay,并且你已经正确地设置了CarPlay的权限和capabilities。

React Native是一个开源的移动应用开发框架,它使用JavaScript语言来编写iOS和Android应用。它的主要特点是:使用React的设计模式,在JavaScript中用于同步状态和属性,以及在DOM中用于描述界面;还可以使用React Native来重用现有的JavaScript代码库。

React Native的环境配置主要包括以下几个步骤:

  1. 安装Node.js:React Native需要Node.js环境,可以通过Node.js的官网下载并安装。
  2. 安装Yarn:Yarn是Facebook开发的一个新的包管理工具,可以用来代替npm,用于安装React Native的依赖包。
  3. 安装React Native CLI:通过npm可以安装React Native的命令行工具,用于初始化新项目。
  4. 创建新的React Native项目:使用React Native CLI工具创建一个新的项目。
  5. 安装Android Studio或Xcode:安装Android Studio来开发Android应用,或者安装Xcode来开发iOS应用。
  6. 配置Android或iOS的开发环境:需要安装Android SDK和Xcode的Command Line Tools,以及配置好模拟器或真机。
  7. 运行项目:使用React Native提供的命令行工具或者在Android Studio/Xcode中运行项目。

以下是一个创建React Native项目的示例代码:




npm install -g yarn react-native-cli
 
yarn config set registry https://registry.npm.taobao.org
 
react-native init AwesomeProject
 
cd AwesomeProject
 
react-native run-android

以上命令会创建一个名为AwesomeProject的React Native项目,并在安卓模拟器上运行这个项目。如果你想在iOS上运行项目,需要确保你有一台Mac电脑,并已经安装了Xcode。然后,你可以使用以下命令:




cd AwesomeProject
 
react-native run-ios

这些步骤是在你有基本的编程经验,并且了解JavaScript和React基础知识的前提下进行的。如果你是React Native的初学者,建议按步骤进行,并参考官方文档和社区资源来解决可能出现的问题。




import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View
} from 'react-native';
 
class HelloWorldApp extends Component {
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.hello}>Hello, World!</Text>
      </View>
    );
  }
}
 
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
  },
  hello: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
});
 
AppRegistry.registerComponent('HelloWorldApp', () => HelloWorldApp);

这段代码展示了如何使用React Native创建一个简单的Hello World应用程序。它定义了一个名为HelloWorldApp的React组件,该组件在一个View容器中渲染了一个Text元素。StyleSheet用于定义文本和容器的样式。最后,我们通过AppRegistry.registerComponent将应用程序注册到全局变量,使其能够在设备或模拟器上运行。这是学习React Native的一个基本例子,展示了如何开始构建原生级别的应用程序。




import { CameraRoll } from 'react-native';
 
// 获取相册的方法
const getPhotosFromCameraRoll = async () => {
  const { edges } = await CameraRoll.getPhotos({
    first: 20,
    assetType: 'photos',
  });
 
  const photos = edges.map(edge => {
    return {
      uri: edge.node.image.uri,
      width: edge.node.image.width,
      height: edge.node.image.height,
    };
  });
 
  return photos;
};
 
// 使用示例
getPhotosFromCameraRoll().then(photos => {
  console.log(photos);
}).catch(error => {
  console.error('An error occurred: ', error);
});

这段代码展示了如何使用React Native的CameraRoll API来获取相册中的照片。它首先从相册中获取20张照片的信息,然后将这些信息映射为一个更简洁的对象,最后返回这个简洁的照片列表。注意,在实际应用中,你可能需要处理权限请求以及错误处理。




import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { SafeAreaView } from 'react-navigation';
import { useSelector } from 'react-redux';
 
// 假设这是一个原生原子组件
const NativeAtomicComponent = React.forwardRef((props, ref) => {
  // 实现细节
});
 
// 桥接原生原子组件
export const BridgedAtomicComponent = React.forwardRef((props, ref) => {
  const theme = useSelector(state => state.theme);
  const styles = createStyles(theme);
 
  return (
    <SafeAreaView style={styles.container}>
      <NativeAtomicComponent ref={ref} {...props} />
    </SafeAreaView>
  );
});
 
const createStyles = theme => StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: theme.colors.background,
  },
});

这个代码示例展示了如何在React Native应用中桥接一个原生的原子组件。首先,我们导入了React Native和React Navigation所必需的组件。然后,我们创建了一个名为NativeAtomicComponent的组件,这是一个假设的原生组件。在BridgedAtomicComponent中,我们使用React.forwardRef来转发ref到子组件,并结合Redux的useSelector来获取当前主题,并应用于样式。最后,我们在SafeAreaView中渲染原生组件,确保内容安全区域正确应用。