国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

使用React、Electron、Dva、Webpack、Node.js、Websocket快速構建

Caicloud / 2733人閱讀

摘要:是一個使用和等技術創建原生程序的框架,它負責比較難搞的部分,你只需把精力放在你的應用的核心上即可。談談技術選型使用去做底層的繪制,大項目首選狀態管理的最佳實踐肯定不是,目前首選,或者。

目前Electrongithub上面的star量已經快要跟React-native一樣多了
這里吐槽下,webpack感覺每周都在偷偷更新,很糟心啊,還有Angular更新到了8,Vue馬上又要出正式新版本了,5G今年就要商用,華為的系統也要出來了,RN還沒有更新到正式的1版本,還有號稱讓前端開發者失業的技術flutter也在瘋狂更新,前端真的是學不完的


回到正題,不能否認,現在的大前端,真的太牛了,PC端可以跨三種平臺開發,移動端可以一次編寫,生成各種小程序以及React-native應用,然后跑在ios和安卓以及網頁中      , 這里不得不說-------京東的Taro框架  這些人 已經把Node.jswebpack用上了天

webpack不熟悉的,看我之前的文章 ,今天不把重點放在webpack

歡迎關注我的專欄 《前端進階》 都是百星高贊文章

手寫React優化版腳手架

前端性能優化不完全手冊

手寫vue腳手架

本文源碼git倉庫地址

先說說Electron官網介紹: 使用 JavaScript, HTML 和 CSS 構建跨平臺的桌面應用 ,如果你可以建一個網站,你就可以建一個桌面應用程序。 Electron 是一個使用 JavaScript, HTML 和 CSS 等 Web 技術創建原生程序的框架,它負責比較難搞的部分,你只需把精力放在你的應用的核心上即可。

什么意思呢?

Electron = Node.js + 谷歌瀏覽器 + 平常的JS代碼生成的應用,最終打包成安裝包,就是一個完整的應用

Electron分兩個進程,主進程負責比較難搞的那部分,渲染進程(平常的JS代碼)部分,負責UI界面展示

兩個進程之間可以通過remote模塊,以及IPCRenderIPCMain之間通信,前者類似于掛載在全局的屬性上進行通信(很像最早的命名空間模塊化方案),后者是基于發布訂閱機制,自定義事件的監聽和觸發實現兩個進程的通信。

Electron相當于給React生成的單頁面應用套了一層殼,如果涉及到文件操作這類的復雜功能,那么就要依靠Electron的主進程,因為主進程可以直接調用Node.jsAPI,還可以使用C++插件,這里Node.js的牛逼程度就凸顯出來了,既可以寫后臺的CRUD,又可以做中間件,現在又可以寫前端。

談談技術選型

使用React去做底層的UI繪制,大項目首選React+TS

狀態管理的最佳實踐肯定不是Redux,目前首選dva,或者redux-saga

構建工具選擇webpack,如果不會webpack真的很吃虧,會嚴重限制你的前端發展,所以建議好好學習Node.jswebpack

選擇了普通的Restful架構,而不是GraphQL,可能我對GraphQL理解不深,沒有領悟到精髓

在通信協議這塊,選擇了websoket和普通的http通信方式

因為是demo,很多地方并沒有細化,后期會針對electron出一個網易云音樂的開源項目,這是一定要做到的

先開始正式的環境搭建

config文件放置webpack配置文件

server文件夾放置Node.js的后端服務器代碼

src下放置源碼

main.jsElectron的入口文件

json文件是腳本入口文件,也是包管理的文件~

開發模式項目啟動思路:

先啟動webpack將代碼打包到內存中,實現熱更新

再啟動Electron讀取對應的url地址的文件內容,也實現熱更新

設置webpack入口
        app: ["babel-polyfill", "./src/index.js", "./index.html"],
        vendor: ["react"]
        }
    
忽略Electron中的代碼,不用webpack打包(因為Electron中有后臺模塊代碼,打包就會報錯)
externals: [
        (function () {
            var IGNORES = [
                "electron"
            ];
            return function (context, request, callback) {
                if (IGNORES.indexOf(request) >= 0) {
                    return callback(null, "require("" + request + "")");
                }
                return callback();
            };
        })()
    ]
    
