1
头图

作为一名熟悉ReactJS的软件工程师,如果您能够将熟悉的概念映射到新环境中,那么学习Swift和SwiftUI将是一个平稳的过渡。在本指南中,我们将了解常见的ReactJS模式如何转化为Swift和SwiftUI。

请注意,下面的示例旨在使用简短的代码片段来突出一般概念。

我建议您从GitHub下载 Playground,以便尝试和使用这些示例。

初始化一个项目

启动一个新的React项目有很多种方法,其中一种方法是使用create-react-app:

npx create-react-app my-app
cd my-app
npm start

在Swift中,您使用Xcode创建一个新的SwiftUI项目:

  1. 打开 Xcode
  2. 选择“Create a new Xcode project”
  3. 选择iOS(或macOS或多平台)后,选择 “App”,并在 “interface” 选项中选择SwiftUI。

结构化组件

组件是应用程序 UI 的构建模块。

在React中,组件通常是返回一些JSX的函数。

const Greeting = () => <h1>Hello, world!</h1>;

在SwiftUI中,组件被称为Views(视图)。您可以将它们定义为符合 View 协议的 structures(结构)。

struct Greeting: View {
    var body: some View {
        Text("Hello, world!")
    }
}

捕获表单输入

处理用户输入是任何应用程序的常见模式。

ReactJS

在 React 中,您可能会创建一个输入字段,并使用 useState 钩子来跟踪其值。

const InputComponent = () => {
  const [inputValue, setInputValue] = useState("");

  const handleChange = event => setInputValue(event.target.value);

  return <input type="text" value={inputValue} onChange={handleChange} />;
};

SwiftUI

SwiftUI简化了这一过程。通过使用 @State 属性包装器并将其绑定到input,SwiftUI 将为您处理同步。

struct InputView: View {
    @State private var inputValue = ""

    var body: some View {
        TextField("Enter text", text: $inputValue)
            .padding()
    }
}

使用 State 状态

状态对于响应式用户界面是必不可少的。

ReactJS

在React中,我们经常使用 useState 钩子来管理组件级状态。

const Counter = () => {
  const [count, setCount] = useState(0);

  return (
    <button onClick={() => setCount(count + 1)}>
      Clicked {count} times
    </button>
  );
};

SwiftUI

类似地,在SwiftUI中,我们使用 @State 属性包装器来跟踪视图中的本地状态。

struct CounterView: View {
    @State private var count = 0

    var body: some View {
        Button("Clicked \(count) times") {
            count += 1
        }
        .padding()
    }
}

将回调传递给子组件

在父子通信中,将函数作为 props 传递是很常见的。

ReactJS

在React中,你可以通过子组件可以调用的 props 将函数传递给子组件。

const Parent = () => {
  const handleAction = () => console.log("Action handled");

  return <Child onAction={handleAction} />;
};

const Child = ({ onAction }) => <button onClick={onAction}>Do Action</button>;

SwiftUI

在SwiftUI中,通过将闭包传递给子视图也可以实现同样的效果。

struct ParentView: View {
    var body: some View {
        ChildView(onAction: { print("Action handled") })
    }
}

struct ChildView: View {
    let onAction: () -> Void

    var body: some View {
        Button("Do Action", action: onAction)
    }
}

在应用程序中共享数据

ReactJS (使用 Context):

在React中,Context API是共享状态和将状态传递到组件树深处的常用选择,而无需手动传递props。

const AppContext = createContext();

const Parent = () => (
  <AppContext.Provider value={{ message: "Hello from context" }}>
    <Child />
  </AppContext.Provider>
);

const Child = () => {
  const context = useContext(AppContext);

  return <div>{context.message}</div>;
};

SwiftUI (使用 EnvironmentObject):

SwiftUI提供EnvironmentObject,允许视图共享一个共同的数据源。

class AppData: ObservableObject {
    @Published var message = "Hello from environment object"
}

struct ParentView: View {
    var body: some View {
        ChildView().environmentObject(AppData())
    }
}

struct ChildView: View {
    @EnvironmentObject var appData: AppData

    var body: some View {
        Text(appData.message)
    }
}

处理 Effects 副作用

对变化做出反应对于任何现代UI框架来说都是至关重要的。

ReactJS (使用 useEffect):

在React中,useEffect 钩子允许您在函数组件中执行副作用。

const MyComponent = () => {
  useEffect(() => {
    console.log("Component mounted");

    return () => console.log("Component unmounted");
  }, []);

  return <div>Hello, World!</div>;
};

SwiftUI (使用 onAppear 和 onDisappear):

SwiftUI提供了onAppear和onDisappear修饰符,它们可以附加到视图中以实现类似的功能。

struct MyView: View {
    var body: some View {
        Text("Hello, World!")
            .onAppear {
                print("View appeared")
            }
            .onDisappear {
                print("View disappeared")
            }
    }
}

附带说明一下,在视图首次渲染时调用异步函数,使用 .task 修饰符可能比使用 .onAppear 更好。如果视图在任务完成前已被销毁,任务将自动取消。

路由和导航

导航是任何应用程序的基础。

ReactJS (使用 React Router)

在React中,React Router通常用于导航。

import { BrowserRouter as Router, Route, Link } from "react-router-dom";

const Navigation = () => (
  <Router>
    <div>
      <nav>
        <ul>
          <li><Link to="/">Home</Link></li>
        </ul>
      </nav>

      <Route path="/" exact component={Home} />
    </div>
  </Router>
);

SwiftUI (使用 NavigationView 和 NavigationLink)

SwiftUI提供了NavigationView和NavigationLink来创建导航接口。

struct NavigationExampleView: View {
    var body: some View {
        NavigationView {
            NavigationLink(destination: HomeView()) {
                Text("Home")
            }
        }
    }
}

总结

SwiftUI带来了一种声明式的UI构建方式,类似于ReactJS,但与Swift集成得更紧密。

了解ReactJS和SwiftUI之间的这些映射可以使两者之间的过渡更加直观。虽然这涉及到一个学习曲线,但了解模式的异同可以使这一过程更加顺利。

请记住,SwiftUI正在迅速发展,因此请及时了解最新的更改和功能。

当您准备好使用HTTP请求并将应用程序连接到远程API时,请查看 "从JavaScript过渡到Swift和SwiftUI?从这个简单的网络层开始"。


杭州程序员张张
11.8k 声望6.7k 粉丝

Web/Flutter/独立开发者/铲屎官