React實戰一

来源:https://www.cnblogs.com/hu1056043921/archive/2019/03/27/10608850.html
-Advertisement-
Play Games

[toc] 1. 搭建環境 2. React知識點 1. 組件 組件:就是將整個UI拆分為很多小的,可重用的UI,每一個小的UI獨立做自己的事情。 1.1 定義一個組件 一個組件需要繼承 重寫 函數,返回 註意點: 1.只要有JSX的地方必須引入 2.返回值中只能有一個元素包裹, 包裹整個JSX,如 ...


目錄

1. 搭建環境

npm install -g creat-react-app
# 創建一個項目
create-react-app jianshu
cd jianshu
npm run start
# 安裝styled-components 全局統一管理css
npm install --save styled-components
# 全局樣式引入
https://meyerweb.com/eric/tools/css/reset/
background-size: contain;

2. React知識點

1. 組件

組件:就是將整個UI拆分為很多小的,可重用的UI,每一個小的UI獨立做自己的事情。

1.1 定義一個組件

一個組件需要繼承React.Component 重寫render()函數,返回JSX

註意點:

1.只要有JSX的地方必須引入React

2.返回值中只能有一個元素包裹,div包裹整個JSX,如下是錯誤的返回方式

return (
 <div>
   hello world
 </div>
 <div>
   hello world
 </div>
);
import React, { Component } from 'react';
class App extends Component {
  render() {
    return (
      <div>
        hello world
      </div>
    );
  }
}
export default App;

1.2 組合與拆分組件

引用官方的一句話:Don’t be afraid to split components into smaller components.

儘可能的讓每一個組件都能分工明確,減少重覆,加大可重用。例如表格組件,就必須被拆分為一個單獨的組件,它可能在各個地方被用到。

組件拆分優點:讓開發顯得更加清晰明瞭。

未拆分組件看起來就沒有食欲

return (
    <div className="Comment">
      <div className="UserInfo">
        <img className="Avatar"
          src={props.author.avatarUrl}
          alt={props.author.name}
        />
        <div className="UserInfo-name">
          {props.author.name}
        </div>
      </div>
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
 );

1.案例解析

將首頁拆分為Header, Right,如下定義一個首頁組件,在首頁組件中分別引入Header和Right組件,這就是一個簡單的組件拆分和組合.

<React.Fragment />是一個虛擬的組件,僅僅是為了包裹其中的元素,並不會出現在頁面上

Index.js

import React from 'react'
import Header from './Header'
import Right from './Right'
class Index extends React.Component {
  render() {
    return (
      <React.Fragment>
        <Header />
        <Right />
      </React.Fragment>
    );
  }
}
export default Index

Header.js

import React from 'react'
class Header extends React.Component {
  render() {
    return (
      <React.Fragment>
        <div>i am header component</div>
      </React.Fragment>
    );
  }
}
export default Header

Right.js

import React from 'react'
class Right extends React.Component {
  render() {
    return (
      <React.Fragment>
        <div>i am right component</div>
      </React.Fragment>
    );
  }
}
export default Right

1.3 組件傳值

組件傳值分為以下幾種情況:1. 父組件傳值到子組件;2.子組件向父組件傳值;3.隔代組件傳值

1. 父傳子

註意點: props是只讀的

例如Index.jsHeader.js組件傳值

    {/* Index.js 傳遞title屬性 */}
    return (
      <React.Fragment>
        <Header title="Header Title"/>
        <Right />
      </React.Fragment>
    );

    {/*Header.js 接受值*/}
    return (
      <React.Fragment>
        <div>{this.props.title}</div>
      </React.Fragment>
    );

1.4 state

state可以用來存儲數據,記性狀態管理。

it is private and fully controlled by the component.

render函數執行:組件state和props發生改變,render函數會被執行,當父組件重新渲染時候,子組件render函數也會被重新執行

class Index extends React.Component {

  constructor(props) {
    super(props)
    this.state = {
      title: 'Header title'
    }
  }

  render() {
    return (
      <React.Fragment>
        <Header title={this.state.title}/>
        <Right />
      </React.Fragment>
    );
  }
}
export default Index

1.5 PropTypes

https://reactjs.org/docs/typechecking-with-proptypes.html

當組件之間傳值的時候,接收一方往往需要對參數進行校驗,這就是PropTypes的作用

import PropTypes from 'prop-types'

