react-ssr之事件绑定

26 篇文章 0 订阅
8 篇文章 0 订阅

没有处理事件的页面是不完整…

这里使用一个计数器的demo来展示如何实现事件绑定….

主要需要两个步骤,抽离配置,页面引入我们写好的计数器脚本

抽离webpack配置文件,单独打包server端和client端

  • webpack.base.js 基础配置
module.exports = {
    mode: 'development',
    target: 'web',
    module: {
        rules: [
            {
                test: /\.(js)$/,
                loader: 'babel-loader',
                exclude: /node_modules/,
                options: {
                    presets: [
                        '@babel/preset-env',
                        '@babel/preset-react'
                    ],
                    plugins: [
                        '@babel/plugin-proposal-class-properties'
                    ]
                }
            }
        ]
    }
}
  • webapck.client.js 客户端打包配置
const path = require('path')
const nodeExternal = require('webpack-node-externals')
const merge = require('webpack-merge')
const base = require('./webpack.base')
module.exports = merge(base, {
    // entry: './src/server/index.js', // 提示
    entry: './src/client/index.js',
    output: {
        filename: 'client.js',
        path: path.join(__dirname,'public')
    }
})
  • webpack.server.js 服务端打包配置
const path = require('path')
const nodeExternal = require('webpack-node-externals')
const merge = require('webpack-merge')
const base = require('./webpack.base')

module.exports = merge(base, {
    target: 'node', // 告诉webpack 打包的是node环境的
    // entry: './src/server/index.js', // 提示
    entry: ['babel-polyfill', './src/server/index.js'],
    output: {
        filename: 'server.js',
        path: path.join(__dirname,'build')
    },
    // 负责检测所有引入不得node的核心模块,并且通知webpack不需要将核心代码打入到server.js 文件中去
    externals: [nodeExternal()],
})

页面引入计数器

1.引入上边写好的脚本(打包后,输出到public)

2.配置服务器静态目录(client端打包后文件存放的路径)

文件修改

  • src/containers/Counter/index.js 文件修改如下
import React from 'react'
/**
@desc 这是一个简单的计数器demo
*/
class Counter extends React.Component{
    state = {
        number: 0
    }
    render () {
        return (<div style={{textAlign: 'center'}}>
            <p>{this.state.number}</p>
            <button onClick={() => {
                let {number} = this.state
                number++;
                
                this.setState({number})
            }}>+</button>
        </div>)
    }
}

export default Counter

因为服务端返回的是HTML文本,所以需要在客户端写一个一模一样的代码。用来处理事件绑定

  • src/client/index.js 页面修改如下:

ReactDOM.hydrate:是核心,通过他讲本地js和服务端返回的代码进行合并,而不是替换,从而实现事件绑定

import React from 'react'
import ReactDOM from 'react-dom'
import Counter from '../containers/Counter'
// hydrate 表示把服务端渲染未完成的工作完成,比如绑定事件完成
ReactDOM.hydrate(<Counter />, document.getElementById('root'))
  • src/server/index.js 页面修改
const Koa = require('koa')
const path = require('path')
const _ = require('koa-route');
import React from 'react'
import Counter from '../containers/Counter/index'
import {renderToString} from 'react-dom/server'

let app = new Koa()
app.use(require('koa-static')('public')) // 设置静态目录 方便浏览器访问

app.use(_.get('/', async function (ctx, next) {
    // 转义组件为字符串
    let counter = renderToString(<Counter />)
    ctx.body = `
    <!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>Document</title>
    </head>
    <body>
        <div id="root">${counter}</div>
        <script src="/client.js"></script><!-- 引入脚本 -->
    </body>
    </html>
    `
}))

app.listen(3000)

总结

至此,完成了事件绑定的基本写法,顺便整理一下实现步骤

  • 为了方便处理,我们抽离了webpack的配置
  • 写一个简单的计数器
  • server端引入计数器,然后客户端(因为返回的内容是HTML,dom事件没法绑定…)
  • 修改client脚本,使用ReactDOM.hydrate实现事件绑定
  • 完成代码传送门
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值