.NET Core與React組合開發技_第01天_前言_專案建立與大致介紹
2022鐵人賽第一天文章,讀者朋友們好
來稍微探究一下於asp.net core中搭配React前端框架的開發
在這30天成蝶的過程
我想React本身很重ES6和Javascript一些基本語法
算還滿適合拿來當三框架中先拿來進行掌握的一門
(但也是最難掌握也很多人不太推先學的XD)
勉勵自己也將知識專業進行傳播
如文章對於你(可能是個小白)也可能是
只會React但不曉得如何結合.NET Core後端的
又或者只會.NET Core後端但不曉得怎麼和React進行結合的
我希望這系列文章
是個對上述這些開發者戰友們或者以往家教學員
有幫助讀起來不會吃力也很容易吸收的技術篇章
此系列會使用
NodeJs 16以上
和
visual studio 2022
(.Net6長期支援版本)
會在Windows作業系統上做筆記文章
當然若是Mac愛好者的朋友.Net Core (.Net6)也以克服跨作業系統的限制
並不侷限於Windows OS
但Mac環境有關visual studio相關操作可能就都要用cli和vscode來搭配了
因為Mac上的Visual Studio for Mac我較沒接觸
請各位先準備好上述這些IDE和開發環境
有任何誤植或者觀點不認同皆可進行一些開發經驗分享
和批評指教一同成長
開啟vs2022創建第一個React.js配asp.net core的新專案
在此去命名專案名稱默認會配有一個.csproj(C#的專案檔)和.sln(方案)
方案中可包含一或多個專案
預設新專案建立好後就可看到如下專案結構
有默認範本的asp.net core web api(相關先備知識可參閱過去技術部落格貼文)
於此系列可能就會稍微帶過
可以觀察到專案目錄下有一份前端的專案檔
裡面有熟悉的NodeJs package.json
於後端C#專案中的範疇
主程式進入點會在Program.cs當中
~\MyReact1\Program.cs
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 | var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllersWithViews(); var app = builder.Build(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.MapControllerRoute( name: "default", pattern: "{controller}/{action=Index}/{id?}"); app.MapFallbackToFile("index.html"); ; app.Run(); |
到了.net6以後採用Minimal API
也跟過去.net3.1和.net5架構又有所不同了省略Startup.cs
和namespace外層包覆
一個後端Get請求抓取一個string List資料
~\MyReact1\Controllers\WeatherForecastController.cs
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 | using Microsoft.AspNetCore.Mvc; namespace MyReact1.Controllers { [ApiController] [Route("[controller]")] public class WeatherForecastController : ControllerBase { private static readonly string[] Summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }; private readonly ILogger<WeatherForecastController> _logger; public WeatherForecastController(ILogger<WeatherForecastController> logger) { _logger = logger; } [HttpGet] public IEnumerable<WeatherForecast> Get() { return Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateTime.Now.AddDays(index), TemperatureC = Random.Shared.Next(-20, 55), Summary = Summaries[Random.Shared.Next(Summaries.Length)] }) .ToArray(); } } } |
於前端React Js中的範疇
我們前端程式進入點位於Index.js這支程式檔中
~\MyReact1\ClientApp\src\index.js
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 | import 'bootstrap/dist/css/bootstrap.css'; import React from 'react'; import ReactDOM from 'react-dom'; import { BrowserRouter } from 'react-router-dom'; import App from './App'; import * as serviceWorkerRegistration from './serviceWorkerRegistration'; import reportWebVitals from './reportWebVitals'; const baseUrl = document.getElementsByTagName('base')[0].getAttribute('href'); const rootElement = document.getElementById('root'); ReactDOM.render( <BrowserRouter basename={baseUrl}> <App /> </BrowserRouter>, rootElement); // If you want your app to work offline and load faster, you can change // unregister() to register() below. Note this comes with some pitfalls. // Learn more about service workers: https://cra.link/PWA serviceWorkerRegistration.unregister(); // If you want to start measuring performance in your app, pass a function // to log results (for example: reportWebVitals(console.log)) // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals reportWebVitals(); |
而當中間接進行App Component的Render
~\MyReact1\ClientApp\src\App.js
在App.js中又間接去存取專for web api存取的Component 也就是FetchData.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import React, { Component } from 'react'; import { Route } from 'react-router'; import { Layout } from './components/Layout'; import { Home } from './components/Home'; import { FetchData } from './components/FetchData'; import { Counter } from './components/Counter'; import './custom.css' export default class App extends Component { static displayName = App.name; render () { return ( <Layout> <Route exact path='/' component={Home} /> <Route path='/counter' component={Counter} /> <Route path='/fetch-data' component={FetchData} /> </Layout> ); } } |
~\MyReact1\ClientApp\src\components\FetchData.js
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 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | import React, { Component } from 'react'; export class FetchData extends Component { static displayName = FetchData.name; constructor(props) { super(props); this.state = { forecasts: [], loading: true }; } componentDidMount() { this.populateWeatherData(); } static renderForecastsTable(forecasts) { return ( <table className='table table-striped' aria-labelledby="tabelLabel"> <thead> <tr> <th>Date</th> <th>Temp. (C)</th> <th>Temp. (F)</th> <th>Summary</th> </tr> </thead> <tbody> {forecasts.map(forecast => <tr key={forecast.date}> <td>{forecast.date}</td> <td>{forecast.temperatureC}</td> <td>{forecast.temperatureF}</td> <td>{forecast.summary}</td> </tr> )} </tbody> </table> ); } render() { let contents = this.state.loading ? <p><em>Loading...</em></p> : FetchData.renderForecastsTable(this.state.forecasts); return ( <div> <h1 id="tabelLabel" >Weather forecast</h1> <p>This component demonstrates fetching data from the server.</p> {contents} </div> ); } async populateWeatherData() { const response = await fetch('weatherforecast'); const data = await response.json(); this.setState({ forecasts: data, loading: false }); } } |
以上是一個大致前後端如何互動的程式碼導讀
我們可將專案運行起來
默認啟動起來(按綠色撥放按鈕)
預設由於還要做前置build因此等他一段時間會自動跳轉到真正的主頁 URL
這邊是兩個站台應用(因此會有各自不同的port)
後端7248,前端44481
可看到React呼叫web api後呈現到頁面的結果
留言
張貼留言