分类 Javascript 下的文章

初探redux用法

之前前端的技术栈偏向vue,针对整个生态圈环境,认为确实非常有必要看一下react,
确实react的生态圈是vue没法相比的,并且react native也对我非常有意义.

在阅读react技术文档过程中,redux相对理解的时间花费了长了一点.在这里记录一下,加深印象.

Redux提供一个createStore函数来生成一个Store

createStore接受第一个参数为function(我们叫做reducer),为了便于理解,以后再说后面的参数

reducer函数接受两个参数,
第1个是state,即当前store中存储的数据对象,可以有一个默认值.
第2个是action,是一个object对象,必须要有type属性,其他属性随意.

这个function的功能是根据对应type值,做出不同的处理,生成一个新的state被Store存储.

接下来我们在需要做出动作改变数据的地方,使用store.dispath(action)
这里的action就是之前createStore中的reducer的第2个参数.(当然按照规定也要有一个type属性)

当我们调用store.dispath的时候,Redux会自动去调之前我们传入的function,通过不同的type去做不同的处理,最后Store会根据reducer返回的对象生成一个新的store

最后,还有一个最重要的store.subscribe函数,他用来注册需要监听的函数.当store中的state数据发生了变化时,他会自动调用所有注册过的函数,在注册的函数内部可以通过store.getState()获取数据快照,来对组件进行渲染.

当程序庞大到一定程度时,单个reducer函数会变的非常庞大,Redux提供了combineReducers的方法.通过传入一个对象,对象中包裹多个reducer(多个reducer一般是分多个js去编写),来生成一个整体的reducer函数.使得程序维护变的简单.

React-Redux则变的简单很多.
他主要提供2个功能,

  1. Provider 组件
    Provider组件可以把传入的store对象,传给他下面的所有子组件.并且注册组件的render函数.省去我们手动注册的过程(就是说我们可以忘记subscribe函数)
  2. connect方法
    connect是一个高阶组件,他接收2个参数,第一个为映射的state,可以用他来返回你想要的筛选处理过后的state,一个是映射dispatch 用来映射你容器内需要用到的生成action的方法.
    最终他会返回一个函数,通过这个函数调用传入你的原始容器,将会生成一个新的容器,这个容器的props会注入你所有映射的state和映射的dispatch,来方便你使用.

socket.io框架搭建简介

在线游戏,实时通讯都需要用到websocket技术.
其中搭建websocket最方便的就是nodejs,node的高并发,js的单线程,异步处理的优势无限放大.

socket.io是基于nodeJS的websocket的socket开发框架.相对原生websocket的优势在于他的浏览器兼容性以及封装输出统一性.

源码下载:socket.io搭建源码
在这里吐槽一下杭州的电信,github访问速度超慢,动不动直接封死.连我连接的SSR服务器也经常封住...
(无限流量套餐的可以用4G无线连,一般4G都是不封的)

服务器端socket.io搭建

首先下载socket.io, 客户端代码也可以放同一个服务器端口下,可以下载express搭建一个node静态网页服务器

npm init -y
npm install --save socket.io
npm install --save express

然后新建一个index.js,写入内容

const express = require('express');
const path = require('path');
let app = express();

const http = require('http').Server(app);
let io = require('socket.io')(http);

//搭建静态客户端页面.
app.use(express.static(path.join(__dirname, 'statics')));

//=================socket==========================

io.on('connection', socket => {
    console.log('a user connected:' + socket.id);
});


http.listen(3000, () => {
    console.log('服务已启动,http://localhost:3000');
});

然后在控制台中运行node index.js

当看到控制台中跳出"服务已启动,http://localhost:3000"字样后,就说明服务器已经成功启动了.
服务启动

客户端socket.io搭建

首先建一个文件夹,专门存放静态页面(个人习惯叫做statics,如果文件夹不叫这个名字的话注意要修改服务器的对应路径:app.use(express.static(path.join(__dirname, 'statics')));)

新建一个index.html的首页.

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>socket.io test</title>
</head>

<body>
  <div id='message'>


  </div>
</body>
<!-- 也可以把js下载下来存放在自己的服务器上 -->
<!-- <script src="https://cdn.bootcss.com/socket.io/2.0.4/socket.io.js"></script> -->
<script src="https://cdn.bootcss.com/socket.io/2.0.4/socket.io.slim.js"></script>
<script src="index.js"></script>
</html>

