React Native超簡單完整示例-tabs、頁面導航、熱更新、用戶行為分析

来源:https://www.cnblogs.com/mafengzi/archive/2020/05/08/12853093.html
-Advertisement-
Play Games

初學React Native,如果沒有人指引,會發現好多東西無從下手,但當有人指引後,會發現其實很簡單。這也是本人寫這篇博客的主要原因,希望能幫到初學者。 本文不會介紹如何搭建開發環境,如果你還沒有搭建,可參考這裡的官方文檔:https://react-native.org/doc/getting- ...


初學React Native,如果沒有人指引,會發現好多東西無從下手,但當有人指引後,會發現其實很簡單。這也是本人寫這篇博客的主要原因,希望能幫到初學者。

本文不會介紹如何搭建開發環境,如果你還沒有搭建,可參考這裡的官方文檔:https://react-native.org/doc/getting-started.html 。

本文也不會介紹各種組件,太多了,可參考這裡的官方文檔:https://react-native.org/doc/components-and-apis.html 。

本文將會從創建項目開始,到基本的常見佈局(tabs)多頁面之間的導航,加入熱更新用戶行為分析功能。總之,我希望告訴你在實際工作中一個React Native App是如何開發出來的。

每一個知識點不會展開來詳細講解,這篇博客只是起到一個指引的作用,能讓你少走一點彎路,少一些自己摸索的時間。

第一步:創建項目

當然,前提是你已經搭建好了開發環境。

在命令行中,進入你想要放項目文件的地方,我放在D盤的mydocs文件夾下(D:\mydocs\),執行以下命令:

react-native init 項目名

我的項目名是“test0”,所以完整的命令應該是這樣的:

react-native init test0

由於需要到外網下載文件,而我朝對網路是有管制的,因此這個命令可能需要執行較長時間。只要網路沒有中斷,沒有報錯,就耐心等待吧。

待命令執行完畢後,在 D:\mydocs\ 目錄下就多了一個 test0 文件夾。裡面有很多已經預設創建好的文件和文件夾。

先來對預設創建的項目文件做個簡單的認識。

用你喜歡的任意編輯器(我喜歡用VS Code)找開這個文件夾。你將看到一個類似這樣的目錄結構:

React Native目錄結構

其中,

/package.json 是包管理的配置文件,要安裝什麼包,可在這裡配置,項目的基本信息,比如項目名、版本號、項目說明、等等,也可在此配置。但大多數情況下,可以不用管它。

/index.js 項目的啟動文件。

/App.js 首頁文件,在/index.js中會載入這個文件。

/node_modules 項目中用到的所有包都存放在這個文件夾中。自己的項目文件不要放在這裡。

/android 這裡放的是與Android原生編譯相關的一些文件,作為一名React Native開發者,一般情況下也不用去管它。

/ios 這裡放的是與iOS原生編譯相關的一些文件,作為一名React Native開發者,一般情況下也不用去管它。

這裡需說明一下,如果你的項目的開發中,需要大量去動 /android 和 /ios 下的代碼,甚至在裡面加入很多業務邏輯,那就說明你的項目開發是存在問題的,一般情況下,只有在某些與編譯、配置、發佈相關的才會動到這裡的代碼。

第二步:創建我們的第一個頁面-Hello React Native

其實,現在我們已經可以運行項目了。 react-native init test0 這個命令已經預設為我們創建了一個首頁,但我想替換為我自己的內容。

修改  /App.js ,有以下的代碼替換掉原來的所有代碼:

 1 import React from 'react';
 2 import { SafeAreaView, View, Text } from 'react-native';
 3 
 4 class App extends React.Component {
 5     render() {
 6         return (
 7             <SafeAreaView>
 8                 <View>
 9                     <Text>Hello React Native</Text>
10                 </View>
11             </SafeAreaView>
12         );
13     }
14 };
15 
16 export default App;

預設生成的代碼是hooks語法,但我不喜歡,我更喜歡用class。我覺得class的結構更清晰一些。

第三步:在模擬器中查看運行效果

我們的第一個頁面已經創建好了,現在需要查看一下運行效果。可用真機調試,但大多數情況下,用模擬器會更方便一些。