class ReactUI extends React.Component {
  render() {
    return (
        
    )
  }
}
//屬性類型
ReactUI.propTypes = {
  //表示name必須是string類型
  name: PropTypes.string
  //屬性必傳
  id: PropTypes.element.isRequired
}

預設值

The propTypes typechecking happens after defaultProps are resolved

class Greeting extends React.Component {
  static defaultProps = {
    name: 'stranger'
  }

  render() {
    return (
      <div>Hello, {this.props.name}</div>
    )
  }
}

1.5 生命周期函數

在頁面載入的過程中,特定時間點自動執行的函數稱為生命周期函數。

生命周期的四個階段:

  1. Initialization

這一階段主要載入props和state

  1. Mounting:頁面第一次載入的時候才會執行的掛載

componentWillMount:在組件即將被掛載到頁面的時刻執行

render:

componentDisMount:在組件掛載完成之後會被執行

​ 使用場景:用於發送ajax請求

  1. Updation:數據發生變化的時候會被執行
  • props:

componentWillReceiveProps:

​ 子組件從父組件接受屬性,第一次存在父組件,render函數執行,該函數不會被執行,當父組件render函數重新被執行,就會執行這個函數

shouldComponentUpdate:組件是否需要被更新,返回boolean值

​ 使用場景:shouldComponentUpdate(nextProps, nextState);這兩個參數來接受即將改變的props和state的值;演示:

  shouldComponentUpdate(nextProps, nextState) {
    if (nextProps.title !== this.props.title) { //放生改變,則需要重新渲染
      return true
    } else {
      return false
    }
  }

componentWillUpdate: 當組件被更新之前被執行,但是取決於shouldComponentUpdate的返回結果,

render

componentDidUpdate:組件更新完成之後會被執行

  • states:

shouldComponentUpdate

componentWillUpdate

componentDidUpdate:

  1. Unmounting

componentWillUnmount: 組件從頁面移除的時候會被執行

1.6 無狀態組件

無狀態組件: 就是組件中只含有render()函數的組件,

import React from 'react'

class Header extends React.Component {
  render() {
    return (
      <React.Fragment>
        <div>xx {this.props.title}</div>
      </React.Fragment>
    );
  }
}
export default Header

這種組件可以被簡化為無狀態組件

export default (props, context) => {
  return (
    <React.Fragment>
      <div>xx {props.title}</div>
    </React.Fragment>
  );
}

1.7 List and Key

案例:使用List集合渲染一個頁面

key的作用:

Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity

這個主要和虛擬DOM有關,可以提高虛擬DOM性能。

兄弟姐妹之間的key必須獨一無二

import React from 'react'

class Event extends React.Component {

  constructor(props) {
    super(props)
    this.state = {
      data: [1, 2, 3, 4, 5, 6, 7]
    }

    this.handClick = this.handClick.bind(this);
  }
  render() {
    return (
     <div>
       <ul>
         {
           this.state.data.map((item) => (
            <li key={item}>{item}</li>
           ))
         }
       </ul>
     </div>
    )
  }
}
export default Event

2. JSX

JSX 既不是string也不是html,是React獨有的一種語法,jsx中需要註意的點:

  1. 標簽的類class 如:<div class='show'></div> 會和ES6關鍵字衝突會使用className代替
  2. <label></label> for屬性也會使用htmlFor 代替

3. 虛擬DOM

虛擬DOM就是一個JS對象,用來描述真實DOM

jsx轉換成js對象

<div className='show'>hello world</div>
React.createElement('div',{className: 'show'}, 'hello world');

流程講解

  1. state數據
  2. jsx模板
  3. 數據 + 模板生成虛擬DOM
  4. 使用虛擬DOM來來生成真實DOM, 顯示在頁面上
  5. state發生改變
  6. 數據 + 模板生成新的虛擬DOM
  7. 比較原始的虛擬DOM和新的虛擬DOM之間的區別,找到不同之處
  8. 操作DOM,改變不同的地方

diff演算法

上面的第七步驟是如何比對不同之處呢,這裡使用了diff演算法。

同層比對:第一層有差異,則不會再進行比對,直接向下全部渲染,如果第一層相同,則向下繼續比較。

根據Key做關聯來進行比對: 同層的key必須固定不變,這樣才能再進行比對的時候準確的找到原始的dom節點。假如使用index作為key值,當刪除一個元素,那個被刪除元素後面的所有標簽key值都會被改變,那麼進行比對的時候,就會出現性能消耗。

5. 函數綁定

React events are named using camelCase, rather than lowercase.

