關於當前Web前端技術的一些感悟和筆記

来源:https://www.cnblogs.com/wuhuacong/archive/2019/03/26/10481692.html
-Advertisement-
Play Games

最近這些年,隨著前端應用技術突飛猛進,產生了很多新的前端框架,當然也引入了數不勝數的前端技術概念,前端不在是早期Web Form的拖拉處理方式,也不再是Ajax+HTML那麼簡單,隨著前端技術的發展,前端的JS越來越重要,也越來越複雜,而為了開發的方便,引入了很多可以對JS+CSS進行編譯的框架,而... ...


最近這些年,隨著前端應用技術突飛猛進,產生了很多新的前端框架,當然也引入了數不勝數的前端技術概念,前端不在是早期Web Form的拖拉處理方式,也不再是Ajax+HTML那麼簡單,隨著前端技術的發展,前端的JS越來越重要,也越來越複雜,而為了開發的方便,引入了很多可以對JS+CSS進行編譯的框架,而在發佈的時候按需編譯處理,從而增強了整個前端的開發過程,這些前端的技術包括AngularJS、React、Vue等等,這些前端技術應用框架又囊括了很多相關的技術,包括了MVVM(Model-View-ViewModel)、ES6、Babel、dva、umi、less等技術或概念。前端技術越滾越大,範圍也越來越廣,大有日新月異的感覺。

1、前端技術的自我回顧和展望

記得在上大學時候,開始玩asp的年代,前端和後端糅合一起的困境;也曾記得WebForm開發的樂趣和無奈,快捷但是很醜很笨重;而現在還在繼續做著Ajax + HTML的這種前端的處理,痛並快樂著。技術總是一步步的推進則,但是眼光一旦聚焦在某個技術範疇,日月如梭,抬頭間很快就會發現世界又多了新的前端技術,從開始的猶豫和不確信的停留這段時間後,發現整個前端的世界也已經漸成格局,包括Angular、React、Vue等技術應用已經日趨成熟,而且擁有著龐大的擁躉群體,也有著豐富的資源可供學習和瞭解。

下麵是Angular、React、Vue幾個技術框架的一些介紹。

AngularJS誕生於2009年,由Misko Hevery 等人創建,後為Google所收購。是一款優秀的前端JS框架,已經被用於Google的多款產品當中。AngularJS有著諸多特性,最為核心的是:MVC(Model–view–controller)、模塊化、自動化雙向數據綁定、語義化標簽、依賴註入等等。Angular開發在全球開發人員中廣泛流行,並被谷歌,福布斯,WhatsApp,Instagram,healthcare.gov和許多財富500強公司等大型組織使用。

React 起源於 Facebook 的內部項目,因為該公司對市場上所有 JavaScript MVC 框架,都不滿意,就決定自己寫一套,用來架設 Instagram 的網站。做出來以後,發現這套東西很好用,就在2013年5月開源了。 由於 React 的設計思想極其獨特,屬於革命性創新,性能出眾,代碼邏輯卻非常簡單。所以,越來越多的人開始關註和使用,認為它可能是將來 Web 開發的主流工具。

Vue.js是討論最多且發展最快的JavaScript框架之一。它由前谷歌員工Evan You創建,他在擔任Google員工時曾在Angular工作過。您可以認為它是成功的,因為它能夠使用HTML,CSS和JavaScript構建有吸引力的UI。

這些技術各有優點,很難片面的說明誰優誰劣,它們都各自有自己的生存土壤和大批的擁躉,而我開始選型做前端技術更新的時候,主要看中的是阿裡巴巴的Ant-Design開發框架,這個它是使用了React的技術框架,因此也就自然而然的研究學習起React和Ant-Design來,雖然之前對前端的一些技術有所涉獵,但是真正等你想要進入Ant-Design的開發大門的時候,還是感覺自己像進入了一個前端技術的大觀園,一個個新概念接踵而來,一種種代碼的寫法迎面衝擊,教程看了幾遍還是一頭霧水,真的開始懷疑人生了,不過學習新技術還是需要很多平靜的心態,調整好,一步一個腳印相信還是有所斬獲的,偶爾看到阮一峰的大牛介紹在學習研究React的時候,也曾花了幾個月的時候,雖然他的高度難以看齊,但是學習的韌勁和毅力,是值得我們學習的。學習新的東西,從技術角度,可以滿足好奇心,提高技術水平;從職業角度,有利於求職和晉升,有利於參與潛力大的項目(摘自阮一峰筆記)。

 

