基于redux的弹窗类组件设计与实现(超级干货总结)

弹窗类组件设计与实现

设计思路

弹窗类组件的要求弹窗内容在A处声明,却在B处展示。react中相当于弹窗内容看起来被render到⼀个组件⾥⾯去,实际改变的是⽹⻚上另⼀处的DOM结构,这个显然不符合正常逻辑。但是通过使⽤框架提供的特定API创建组件实例并指定挂载⽬标仍可完成任务。

常⻅⽤法如下:Dialog在当前组件声明,但是却在body中另⼀个div中显示

import React, {Component} from "react";
import Dialog from "../conponents/Dialog";
export default class DialogPage extends Component {
	constructor(props) {
		super(props);
		this.state = {
			showDialog: false
	 	};
}
render() {
	const {showDialog} = this.state;
	return (
		<div>
			<h3>DialogPage</h3> 
			<button  onClick={()=>this.setState({showDialog: !showDialog})}>
 				toggle
			</button>
		 	{showDialog && <Dialog />}
		</div>
 );
 }}
具体实现: Portal

传送⻔,react v16之后出现的portal可以实现内容传送功能。

范例:Dialog组件 (Dialog.js)

import React, { Component } from "react";
import { createPortal } from "react-dom";

export default class Dialog extends Component {
	constructor(props) {
		super(props);
		const doc = window.document;
		this.node = doc.createElement("div");
		doc.body.appendChild(this.node);   
 	}
 	//卸载时,外界的div被清除
	componentWillUnmount() {   
		window.document.body.removeChild(this.node);
	}
	render() {
		const { hideDialog } = this.props;
		return createPortal(
		 <div className="dialog">
 			{this.props.children}
 			{typeof hideDialog === "function" && (
			<button onClick={hideDialog}>关掉弹窗</button>
 		)}
		</div>,
		this.node,
 );
 }}

总结⼀下:Dialog做得事情是通过调⽤createPortal把要画的东⻄画在DOM树上另⼀个⻆落。

Reducer

reducer 就是⼀个纯函数,接收旧的 state 和 action,返回新的 state。

;(previousState, action) => newState

之所以将这样的函数称之为 reducer,是因为这种函数与被传Array.prototype.reduce(reducer, ?initialValue) ⾥的回调函数属于相同的类型。保持 reducer 纯净⾮常重要。永远不要在 reducer ⾥做这些操作:

  • 修改传⼊参数;
  • 执⾏有副作⽤的操作,如 API 请求和路由跳转;
  • 调⽤⾮纯函数,如 Date.now()Math.random()

什么是reduce

const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator
+ currentValue;
// 1 + 2 + 3 + 4
console.log(array1.reduce(reducer));
// expected output: 10
// 5 + 1 + 2 + 3 + 4
console.log(array1.reduce(reducer, 5));
// expected output: 15

Redux 上⼿

Redux是JavaScript应⽤的状态容器。它保证程序⾏为⼀致性且易于测试。

安装redux
yarn add redux

redux较难上⼿,是因为上来就有太多的概念需要学习,⽤⼀个累加器举例:

  1. 需要⼀个store来存储数据
  2. store⾥的reducer初始化state并定义state修改规则
  3. 通过dispatch⼀个action来提交对数据的修改
  4. action提交到reducer函数⾥,根据传⼊的action的type,返回新的state
举个栗子

1、创建store,src/store/index.js

import {createStore} from "redux";
export const counterReducer = (state = 0, {type, payload = 1}) => {
	switch (type) {
		case "ADD":
			return state + payload;
		//如果state是对象
		// return {...state, ...newState};
		case "MINUS":
			return state - payload;
		default:
			return state;
 	}
};
const store = createStore(countReducer);
export default store;

2、创建ReduxPage

import React, {Component} from "react";
import store from "../store/";
export default class ReduxPage extends Component {
	componentDidMount() {
		this.unsubscribe = store.subscribe(() => {
		this.forceUpdate();
 		});
 	}
	componentWillUnmount() {
		this.unsubscribe();
 	}
	add = () => {
		store.dispatch({type: "ADD"});
 	};
	minus = () => {
		store.dispatch({type: "MINUS"});
 	};
	render() {
		console.log("store", store); //sy-log
	return (
		<div> 
		<h3>ReduxPage</h3> 
		<p>{store.getState()}</p> 
		<button onClick={this.add}>add</button> 
		<button onClick{this.minus}>minus</button>
		</div>
 );
 }}

注意:如果点击按钮不能更新,查看是否订阅(subscribe)状态变更。

3、还可以在src/index.js的render⾥订阅状态变更

import store from './store/'
const render = ()=>{
	ReactDom.render( <App/>,
	document.querySelector('#root')
 )
}
render()
store.subscribe(render)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

椰卤工程师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值