有各種模擬器可供選擇,我喜歡用Android Studio自帶的模擬器。安裝方法同樣見這個文檔:https://react-native.org/doc/getting-started.html 。

打開Android Studio,點擊 Configure -> AVD Manager

Android Studio啟動界面

 

 

在打開的視窗中,就能看到所有你已經創建過的模擬器了。如果你還沒有創建過模擬器,就點擊 Create Virtual Device 創建一個。下麵是我已經創建好的模擬器。

Android Studio模擬器管理

 

 

點擊後面的綠色三角形,就能啟動模擬器了,啟動後是這個樣子的:

Android Studio模擬器

 

 

再次回到我們的項目。在命令行中,進入項目文件夾( D:\mydocs\test0\ ),執行以下命令:

react-native run-android

因為我用的是Windows系統,就不演示ios的運行效果了。ios的運行,需在Mac電腦上執行以下命令:

react-native run-ios

同樣,可能需要等待比較長的時間,因為同樣需要到外網下載編譯工具。以後再執行此命令時就會快很多了。(這就是很多碼農們恨透了GFW的主要原因之一 ^_^)

以下是目前我們的代碼所運行的效果:

react native hello world

第四步:多個頁面之間的導航

現在我們的示例只有一個頁面,如果有多個頁面,又應該怎樣從一個頁面跳轉到另一個頁面呢?

React Native中,有很多包可以實現此功能。比如:React NavigationReact Native Navigation、等等。

網上有各種文章比較過各種包之間的好壞,但對於一般的應用,其實差別不大。雖然在項目中我一般都使用React Native Navigation,但相對來說,React Navigation使用起來更加簡單、比較容易上手。因此在這個示例中,我選擇使用React Navigation

先創建第二個頁面。

在項目的根目錄下創建一個文件: /one.js 。並加入以下代碼:

 1 import React from 'react';
 2 import { View, Text } from 'react-native';
 3 
 4 class One extends React.Component {
 5     render() {
 6         return (
 8             <View>
 9                 <Text>另一個頁面</Text>
10             </View>
12         );
13     }
14 };
15 
16 export default One;

然後在 /App.js 中加個按鈕,希望點擊它後能跳轉到 /one.js 。將 /App.js 的代碼修改為下麵這樣子:

 1 import React from 'react';
 2 import { SafeAreaView, View, Text, Button } from 'react-native';
 3 
 4 class App extends React.Component {
 5     onPress() {
 6         // TODO: 跳到另一個頁面
 7     }
 8 
 9     render() {
10         return (
11             <SafeAreaView>
12                 <View>
13                     <Text>Hello React Native</Text>
14                 </View>
15                 <View>
16                     <Button title="點擊我去另一個頁面" onPress={this.onPress}></Button>
17                 </View>
18             </SafeAreaView>
19         );
20     }
21 };
22 
23 export default App;

接下來需要在 onPress() 方法中加入跳轉的代碼。在這之前,需要先安裝React Navigation包。

在項目的根目錄下執行以下命令(你可能需要先關閉模擬器中打開的App,或者直接關閉模擬器,並結束項目的運行):

npm install @react-navigation/native
npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view
npm install @react-navigation/stack

然後將 /App.js 中的代碼修改為下麵這樣子:

 1 import React from 'react';
 2 import { View, Text, Button } from 'react-native';
 3 import { NavigationContainer } from '@react-navigation/native';
 4 import { createStackNavigator } from '@react-navigation/stack';
 5 import One from './one';
 6 
 7 const Stack = createStackNavigator();
 8 
 9 class Home extends React.Component {
10     onPress = () => {
11         this.props.navigation.navigate('One');
12     }
13 
14     render() {
15         return (
16             <View>
17                 <View>
18                     <Text>Hello React Native</Text>
19                 </View>
20                 <View>
21                     <Button title="點擊我去另一個頁面" onPress={this.onPress}></Button>
22                 </View>
23             </View>
24         );
25     }
26 };
27 
28 class App extends React.Component {
29     render() {
30         return (
31             <NavigationContainer>
32                 <Stack.Navigator initialRouteName="Home">
33                     <Stack.Screen name="Home" component={Home} />
34                     <Stack.Screen name="One" component={One} />
35                 </Stack.Navigator>
36             </NavigationContainer>
37         );
38     }
39 }
40 
41 export default App;