2、React的技術學習

接觸一些新的東西,就必然需要投入精力來學習掌握。對於學習Ant-Desin,雖然這個框架本身提供了很多教程介紹,但是我們一些技術點,還是需要更細節的學習,首推還是阮一峰的技術日誌吧。

1、ECMAScript 6 入門

2、React 入門實例教程 

3、Redux 入門教程(一):基本用法

4、Redux 入門教程(二):中間件與非同步操作

5、Redux 入門教程(三):React-Redux 的用法

6、Redux 文檔基礎教程

7、DvaJS快速上手

 

下麵有些內容在學習的時候,掌握的不是很好,摘錄並作為一個回顧吧。 

模塊的 Import 和 Export

import 用於引入模塊,export 用於導出模塊。

// 引入全部
import dva from 'dva';

// 引入部分
import { connect } from 'dva';
import { Link, Route } from 'dva/router';

// 引入全部並作為 github 對象
import * as github from './services/github';

// 導出預設
export default App;
// 部分導出,需 import { App } from './file'; 引入
export class App extend Component {};

析構賦值

析構賦值讓我們從 Object 或 Array 里取部分數據存為變數。

// 對象
const user = { name: 'guanguan', age: 2 };
const { name, age } = user;
console.log(`${name} : ${age}`);  // guanguan : 2

// 數組
const arr = [1, 2];
const [foo, bar] = arr;
console.log(foo);  // 1

我們也可以析構傳入的函數參數。

const add = (state, { payload }) => {
  return state.concat(payload);
};

//析構時還可以配 alias,讓代碼更具有語義
const add = (state, { payload: todo }) => {
  return state.concat(todo);
};

 

對象展開運算符(Object Spread Operator)

//可用於組裝數組。
const todos = ['Learn dva'];
[...todos, 'Learn antd'];  // ['Learn dva', 'Learn antd']

//也可用於獲取數組的部分項。
const arr = ['a', 'b', 'c'];
const [first, ...rest] = arr;
rest;  // ['b', 'c']

// With ignore
const [first, , ...rest] = arr;
rest;  // ['c']

//還可收集函數參數為數組。
function directions(first, ...rest) {
  console.log(rest);
}
directions('a', 'b', 'c');  // ['b', 'c'];


//代替 apply。
function foo(x, y, z) {}
const args = [1,2,3];

// 下麵兩句效果相同
foo.apply(null, args);
foo(...args);


//對於 Object 而言,用於組合成新的 Object 
const foo = {
  a: 1,
  b: 2,
};
const bar = {
  b: 3,
  c: 2,
};
const d = 4;

const ret = { ...foo, ...bar, d };  // { a:1, b:3, c:2, d:4 }

propTypes

 JavaScript 是弱類型語言,所以請儘量聲明 propTypes 對 props 進行校驗,以減少不必要的問題。

function App(props) {
  return <div>{props.name}</div>;
}
App.propTypes = {
  name: React.PropTypes.string.isRequired,
};

內置的 prop type 有:

  • PropTypes.array
  • PropTypes.bool
  • PropTypes.func
  • PropTypes.number
  • PropTypes.object
  • PropTypes.string

 

DVA數據流向

數據的改變發生通常是通過用戶交互行為或者瀏覽器行為(如路由跳轉等)觸發的,當此類行為會改變數據的時候可以通過 dispatch 發起一個 action,如果是同步行為會直接通過 Reducers 改變 State ,如果是非同步行為(副作用)會先觸發 Effects 然後流向 Reducers 最終改變 State。

 