然后再新建一个index.js

var socket = io();  //只要这一句就可以连接了.

//socket连接成功事件
socket.on('connect',function(){
    appendText("连接成功 " + socket.id);
});

//追加文字到html页面上
function appendText(strText){
    var p = document.createElement("p");
    p.innerText = strText;

    document.getElementById("message").appendChild(p);
}

然后用浏览器访问http://localhost:3000/就可以看到链接成功的输出了.

服务器返回文字

web浏览器显示内容

通过webpack搭建socket.io客户端.

用 webpack搭建socket.io客户端框架的话尽量不要和服务器端的放一起,不方便开发以及调试,当然打完包后还是可以放在服务器端目录下面的

附上我的测试代码的package.json

  ...
  "scripts": {
    "build": "webpack --config ./webpack.config.js --env production",
    "start": "webpack-dev-server --config ./webpack.config.dev.js --env development --open"
  },
  "devDependencies": {
    "clean-webpack-plugin": "^0.1.18",
    "html-webpack-plugin": "^2.30.1",
    "uglifyjs-webpack-plugin": "^1.2.2",
    "webpack": "^3.11.0",
    "webpack-dev-server": "^2.11.1"
  },
  "dependencies": {
    "socket.io-client": "^2.0.4"
  }
  ...

首先在根目录新建入口模板页面 index.impl.html

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>socket.io client</title>
</head>

<body>
    <h1>socket client</h1>
    <div id="message"></div>
</body>
<!-- 通过cdn引用socket.io -->
<script src="https://cdn.bootcss.com/socket.io/2.0.4/socket.io.slim.js"></script>
<script type="text/javascript" src="<%=htmlWebpackPlugin.files.chunks.index.entry%>"></script>

</html>

新建一个lib文件夹,专门用来存放需要打包的文件

./lib/config.js (配置文件)

let config = {
    socketUrl: 'http://localhost:3000' ,    //socket.io 服务器路径. 
};

export { config as default };

./lib/index.js

import config from './config';
//import io from 'socket.io-client';    //也可以把socket.io和自己的代码打包在一起.

const socket = io(config.socketUrl);

socket.on('connect',()=>{
    console.log('connect ' + socket.id);

    appendText("连接成功 " + socket.id);
});

//追加文字到html页面上
function appendText(strText){
    var p = document.createElement("p");
    p.innerText = strText;

    document.getElementById("message").appendChild(p);
}

再新建一个webpack.config.dev.js (开发专用的config)

const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');

module.exports = {
    devtool: 'eval-source-map',
    devServer: {
        host: process.env.HOST,
        port: 8080,
        inline: true,
        //historyApiFallback: true,
        // overlay: {
        //     errors: true,
        //     warnings: true
        // }
        //hotOnly:true
    },
    entry: {
        index: './lib/index.js'
    },
    output: {
        path: path.join(__dirname, './dist'),
        filename: '[name]-[hash].js'
    },
    plugins: [
        new HtmlWebpackPlugin({
            filename: 'index.html',
            template: 'index.impl.html',
            inject: false
        }),

    ]
};

发布正式webpack.config.js:

const HtmlWebpackPlugin = require('html-webpack-plugin');       //html模板插件
const CleanWebpackPlugin = require("clean-webpack-plugin");     //清除历史打包文件
const Uglify = require('uglifyjs-webpack-plugin');              //压缩js代码

const path = require('path');

module.exports = {
    entry: {
        index: './lib/index.js'
    },
    output: {
        path: path.join(__dirname, './dist'),
        filename: '[name]-[hash].js'
    },
    plugins: [
        new HtmlWebpackPlugin({
            filename: 'index.html',
            template: 'index.impl.html',
            inject: false
        }),
        new CleanWebpackPlugin('./dist/*.*', {
            root: __dirname,
            verbose: true,
            dry: false
        }),
        new Uglify(),        //压缩js代码
    ]
};
npm install
npm start        //启动调试
npm run build    //打包文件

当浏览器自动打开 http://localhost:8080/ 则说明框架搭建成功
(注意服务端程序不要停止,否则连接不上)

webpack客户端