這次的改動比較大。新加了一個 class Home ,將之前 class App 中的代碼移到了 class Home 中,現在的 class App 是一個維護導航的容器。

留意 class Home 中 onPress() 內的代碼,在這裡,用 navigation.navigate(name) 跳轉到另一個頁面。通過 class App 中的處理, class Home 的 props 中有了一個 navigation 對象。

再次執行 react-native run-android 在模擬器中查看效果:

react native 導航

 

 

點擊頁面中的Button,就能跳轉到 /one.js 了。

在 /one.js 中,可以直接點擊左上角的“返回”圖標回到上一頁。但為了演示如何使用代碼返回到上一頁,我將 /one.js 的代碼修改為下麵這樣子:

 1 import React from 'react';
 2 import { View, Text, Button } from 'react-native';
 3 
 4 class One extends React.Component {
 5     onPress = () => {
 6         this.props.navigation.goBack();
 7     }
 8 
 9     render() {
10         return (
11             <View>
12                 <Text>另一個頁面</Text>
13                 <View>
14                     <Button title="返回" onPress={this.onPress}></Button>
15                 </View>
16             </View>
17         );
18     }
19 };
20 
21 export default One;

在這裡使用了 navigation.goBack() 返回到上一頁。

現在,點擊 /one.js 中的“返回”Button,就能回到上一頁了。

react native 導航,返回上一頁

 navigation 還有個 push() 方法,也是較常用的。你可以試試效果。具體使用方法參考官方文檔:https://react-native.org/doc/navigation.html 。

 

 

第五步:加入選項卡tabs

在App中,比較常見的一種佈局是在底部有一排選項卡tabs。

其實,tabs是由多個頁面組成的,因此,在tabs之間切換,也是在多個頁面之間導航。因此這裡同樣需要用到React Navigation

在項目的根目錄下執行以下命令(同樣,你可能需要先停止項目的運行):

npm install @react-navigation/bottom-tabs

為了更好的演示效果,加入第三個頁面 /two.js ,代碼如下:

 1 import React from 'react';
 2 import { View, Text } from 'react-native';
 3 
 4 class Two extends React.Component {
 5     render() {
 6         return (
 7             <View>
 8                 <Text>第三個頁面</Text>
 9             </View>
10         );
11     }
12 };
13 
14 export default Two;

在 /App.js 中引入它:

1 import Two from './two';

將之前的

1 import { createStackNavigator } from '@react-navigation/stack';

替換為:

1 import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';

並將之前的

1 const Stack = createStackNavigator();

替換為:

1 const Tab = createBottomTabNavigator();

然後將 class App 修改為:

 1 class App extends React.Component {
 2     render() {
 3         return (
 4             <NavigationContainer>
 5                 <Tab.Navigator>
 6                     <Tab.Screen name="Home" component={Home} options={{title: 'Javascript'}} />
 7                     <Tab.Screen name="One" component={One} options={{title: 'Python'}} />
 8                     <Tab.Screen name="Two" component={Two} options={{title: 'PHP'}} />
 9                 </Tab.Navigator>
10             </NavigationContainer>
11         );
12     }
13 }

再次在項目根目錄下執行 react-native run-android 查看運行效果:

react native選項卡tabs

 

 

可以看到在底部出現了一排選項卡tabs。點擊它就能在不同頁面之間切換了。

當然,還可以給tabs加上Icon圖標。這裡就不演示了,懶得去找圖標了。更多內容可參考官方文檔:https://react-native.org/doc/navigation.html 。

第六步:加入熱更新功能

好吧,假設到這裡我們App的功能已經開發完了。

但就可以這樣結束了嗎?

當然不行。

我們老大說過:用React Native做App,卻不做熱更新,那你用React Native幹嘛?

這當然是句玩笑話,但實際情況確實如此,只要是用React Native開發App,一般都會加入熱更新功能,這是用React Native開發App的最大優勢之一。如果將最大的優勢都丟棄了,確實說不過去。

在這裡我使用CodePush中國提供的熱更新服務。使用的方法比較簡單,官方的示例文檔已經寫得很清楚了,我就不加說明瞭,直接上代碼。