Reducer和effects

 reducer 是一個函數,接受 state 和 action,返回老的或新的 state 。即:(state, action) => state

app.model({
  namespace: 'todos',
  state: [],
  reducers: {
    add(state, { payload: todo }) {
      return state.concat(todo);
    },
    remove(state, { payload: id }) {
      return state.filter(todo => todo.id !== id);
    },
    update(state, { payload: updatedTodo }) {
      return state.map(todo => {
        if (todo.id === updatedTodo.id) {
          return { ...todo, ...updatedTodo };
        } else {
          return todo;
        }
      });
    },
  },
};

建議最多一層嵌套,以保持 state 的扁平化,深層嵌套會讓 reducer 很難寫和難以維護。

app.model({
  namespace: 'app',
  state: {
    todos: [],
    loading: false,
  },
  reducers: {
    add(state, { payload: todo }) {
      const todos = state.todos.concat(todo);
      return { ...state, todos };
    },
  },
});

effects示例

app.model({
  namespace: 'todos',
  effects: {
    *addRemote({ payload: todo }, { put, call }) {
      yield call(addTodo, todo);
      yield put({ type: 'add', payload: todo });
    },
  },
});

put用於觸發 action,call用於調用非同步邏輯,支持 promise。

 

非同步請求

非同步請求基於 whatwg-fetch,API 詳見:https://github.com/github/fetch

GET 和 POST

import request from '../util/request';

// GET
request('/api/todos');

// POST
request('/api/todos', {
  method: 'POST',
  body: JSON.stringify({ a: 1 }),
});

統一錯誤處理

假如約定後臺返回以下格式時,做統一的錯誤處理。

{
  status: 'error',
  message: '',
}

編輯 utils/request.js,加入以下中間件:

function parseErrorMessage({ data }) {
  const { status, message } = data;
  if (status === 'error') {
    throw new Error(message);
  }
  return { data };
}

然後,這類錯誤就會走到 onError hook 里。

 

Subscription

subscriptions 是訂閱,用於訂閱一個數據源,然後根據需要 dispatch 相應的 action。數據源可以是當前的時間、伺服器的 websocket 連接、keyboard 輸入、geolocation 變化、history 路由變化等等。格式為 ({ dispatch, history }) => unsubscribe 。

非同步數據初始化

比如:當用戶進入 /users 頁面時,觸發 action users/fetch 載入用戶數據。

app.model({
  subscriptions: {
    setup({ dispatch, history }) {
      history.listen(({ pathname }) => {
        if (pathname === '/users') {
          dispatch({
            type: 'users/fetch',
          });
        }
      });
    },
  },
});
  react dva 的 connect 與 @connect   connect的作用是將組件和models結合在一起。將models中的state綁定到組件的props中。並提供一些額外的功能,譬如dispatch

connect 的使用

connect 方法返回的也是一個 React 組件,通常稱為容器組件。因為它是原始 UI 組件的容器,即在外麵包了一層 State。

connect 方法傳入的第一個參數是 mapStateToProps 函數,該函數需要返回一個對象,用於建立 State 到 Props 的映射關係。

簡而言之,connect接收一個函數,返回一個函數。

第一個函數會註入全部的models,你需要返回一個新的對象,挑選該組件所需要的models。

export default connect(({ user, login, global = {}, loading }) => ({
    currentUser: user.currentUser,
    collapsed: global.collapsed,
    fetchingNotices: loading.effects['global/fetchNotices'],
    notices: global.notices
}))(BasicLayout);

// 簡化版
export default connect( 
  ({ user, login, global = {}, loading }) => {
        return {
          currentUser: user.currentUser,
          collapsed: global.collapsed,
          fetchingNotices: loading.effects['global/fetchNotices'],
          notices: global.notices
        }
  }
)(BasicLayout);

@connect的使用

其實只是connect的裝飾器、語法糖罷了。

// 將 model 和 component 串聯起來
export default connect(({ user, login, global = {}, loading }) => ({
    currentUser: user.currentUser,
    collapsed: global.collapsed,
    fetchingNotices: loading.effects['global/fetchNotices'],
    notices: global.notices,
    menuData: login.menuData,         
    redirectData: login.redirectData, 
}))(BasicLayout);
// 改為這樣(export 的不再是connect,而是class組件本身。),也是可以執行的,但要註意@connect必須放在export default class前面:
// 將 model 和 component 串聯起來
@connect(({ user, login, global = {}, loading }) => ({
  currentUser: user.currentUser,
  collapsed: global.collapsed,
  fetchingNotices: loading.effects['global/fetchNotices'],
  notices: global.notices,
  menuData: login.menuData,        
  redirectData: login.redirectData, 
}))

export default class BasicLayout extends React.PureComponent { 
   // ...
}
export default connect(從 model 的 state 中獲取數據)(要將數據綁定到哪個組件)   

以上部分內容摘自 https://blog.csdn.net/zhangrui_web/article/details/79651812

 

2、Ant-Design的框架

這款基於React開發的UI框架,界面非常簡潔美觀,是阿裡巴巴旗下螞蟻金融服務集團(旗下擁有支付寶、餘額寶等產品)所設計的一個前端UI組件庫。目前支持了React, 並且有一個對Vue支持的測試版本。

學習和使用Ant-Design,我們可以使用VSCode來對項目代碼進行維護和編輯,這樣可以在Mac和Window環境同樣的開發體驗和操作模式,非常方便。

 

如果需要掌握Ant-Design框架,我們需要瞭解model,namespace,connect,dispatch,action,reducer ,effect這些概念。

DVA 的 model 對象有幾個基本的屬性介紹。

  1. namespace:model 的命名空間,只能用字元串。一個大型應用可能包含多個 model,通過namespace區分。
  1. state:當前 model 狀態的初始值,表示當前狀態。
  1. reducers:用於處理同步操作,可以修改 state,由 action 觸發。reducer 是一個純函數,它接受當前的 state 及一個 action 對象。action 對象裡面可以包含數據體(payload)作為入參,需要返回一個新的 state。
  1. effects:用於處理非同步操作(例如:與服務端交互)和業務邏輯,也是由 action 觸發。但是,它不可以修改 state,要通過觸發 action 調用 reducer 實現對 state 的間接操作。
  1. action:action 就是一個普通 JavaScript 對象,是 reducers 及 effects 的觸發器,形如{ type: 'add', payload: todo },通過 type 屬性可以匹配到具體某個 reducer 或者 effect,payload 屬性則是數據體,用於傳送給 reducer 或 effect。

整體的數據流向見下圖:

 

 

在Reducer裡面,不要修改傳入的 state。 使用 Object.assign() 新建了一個副本。不能這樣使用 Object.assign(state, { visibilityFilter: action.filter }),因為它會改變第一個參數的值。你必須把第一個參數設置為空對象。

function todoApp(state = initialState, action) {
  switch (action.type) {
    case SET_VISIBILITY_FILTER:
      return Object.assign({}, state, {
        visibilityFilter: action.filter
      })
    default:
      return state
  }
}

或者使用使用對象展開運算符(Object Spread Operator)來處理,從而使用 { ...state, ...newState } 達到相同的目的。

  reducers: {
    save(state, action) {
      return {
        ...state,
        ...action.payload,
      };
    },
  },

在 default 情況下返回舊的 state。遇到未知的 action 時,一定要返回舊的 state

每個 reducer 只負責管理全局 state 中它負責的一部分。每個 reducer 的 state 參數都不同,分別對應它管理的那部分 state 數據。

下麵兩種合成 reducer 方法完全等價:

const reducer = combineReducers({
  a: doSomethingWithA,
  b: processB,
  c: c
})
function reducer(state = {}, action) {
  return {
    a: doSomethingWithA(state.a, action),
    b: processB(state.b, action),
    c: c(state.c, action)
  }
}

dva封裝了redux,減少很多重覆代碼比如action reducers 常量等,dva所有的redux操作是放在models目錄下,通過namespace作為key,標識不同的模塊state,可以給state設置初始數據。

reducers跟傳統的react-redux寫法一致,所有的操作放在reducers對象內

Effect 被稱為副作用,在我們的應用中,最常見的就是非同步操作,Effects 的最終流向是通過 Reducers 改變 State

其中上面的effects裡面,call, put其實是saga的寫法,dva集成了saga,可以參考上圖中的saga內容

 

DVA 首先是一個基於 redux 和 redux-saga 的數據流方案,然後為了簡化開發體驗,DVA 還額外內置了 react-router 和 fetch,所以也可以理解為一個輕量級的應用框架。

DVA 是基於現有應用架構 (redux + react-router + redux-saga 等)的一層輕量封裝,沒有引入任何新概念,全部代碼不到 100 行。

在Ant-Design的Pages/.umi目錄裡面,有一個initDva.js文件,就是用來統一批量處理 DVA 的引入的,如下所示。

在有 DVA 之前,我們通常會創建 sagas/products.jsreducers/products.js 和 actions/products.js,然後在這些文件之間來回切換。

有了 DVA 後,它最核心的是提供了 app.model 方法,用於把 reducer, initialState, action, saga 封裝到一起,這樣我們在書寫代碼的時候,把它主要內容,和載入分離出來。如果建立的Model比較多,每次開始的時候需要加入這一句好像也是挺麻煩的,如果可以自動把這個model批量加入,應該會更好吧,不過不知道是基於什麼考量。

 


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

-Advertisement-
Play Games
更多相關文章
  • 前段時間在使用jQuery的animate() 函數時候用到Alternate方式。主要是要讓數字自增到指定大小,且能看見數字增加過程。 一般使用如下方式: 嗯...能運行,不報錯,但是問題來了。多刷新試試,會發現有時動畫過程會在未達到指定數字的時候就停下了。可想而知,不管是數字動畫還是其他動畫都可 ...
  • 2019年3月21日開通博客準備開始前端學習的徵程! ...
  • js導出word文檔所需要的兩個插件: 使用jquery.wordexport.js這個插件導出的word文檔的排版方式; 編輯器打開jquery.wordexport.js,找到 var styles = 在後面添加樣式即可: ...
  • 代碼如下: <div id="menu"> <ul> <li><a href="#">首頁</a></li> <li class="menuDiv"></li> <li><a href="#">博客</a></li> <li class="menuDiv"></li> & ...
  • 初識 javascript 1、JS組成:ECMA BOM DOM (1)是一種基於 對象模型 和 事件 的腳本語言 (2)組成: ECMAScript由ECMA-262定義,提供核心語言功能; 文檔對象模型(DOM),提供訪問和操作網頁內容的方法和介面; 瀏覽器對象模型(BOM),提供與瀏覽器交互 ...
  • //動畫函數---任意一個元素移動到指定的目標位置 //element為元素 target為位置 function carToon(element, target) { //設置一個定時器讓他迴圈去增加 element.timeid = setInterval(function () { //拿到當... ...
  • 事件分發 之前講述了事件如何綁定在 上,那麼具體事件觸發的時候是如何分發到具體的監聽者呢?我們接著上次註冊的事件代理看。當我點擊 按鈕時,觸發註冊的 事件代理。 為`click nativeEvent dispatchEvent(topLevelType, nativeEvent) _interac ...
  • 下麵看下正則表達式實現手機號中間4位數隱藏或者只顯示末尾四位數 ? 1 2 // 匹配手機號首尾,以類似“123****8901”的形式輸出 '12345678901'.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2'); ? 1 2 // 匹配手機號首尾,以類似“ ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...