例如onClick, onBlur...

import React from 'react'
import './event.css'

class Event extends React.Component {

  constructor(props) {
    super(props)
    this.state = {
      isShow: true
    }
  }
  render() {
    return (
     <div>
       <button onClick={this.handClick.bind(this)}>切換</button>
       <div className={this.state.isShow ? 'show':'hidden'}>你好</div>
     </div>
    )
  }

  handClick() {
    this.setState((state) => ({
      isShow: !state.isShow
    }))
  }
}
export default Event

傳遞參數

render() {
    return (
     <div>
       <button onClick={() => this.handClick(this.state.isShow)}>切換</button>
       <div className={this.state.isShow ? 'show':'hidden'}>你好</div>
     </div>
    )
  }

  handClick(isShow) {
    this.setState((state) => ({
      isShow: !isShow
    }))
  }

傳遞參數的幾種方式

<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
<SearchSwitch onClick={() => switchItem(page, totalPage)}>換一批</SearchSwitch>

3. Redux

https://redux.js.org/introduction/getting-started

# 安裝
npm install --save redux

1. 瞭解是三個概念

Actions: 就像一個快遞,裡面包含地址(行為),以及物品(數據)

Reducers:就像一個快遞員,負責分發不同的快遞,根據地址(行為)派送到不同地方

Store: 就像一個總站,可以存儲這些快遞,最後返回給用戶。

與物流之間的區別就是:store不可變,只可以返回數據,而原先的數據一直保留在store裡面

1.1 演示

第一步:創建Store index.js

這裡藉助redux createStore方法創建store,並且引入reducer

import { createStore } from 'redux'
import reducer from './Reducers'

const store = createStore(
  reducer,
  // 這個可以使用Chrome redux 插件進行調試
  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
)
export default store

第二步:創建一個reducer

reducer 裡面保存數據的初始狀態,defaultState

解析action的行為

const defaultState = {
  list: ['hello', 'world']
}

const reducer = (state = defaultState, action) => {
  switch (action.type) {
    case 'add_list_action':
      return {list: action.data}
    default:
      return state
  }
}
export default reducer

第三步:使用redux

  1. this.state = store.getState() 從store中獲取數據
  2. store.subscribe(this.handSubscribe)訂閱數據,監聽數據的變化
  3. handClick()方法中主要定義action,然後利用store進行分發
import React from 'react'
import store from './store'

class ReduxUI extends React.Component {

  constructor(props) {
    super(props)
    this.state = store.getState()
    this.handClick = this.handClick.bind(this)
    this.handSubscribe = this.handSubscribe.bind(this)
    store.subscribe(this.handSubscribe)
  }

  render() {
    return (
      <div>
        <button onClick={this.handClick}>點擊我</button>
        <ul>
          {
            this.state.list.map((item) => {
              return <li key={item}>{item}</li>
            })
          }
        </ul>
      </div>
    )
  }
  handClick() {
    //創建一個Action
    const addListAction = () => ({
      type: 'add_list_action',
      data: ['1', '2', '3']
    })
    //這是一個非同步操作
    store.dispatch(addListAction())
  }

  handSubscribe() {
    this.setState(store.getState())
  }
}
export default ReduxUI

2. react-redux中間件

改造1>1.1 中的代碼

nmp install --save react-redux

新增加一個父組件,統一管理store,

這個組件擁有store,<Provider store={store}>表示改下麵的所有元素都可以使用store中的數據

import React, { Component } from 'react';
import store from './pages/redux/store'
import { Provider } from 'react-redux'
import ReduxUI from './pages/redux/ReduxUI'
class App extends Component {
  render() {
    return (
      <Provider store={store}>
        <ReduxUI/>
      </Provider>
    );
  }
}

export default App;

步驟三中的修改

第一步:添加connect 方法

第三步:映射state中的屬性,定義分發的方法

第四步:連接組件

import React from 'react'
import {connect } from 'react-redux'

class ReduxUI extends React.Component {

  render() {
    //從react-redux中接收store中的信息,以及分發action的方法
    const { list, handClick } = this.props
    return (
      <div>
        <div>
          <button onClick={handClick}>點擊我</button>
          <ul>
            {
              list.map((item) => {
                return <li key={item}>{item}</li>
              })
            }
          </ul>
        </div>
      </div>
    )
  }

}
//state就是store中state
const mapStateToProps = (state) => ({
  list: state.list
})
//這裡定義分發action的方法,dispatch 就是store的dispatch方法
const mapDispatchProps = (dispatch) => ({
  handClick() {
    //創建一個Action
    const addListAction = () => ({
      type: 'add_list_action',
      data: ['1', '2', '3']
    })
    dispatch(addListAction())
  }
})
//連接組件,並且把屬性和action行為傳遞給組件
export default connect(mapStateToProps, mapDispatchProps)(ReduxUI)