官方示例文檔在這裡:http://code-push.cn/docs/1600.htm 。

按照官方文檔安裝好 cpcn-react-native 後,在 /App.js 文件中引入它:

1 import cpcn from "cpcn-react-native";

為了偷懶,我將官網示例中的代碼直接複製到 class Home 中:

 1 class Home extends React.Component {
 2     constructor(props) {
 3         super(props);
 4         this.state = {
 5             upgradeState: 0,
 6             upgradeAllBytes: 0,
 7             upgradeReceived: 0
 8         };
 9     }
10 
11     onPress = () => {
12         this.props.navigation.navigate('One');
13     }
14 
15     componentDidMount() {
16         cpcn.check({
17             // 檢查是否有新版本後調用此方法
18             checkCallback: (remotePackage, agreeContinueFun) => {
19                 if(remotePackage){
20                     // 如果 remotePackage 有值,表示有新版本可更新。
21                     // 將 this.state.upgradeState 的值設為1,以顯示提示消息
22                     this.setState({
23                         upgradeState: 1
24                     });
25                 }
26             },
27             // 下載新版本時調用此方法
28             downloadProgressCallback: (downloadProgress) => {
29                 // 更新顯示的下載進度中的數值
30                 this.setState({
31                     upgradeReceived: downloadProgress.receivedBytes,
32                     upgradeAllBytes: downloadProgress.totalBytes
33                 });
34             },
35             // 安裝新版本後調用此方法
36             installedCallback: (restartFun) => {
37                 // 新版本安裝成功了,將 this.state.upgradeState 的值設為0,以關閉對話框
38                 this.setState({
39                     upgradeState: 0
40                 }, () => {
41                     // 調用此方法重啟App,重啟後將會使用新版本
42                     restartFun(true);
43                 });
44             }
45         });
46     }
47 
48     upgradeContinue = () => {
49         // 用戶確定更新後,調用此方法以開始更新
50         cpcn.agreeContinue(true);
51         // 將 this.state.upgradeState 的值設為2,以顯示下載進度
52         this.setState({
53             upgradeState: 2
54         });
55     }
56 
57     render() {
58         return (
59             <>
60                 <View>
61                     <View>
62                         <Text>Hello React Native</Text>
63                     </View>
64                     <View>
65                         <Button title="點擊我去另一個頁面" onPress={this.onPress}></Button>
66                     </View>
67                 </View>
68                 <Modal
69                     visible={this.state.upgradeState > 0}
70                     transparent={true}>
71                     <View style={{padding:18, backgroundColor:"rgba(10,10,10,0.6)", height:"100%", display:"flex", flexDirection:"row", alignItems:"center"}}>
72                         <View style={{backgroundColor:"#fff", width:"100%", padding:18}}>
73                             {
74                                 this.state.upgradeState == 1
75                                 &&
76                                 <View>
77                                     <View style={{paddingBottom:20}}>
78                                         <Text>發現新版本</Text>
79                                     </View>
80                                     <View>
81                                         <Button title="馬上更新" onPress={this.upgradeContinue}/>
82                                     </View>
83                                 </View>
84                             }
85                             {
86                                 this.state.upgradeState == 2
87                                 &&
88                                 <View>
89                                     <Text style={{textAlign:"center"}}>{this.state.upgradeReceived} / {this.state.upgradeAllBytes}</Text>
90                                 </View>
91                             }
92                         </View>
93                     </View>
94                 </Modal>
95             </>
96         );
97     }
98 };

這就算搞定了。這個App已經有了熱更新功能。

第七步:加入用戶行為分析功能

這還不算完。在真實開發工作中,一個App上線之後,還需要做的事情還很多,比如需要將錯誤日誌傳到伺服器,以方便監控是否存在Bug。再比如,很重要的一點,需要分析用戶的行為,以方便對產品進行改進。這是公司在運營App時的很重要的參考數據。

之前我們都是自己寫用戶行為分析。但是搞得代碼很亂,每次修改和加新的監控都很麻煩,並且我們自己的分析功能寫得也不是很好。

前段時間偶然發現,CodePush中已經有了用戶行為分析的功能,於是便向老大提議用這個,結果還受到了老大的表揚。^_^