加入代碼分割
optimization: {
        runtimeChunk: true,
        splitChunks: {
            chunks: "all"
        }
    },
設置熱更新等
 
    plugins: [
        new HtmlWebpackPlugin({
            template: "./index.html"
        }),
        new webpack.HotModuleReplacementPlugin(),
        new webpack.NamedModulesPlugin(),
    ],
    mode: "development",
    devServer: {
        contentBase: "../build",
        open: true,
        port: 5000,
        hot: true
    },

#### 加入babel

{
    loader: "babel-loader",
    options: {   //jsx語法
        presets: ["@babel/preset-react",
            //tree shaking 按需加載babel-polifill  presets從后到前執行 
            ["@babel/preset-env", {
                "modules": false,
                "useBuiltIns": "false", "corejs": 2,
            }],
        ],

    plugins: [
        //支持import 懶加載    plugin從前到后
        "@babel/plugin-syntax-dynamic-import",
        //andt-mobile按需加載  true是less,如果不用less style的值可以寫"css" 
        ["import", { libraryName: "antd-mobile", style: true }],
        //識別class組件
        ["@babel/plugin-proposal-class-properties", { "loose": true }],
        //
    ],
    cacheDirectory: true
},
}
看看主進程的配置文件main.js
// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain, Tray, Menu } = require("electron")
const path = require("path")
// Keep a global reference of the window object, if you don"t, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
app.disableHardwareAcceleration()
// ipcMain.on("sync-message", (event, arg) => {
//   console.log("sync - message")
//   // event.returnValue("message", "tanjinjie hello")
// })
function createWindow() {
  // Create the browser window.
  tray = new Tray(path.join(__dirname, "./src/assets/bg.jpg"));
  tray.setToolTip("wechart");
  tray.on("click", () => {
    mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show()
  });
  const contextMenu = Menu.buildFromTemplate([
    { label: "退出", click: () => mainWindow.quit() },
  ]);
  tray.setContextMenu(contextMenu);
  mainWindow = new BrowserWindow({
    width: 805,
    height: 500,
    webPreferences: {
      nodeIntegration: true
    },
    // titleBarStyle: "hidden"
    frame: false
  })

  //自定義放大縮小托盤功能
  ipcMain.on("changeWindow", (event, arg) => {
    if (arg === "min") {
      console.log("min")
      mainWindow.minimize()
    } else if (arg === "max") {
      console.log("max")
      if (mainWindow.isMaximized()) {
        mainWindow.unmaximize()
      } else {
        mainWindow.maximize()
      }
    } else if (arg === "hide") {
      console.log("hide")
      mainWindow.hide()
    }
  })
  // and load the index.html of the app.
  // mainWindow.loadFile("index.html")
  mainWindow.loadURL("http://localhost:5000");
  BrowserWindow.addDevToolsExtension(
    path.join(__dirname, "./src/extensions/react-dev-tool"),
  );


  // Open the DevTools.
  // mainWindow.webContents.openDevTools()

  // Emitted when the window is closed.
  mainWindow.on("closed", function () {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    mainWindow = null
    BrowserWindow.removeDevToolsExtension(
      path.join(__dirname, "./src/extensions/react-dev-tool"),
    );
  })
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on("ready", createWindow)

// Quit when all windows are closed.
app.on("window-all-closed", function () {
  // On macOS it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== "darwin") app.quit()
})

app.on("activate", function () {
  // On macOS it"s common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (mainWindow === null) createWindow()
})


// In this file you can include the rest of your app"s specific main process
// code. You can also put them in separate files and require them here.


今天只講開發模式下的配置,因為實在太多,得分兩篇文章寫了~ 剩下的配置去git倉庫看 在開發模式下啟動項目:

使用 "dev": "webpack-dev-server --config ./config/webpack.dev.js", 將代碼打包到內存中

使用 "start": "electron ." 開啟electron,讀取對應的內存地址中的資源,實現熱更新

項目起來后,在入口處index.js文件中,注入dva
import React from "react"
import App from "./App"
import dva from "dva"
import Homes from "./model/Homes"
import main from "./model/main"
const app = dva()
app.router(({ history, app: store }) => (
  
));
app.model(Homes)
app.model(main)
app.start("#root")
這里不得不說redux,redux-sage,dva的區別 直接看圖 首先是Redux

React 只負責頁面渲染, 而不負責頁面邏輯, 頁面邏輯可以從中多帶帶抽取出來, 變成 store,狀態及頁面邏輯從 里面抽取出來, 成為獨立的 store,

頁面邏輯就是 reducer,都是 Pure Component, 通過 connect 方法可以很方便地給它倆加一層 wrapper 從而建立起與 store 的聯系: 可以通過 dispatchstore 注入 action, 促使 store 的狀態進行變化, 同時又訂閱了 store 的狀態變化, 一旦狀態有變, 被 connect 的組件也隨之刷新,使用 dispatchstore 發送 action 的這個過程是可以被攔截的, 自然而然地就可以在這里增加各種 Middleware, 實現各種自定義功能, eg: logging這樣一來, 各個部分各司其職, 耦合度更低, 復用度更高, 擴展性更好

然后是注入Redux-sage

上面說了, 可以使用 Middleware 攔截 action, 這樣一來異步的網絡操作也就很方便了, 做成一個 Middleware 就行了, 這里使用 redux-saga 這個類庫, 舉個栗子:

點擊創建 Todo 的按鈕, 發起一個 type == addTodo 的 action

saga 攔截這個 action, 發起 http 請求, 如果請求成功, 則繼續向 reducer 發一個 type == addTodoSucc action, 提示創建成功, 反之則發送 type == addTodoFailaction 即可

最后是: Dva

有了前面的三步鋪墊, Dva 的出現也就水到渠成了, 正如 Dva 官網所言, Dva 是基于 React + Redux + Saga 的最佳實踐沉淀, 做了 3 件很重要的事情, 大大提升了編碼體驗:

store saga 統一為一個 model 的概念, 寫在一個 js 文件里面

增加了一個 Subscriptions, 用于收集其他來源的 action, eg: 鍵盤操作

model 寫法很簡約, 類似于 DSL 或者 RoR, coding 快得飛起??

約定優于配置, 總是好的

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/114724.html

相關文章

  • 使用ReactElectronDvaWebpackNode.jsWebsocket快速構建

    摘要:是一個使用和等技術創建原生程序的框架,它負責比較難搞的部分,你只需把精力放在你的應用的核心上即可。談談技術選型使用去做底層的繪制,大項目首選狀態管理的最佳實踐肯定不是,目前首選,或者。 showImg(https://segmentfault.com/img/bVbtqlI?w=1308&h=565); 目前Electron在github上面的star量已經快要跟React-nativ...

    Me_Kun 評論0 收藏0
  • React的移動端和PC端生態圈的使用匯總

    摘要:調用通過注冊表調用到實例,透過的,調用到中的,最后通過,調用,根據參數相應模塊執行。京東的,多端解決方案是一套遵循語法規范的多端開發解決方案。 showImg(https://segmentfault.com/img/bVbuMkw?w=1304&h=808); 對于一項技術,我們不能停留在五分鐘狀態,特別喜歡一句話,用什么方式繪制UI界面一點不重要,重要的是底層的思維,解決問題和優化...

    kun_jian 評論0 收藏0
  • React的移動端和PC端生態圈的使用匯總

    摘要:調用通過注冊表調用到實例,透過的,調用到中的,最后通過,調用,根據參數相應模塊執行。京東的,多端解決方案是一套遵循語法規范的多端開發解決方案。 showImg(https://segmentfault.com/img/bVbuMkw?w=1304&h=808); 對于一項技術,我們不能停留在五分鐘狀態,特別喜歡一句話,用什么方式繪制UI界面一點不重要,重要的是底層的思維,解決問題和優化...

    J4ck_Chan 評論0 收藏0
  • React的移動端和PC端生態圈的使用匯總

    摘要:調用通過注冊表調用到實例,透過的,調用到中的,最后通過,調用,根據參數相應模塊執行。京東的,多端解決方案是一套遵循語法規范的多端開發解決方案。 showImg(https://segmentfault.com/img/bVbuMkw?w=1304&h=808); 對于一項技術,我們不能停留在五分鐘狀態,特別喜歡一句話,用什么方式繪制UI界面一點不重要,重要的是底層的思維,解決問題和優化...

    Travis 評論0 收藏0

發表評論

0條評論

Caicloud

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<