4. 其他

1. Redux-thunk

Redux Thunk middleware allows you to write action creators that return a function instead of an action

npm install redux-thunk

to enable Redux Thunk, useapplyMiddleware()

這裡配合redux-devtools-extension調試工具一起使用

import { createStore, compose, applyMiddleware } from 'redux'
import reducer from './reducer'
import thunk  from 'redux-thunk'
// 這個就是讓調試插件配合中間件使用
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose

const store = createStore(
  reducer,
  composeEnhancers(applyMiddleware(thunk))
)
export default store
// 定義一個方法,處理滑鼠聚焦行為
//然後dispatch分發action
handFocus(list) {
    (list.size === 0) && dispatch(actionCreator.getSearchItems())
    dispatch(actionCreator.inputFocusAction())
}

//另外一個文件
//===================================
// 這裡就是上面的action,這個action是一個方法,在該方法裡面發送ajax非同步請求,
//非同步請求之後繼續分發另外一個action
export const getSearchItems = () => {
  return (dispatch) => {
    axios.get("/api/item.json").then((res) => {
      dispatch(searchItemsAction(res.data.data))
    })
  }
}

正如官方文檔所說:redux-thunk允許你分發一個方法類型的action

2. Redux-saga

asynchronous things like data fetching and impure things like accessing the browser cache

npm install --save redux-saga
import { createStore, compose, applyMiddleware } from 'redux'
import reducer from './Reducers'
import createSagaMiddleware from 'redux-saga'
import reduxSaga from './reduxSaga'
const sagaMiddleware = createSagaMiddleware()
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose
const store = createStore(
  reducer,
  composeEnhancers(applyMiddleware(sagaMiddleware))
)
//運行自己的reduxSaga
sagaMiddleware.run(reduxSaga)

export default store

reduxSaga.js

import { takeEvery, put } from 'redux-saga/effects'
import axios from 'axios'

function* getJson() {
  const res = yield axios.get('./data.json')
  yield put({type:"add_list_action", data: res.data}) //繼續派發action
}

function* reduxSaga() {
  // 當store分發'add_list_action' 這個action的時候,會調用getJson方法
  yield takeEvery("add_list__pre_action", getJson)
}
export default reduxSaga

5. immutable

immutable可以保證數據一旦創建,就不會被改變

npm install --save immutable
//目的:將store變成不可變,這是一個簡單reducer.js
import * as constants from './constant' //es6語法
import { fromJS } from 'immutable'
//這裡將defaultStore變成一個immutable對象
const defaultStore = fromJS({
  focused: false,
  mouseIn: false,
  list: [],
  page: 1,
  totalPage: 1
})

export default (state = defaultStore, action) => {
  switch (action.type) {
    case constants.input_focused:
      //這裡的set  immutable對象的一個值,其實並不是改變了state,而是返回一個新的對象
      //通過set可以簡化我們的操作,不用重新構建全部的對象
      return state.set('focused', true)
    default:
      return state
  }
}


// 如何獲取一個immutable對象呢?
const mapStateToProps = (state) => ({
  //這裡表示獲取header組件下的一個immutable對象
   //這裡是 redux-immutable 獲取數據的形式
    // state.header.get('focused') 為immutable獲取數據的格式
  focused: state.getIn(['header', 'focused']), //state.get('header').get('focused')
  mouseIn: state.getIn(['header', 'mouseIn']),
  list: state.getIn(['header', 'list']),
  page: state.getIn(['header', 'page']),
  totalPage: state.getIn(['header', 'totalPage'])
})

//通過action傳遞參數的時候也應該是一個immutable對象
export const searchItemsAction = (data) => ({
  type: constants.render_list,
  data: fromJS(data),
  totalPage: Math.ceil(data.length / 10)
})

5.1 redux-immutable

redux-immutable is used to create an equivalent function of Redux combineReducers that works with Immutable.jsstate.

我們經常面臨很多很多組件,但是如果把所有組件的store,reducer, action 維護在一個目錄下,那將是慘目忍睹的,所以通常情況下我們會分開管理redux,然後將所有的reducer組合在一起