官方文檔在這裡:http://code-push.cn/docs/1700.htm 。

接下來我在這個示例項目中加入用戶行為分析。我需要知道我的用戶對哪些內容感興趣,是Javascript,還是Python?又或者是PHP?

只需為每個頁面做個埋點,看用戶訪問哪個比較多就知道結果了。

由於之前在做熱更新時已經引入了 cpcn-react-native ,所以不需重覆引入。但需要註意的是, cpcn-react-nataive 必須在引入所有組件之前引入,例如我現在的引入順序是這樣子的:

1 import React from 'react';
2 import cpcn from "cpcn-react-native";
3 import { View, Text, Button, Modal } from 'react-native';
4 import { NavigationContainer } from '@react-navigation/native';
5 import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
6 import One from './one';
7 import Two from './two';

然後在 import 語句之後加入以下代碼:

1 cpcn.useFootprint();

再然後修改 /App.js 中的 class Home ,在它的 constructor 中加入埋點:

1 class Home extends React.Component {
2     constructor(props) {
3         super(props);
4         this.footprint('Javascript');
5         // 其它代碼。。。。
6     }
7     // 其它代碼。。。。
8 }

給 /one.js  /two.js 也加入埋點:

1 class One extends React.Component {
2     constructor(props) {
3         super(props);
4         this.footprint('Python');
5     }
6     // 其它代碼。。。。
7 }
1 class Two extends React.Component {
2     constructor(props) {
3         super(props);
4         this.footprint('PHP');
5     }
6     // 其它代碼。。。。
7 }

在 /one.js 中有個Button,我也希望能監控用戶有沒有點擊它。因此給該Button也加個埋點:

1 <Button footprint="點了返回按鈕" title="返回" onPress={this.onPress}></Button>

然後就可以去CodePush的控制臺中查看分析報表了。下麵是我的測試結果:

第八步:現在總應該結束了吧?

結束了嗎?

不,還沒有。^_^

比如在上面已經提到過的,在真實的開發工作中,我們還需要記錄用戶的崩潰日誌。再比如,我們需要知道我們的用戶主要分佈在哪些地方。再比如,我們需要將某些數據做緩存。再比如,我們需要在伺服器發生錯誤時給用戶一個友好的提示。等等等等。。。。。

總之,在實際的開發工作中,開發一個App,比在培訓班做個項目要做的事情多得多。

第九步:結束了

雖然如上面所說,還需要做的事情還很多,但在這篇博客里我就不寫了。以後有時間再寫吧。

之前曾對自己說,要多寫點博客,即可記錄一些知識點,也可幫到別人。但卻一直沒有做到。下班之後就真的不想再動了。^_^

