@@ -75,6 +75,54 @@ In SwiftUI:
75
75
76
76
Almost the same in semantic!
77
77
78
+ Conditional & List
79
+ ------------------
80
+ Structure of the contents can be dynamic, the most common patterns are conditional
81
+ and list.
82
+
83
+ In React:
84
+
85
+ .. code-block :: javascript
86
+
87
+ const UserList = ({ users }) => {
88
+ if (! users .length ) {
89
+ return < p> No users< / p> ;
90
+ }
91
+
92
+ return (
93
+ < ul>
94
+ {users .map (e => (
95
+ < li key= {e .id }> {e .username }< / li>
96
+ ))}
97
+ < / ul>
98
+ );
99
+ }
100
+
101
+ In SwiftUI:
102
+
103
+ .. code-block :: swift
104
+
105
+ struct UserList : View {
106
+ let users: [User]
107
+
108
+ var body: some View {
109
+ Group {
110
+ if users.isEmpty {
111
+ Text (" No users" )
112
+ } else {
113
+ VStack {
114
+ ForEach (users, id : \.id ) {
115
+ Text (" \( 0ドル .username ) " )
116
+ }
117
+ }
118
+ }
119
+ }
120
+ }
121
+ }
122
+
123
+ SwiftUI has built-in ``ForEach `` element, you don't need to manually map the data
124
+ array to views, so you can have a much neater code.
125
+
78
126
Events Handling
79
127
---------------
80
128
In React:
@@ -580,7 +628,107 @@ struct, pretty like how **Hook** works in React.
580
628
In this way, even though the ``View `` objects are recreated frequently, as long as
581
629
the view is not unmounted, the state will be kept.
582
630
631
+ How function builders works?
632
+ ----------------------------
633
+ As we mention earlier, SwiftUI use **Function Builders ** as DSL to let us build
634
+ contents. There is also a draft proposal about it: `Function builders (draft proposal) `_.
635
+
636
+ Let's first take a look at how JSX is transpiled to JavaScript. We have this:
637
+
638
+ .. code-block :: javascript
639
+
640
+ const UserInfo = ({ users }) => {
641
+ if (! users .length ) {
642
+ return < p> No users< / p> ;
643
+ }
644
+
645
+ return (
646
+ < div>
647
+ < p> Great! < / p>
648
+ < p> We have {users .length } users! < / p>
649
+ < / div>
650
+ );
651
+ }
652
+
653
+ And this is the output from Babel with ``react `` preset:
654
+
655
+ .. code-block :: javascript
656
+
657
+ const UserInfo = ({
658
+ users
659
+ }) => {
660
+ if (! users .length ) {
661
+ return /* #__PURE__*/ React .createElement (" p" , null , " No users" );
662
+ }
663
+
664
+ return /* #__PURE__*/ React .createElement (" div" , null ,
665
+ /* #__PURE__*/ React .createElement (" p" , null , " Great!" ),
666
+ /* #__PURE__*/ React .createElement (" p" , null , " We have " , users .length , " users!" )
667
+ );
668
+ };
669
+
670
+ Most of the structure is identical, and the HTML tags are transformed to ``React.createElement ``
671
+ calls. That makes sense, the function doesn't produce component instances, instead,
672
+ it produces elements. Elements describe how to configure components or DOM elements.
673
+
674
+ Now, let's back to SwiftUI. There is the same example:
675
+
676
+ .. code-block :: swift
677
+
678
+ struct UserInfo : View {
679
+ let users: [User]
680
+
681
+ var body: some View {
682
+ Group {
683
+ if users.isEmpty {
684
+ Text (" No users" )
685
+ } else {
686
+ VStack {
687
+ Text (" Great!" )
688
+ Text (" We have \( users.count ) users!" )
689
+ }
690
+ }
691
+ }
692
+ }
693
+ }
694
+
695
+ And this is the actual code represented by it:
696
+
697
+ .. code-block :: swift
698
+
699
+ struct UserInfo : View {
700
+ let users: [User]
701
+
702
+ var body: some View {
703
+ let v: _ConditionalContent<Text, VStack<TupleView<(Text, Text)>>>
704
+ if users.isEmpty {
705
+ v = ViewBuilder.buildEither (first : Text (" No users" ))
706
+ } else {
707
+ v = ViewBuilder.buildEither (second : VStack {
708
+ return ViewBuilder.buildBlock (
709
+ Text (" Great!" ),
710
+ Text (" We have \( users.count ) users!" )
711
+ )
712
+ })
713
+ }
714
+ return v
715
+ }
716
+ }
717
+
718
+ Voila! All the dynamic structures are replaced by ``ViewBuilder `` method calls. In
719
+ this way, we can use a complex type to represent the structure. Like ``if ``
720
+ statement will be transformed to ``ViewBuilder.buildEither `` call, and its return
721
+ value contains the information of both ``if `` block and ``else `` block.
722
+
723
+ ``ViewBuilder.buildBlock `` is used to represent a child element that contains
724
+ multiple views.
725
+
726
+ With function builders, you can even create your own DSLs. And this year in WWDC20,
727
+ Apple released more features based on function builders, like **WidgetKit ** and
728
+ SwiftUI **App Structure **.
729
+
583
730
.. References:
584
731
585
732
.. _`Thinking in React Hooks` : https://wattenberger.com/blog/react-hooks
586
733
.. _`[SE-0258] Property Wrappers` : https://github.com/apple/swift-evolution/blob/master/proposals/0258-property-wrappers.md
734
+ .. _`Function builders (draft proposal)` : https://github.com/apple/swift-evolution/blob/9992cf3c11c2d5e0ea20bee98657d93902d5b174/proposals/XXXX-function-builders.md
0 commit comments