npm install --save redux-immutable
//import { combineReducers } from 'redux'
import { combineReducers } from 'redux-immutable' //可以管理immutale對象
import { reducer as headerReducer} from '../header/store'

const reducer = combineReducers({
  header: headerReducer
})
export default reducer

5. react-router-dom

React Router is a collection of navigational components that compose declaratively with your application.

npm install --save react-router-dom
import { BrowserRouter, Route } from "react-router-dom"
...
<BrowserRouter>
    {/* 表示路由到一個組件 */}
    <Route path="/home" exact component={Home} />
</BrowserRouter>

Route: 表示要路由的到哪一個組件

Link: 表示一個連接,跳轉到某個頁面

6. react-loadable

一個項目,不同的頁面應該按需載入,而不是當首頁出來之後載入所有的組件,例如我們訪問首頁的時候只會載入首頁相關的資源,訪問詳情頁的時候載入詳情頁的代碼,這樣可以提高首頁訪問速度以及用戶體驗

npm install --save react-loadable

案例演示

import React from 'react'
import Loadable from 'react-loadable'
const LoadableComponent = Loadable({
  //這裡`reactUI`是一個組件,表示這個組件將會被按需載入
  loader: () => import('./reactUI'),
  // 這裡是一個函數,可以是一個組件,表示頁面載入前的狀態
  loading: () => <div>正在載入</div>
})
//返回無狀態組件
export default () => {
  return <LoadableComponent/>
}

7. 在React 使用各種CSS

1. styled-components

npm install --save styled-components

定義全局樣式

import { createGlobalStyle } from 'styled-components'
export const ResetCSS = createGlobalStyle`
    body {
    line-height: 1;
  }
    ....
`
// 引用全局樣式
import { ResetCSS } from './style'
...
render() {
  return (
    <ResetCSS />
  )
}

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

-Advertisement-
Play Games
更多相關文章
  • 一、DOM JavaScript語言核心。變數的定義、變數的類型、運算符、表達式、函數、if語句、for迴圈、演算法等等。這些東西都屬於語言核心,下次繼續學習語言核心就是面向對象了。JavaScript能做非常多的事情:DOM開發、Ajax開發、Canvas開發、NodeJS開發、前端框架(React ...
  • Hello, 大噶好, 小葵花媽媽課堂開課啦。。。。。。 我們日常工作中拿到的數據不可能是只有一維的平面數組, 百分之99.99 是數組裡嵌套數組再套數組的n維數組 ............................. 這種讓人想問候它xx的多維數組我們怎麼把它變成一維數組, 也就是只有一個中 ...
  • angular.js AngularJS [1] 誕生於2009年,由Misko Hevery 等人創建,後為Google所收購。是一款優秀的前端JS框架,已經被用於Google的多款產品當中。AngularJS有著諸多特性,最為核心的是:MVC(Model–view–controller)、模塊化 ...
  • 這是一個非常老牌的Bootstrap商業模板,全面性和穩定性俱佳 ...
  • JavaScript中的閉包 JavaScript中的閉包 介紹 在大多數常用語言中,函數返回後,所有局部變數不再可訪問,因為堆棧幀已被銷毀。牢記這一點,閉包可以被看作是當函數返回時不會釋放的棧幀。 為什麼使用閉包 我有很多人問我為什麼要關閉。我會儘力解釋。 我遇到過閉包的場景是使用Tabular ...
  • 什麼是事件冒泡 <div style="width: 200px;height: 200px;background: red;margin: 200px auto;" onclick="box()"> <p onclick="test()" style="background: blue"> wub ...
  • 1.無限滾動的運用場景: 一般運用在列表展示,有分頁、下拉載入更多的需求中。 2.代碼分析 代碼很簡單,實現了列表分頁,數據載入完之後顯示數據狀態 參考mint-ui官網介紹 1.為HTML元素添加v-infinite-scroll指令即可使用無限滾動。 2.滾動該元素,當其底部與被滾動元素底部的距 ...
  • 這裡先放上官網的教程和說明:點擊這裡,vue導航守衛官方文檔 路由守衛 路由守衛說白了就是路由攔截,在地址欄跳轉之前 之後 跳轉的瞬間 乾什麼事 全局守衛 全局守衛顧名思義,就是全局的,整個項目所有路由,跳轉所用到的守衛(攔截),設置了全局守衛之後,只要路由(瀏覽器地址欄)發生變化就會觸發的事件 全 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...