這是第一次寫這麼長的博客,希望能幫到看這篇博客的你。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 表結構 student(StuId,StuName,StuAge,StuSex) 學生表 teacher(TId,Tname) 教師表 course(CId,Cname,C_TId) 課程表 sc(SId,S_CId,Score) 成績表 問題六:查詢學過“001”並且也學過編號“002”課程的同學 ...
  • 隨著諸如Apache Flink,Apache Spark,Apache Storm之類的開源框架以及諸如Google Dataflow之類的雲框架的增多,創建實時數據處理作業變得非常容易。這些API定義明確,並且諸如Map Reduce之類的標準概念在所有框架中都遵循幾乎相似的語義。 但是,直到今 ...
  • 最近在Java技術棧公眾號發佈的一篇文章,其中有一道題: Redis是多線程還是單線程?(回答單線程的請回吧,為什麼請回,請往下看) 好些粉絲在後臺問我: 為什麼請回,Redis不是單線程嗎? 大家註意審題: Redis是多線程還是單線程? 這個問題你要從多個方面回答,如果你僅僅只回答 "單線程" ...
  • 【目錄】 一、IDE工具介紹與安裝使用——navicat 神器 二、MySQL數據備份 三、pymysql模塊 1、安裝 2、使用模塊 一、IDE工具介紹與安裝使用——navicat 神器 https://www.cnblogs.com/bigorangecc/p/12851845.html 二、M ...
  • 一、碎片的狀態和 1.運行狀態 當一個碎片是可見的,並且她所關聯的活動正處於運行狀態,該碎片就是運行​狀態。 2.暫停狀態 當一個活動那個進入暫停狀態(由於另一個未占滿屏幕的活動被添加到棧頂),與它相關聯的​可見碎片進入到暫停狀態。 3.停止狀態 當一個活動進入到停止狀態的時候,與它相關聯的碎片就會 ...
  • 一、什麼是事件分發 所謂事件分發,就是將一次完整的點擊所包含的點擊事件傳遞到某個具體的View或ViewGroup,讓該View或該ViewGroup處理它(消費它)。分發是從上往下(父到子)依次傳遞的,其中可能經過的對象有最上層Activity,中間層ViewGroup,最下層View。 二、Ac ...
  • 1、需求 首先、針對UILabel中顯示的多個功能標簽,作出顏色標記提示。 其次、對關鍵字作出點擊響應動作。 如圖所示: 解決: 1、使用正則匹配到關鍵字 public static var hashtag = DetectorType.custom(try! NSRegularExpression ...
  • 演示圖 考慮2個情況 一種情況初始狀態下 滾動到在中間區域的時候,這時上半部分看不見的元素就不給字體添加紅色 一種情況是,從頭向下看的. CSS代碼 ...
一周排行
    -Advertisement-
    Play Games
  • C#TMS系統代碼-基礎頁面BaseCity學習 本人純新手,剛進公司跟領導報道,我說我是java全棧,他問我會不會C#,我說大學學過,他說這個TMS系統就給你來管了。外包已經把代碼給我了,這幾天先把增刪改查的代碼背一下,說不定後面就要趕鴨子上架了 Service頁面 //using => impo ...
  • 委托與事件 委托 委托的定義 委托是C#中的一種類型,用於存儲對方法的引用。它允許將方法作為參數傳遞給其他方法,實現回調、事件處理和動態調用等功能。通俗來講,就是委托包含方法的記憶體地址,方法匹配與委托相同的簽名,因此通過使用正確的參數類型來調用方法。 委托的特性 引用方法:委托允許存儲對方法的引用, ...
  • 前言 這幾天閑來沒事看看ABP vNext的文檔和源碼,關於關於依賴註入(屬性註入)這塊兒產生了興趣。 我們都知道。Volo.ABP 依賴註入容器使用了第三方組件Autofac實現的。有三種註入方式,構造函數註入和方法註入和屬性註入。 ABP的屬性註入原則參考如下: 這時候我就開始疑惑了,因為我知道 ...
  • C#TMS系統代碼-業務頁面ShippingNotice學習 學一個業務頁面,ok,領導開完會就被裁掉了,很突然啊,他收拾東西的時候我還以為他要旅游提前請假了,還在尋思為什麼回家連自己買的幾箱飲料都要叫跑腿帶走,怕被偷嗎?還好我在他開會之前拿了兩瓶芬達 感覺感覺前面的BaseCity差不太多,這邊的 ...
  • 概述:在C#中,通過`Expression`類、`AndAlso`和`OrElse`方法可組合兩個`Expression<Func<T, bool>>`,實現多條件動態查詢。通過創建表達式樹,可輕鬆構建複雜的查詢條件。 在C#中,可以使用AndAlso和OrElse方法組合兩個Expression< ...
  • 閑來無聊在我的Biwen.QuickApi中實現一下極簡的事件匯流排,其實代碼還是蠻簡單的,對於初學者可能有些幫助 就貼出來,有什麼不足的地方也歡迎板磚交流~ 首先定義一個事件約定的空介面 public interface IEvent{} 然後定義事件訂閱者介面 public interface I ...
  • 1. 案例 成某三甲醫預約系統, 該項目在2024年初進行上線測試,在正常運行了兩天後,業務系統報錯:The connection pool has been exhausted, either raise MaxPoolSize (currently 800) or Timeout (curren ...
  • 背景 我們有些工具在 Web 版中已經有了很好的實踐,而在 WPF 中重新開發也是一種費時費力的操作,那麼直接集成則是最省事省力的方法了。 思路解釋 為什麼要使用 WPF?莫問為什麼,老 C# 開發的堅持,另外因為 Windows 上已經裝了 Webview2/edge 整體打包比 electron ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...