Redux 是 JavaScript 状态容器,提供可预测化的状态管理。可以理解为全局数据状态管理工具,用来做组件通信等。
redux 时兄弟组件间传值将很麻烦,代码很复杂冗余。使用 redux 定义全局单一的数据 Store,可以自定义 Store 里面存放哪些数据,整个数据结构也是自己清楚的。
yarn add redux -S
{ type: 'ADD_STUDENT['](),data:{name: 'tom',age:18}}
// 引入 legacy_createStore 用于创建 store
import { legacy_createStore as createStore } from "redux";
// 引入 reducer
import count_reducer from './reducer'
// 创建 store 并暴露
export default createStore(reducer)
combineReducers()component
- Count
- index.jsx
redux
- constant.js
- count_action.js
- count_reducer.js
- store.js
App.jsx
index.js
具体代码实现:
redux/constant.js,
该模块用于定义 action 对象中 type 类型的常量值,方便维护,防止写错单词
// ! 该模块用于定义 action 对象中 type 类型的常量值,方便维护,防止写错单词
// 加法的常量
export const INCREMENT = 'increment'
redux/count_aciton.js,该文件专门为 Count 组件生成 action 对象
// !该文件专门为 Count 组件生成 action 对象
// 引入type 类型的常量
import { INCREMENT } from './constant.js'
// 定义 action
export const incrementAction = data => ({ type: INCREMENT, data})
// 异步 action,就是指 action 的值为函数,异步 action 中一般会调用同步 action,异步 action不是必须要用的
export const incrementAsyncAction = (data, time) => {
// store的dispatch方法会判断 传入值是函数还是对象,如果是函数,那就给这个函数传参数,
// 参数是store的dispatch方法并且执行这个函数
return (dispatch) => {
setTimeout(() => {
dispatch(createIncrementAction(data))
}, time)
}
}
reduce/count_reducer.js,该文件用于创建一个为 Count 组件服务的 reducer
/**
* ! 1. 该文件用于创建一个为 Count 组件服务的 reducer,reducer 的本质就是一个函数
* * 2. reducer 函数会接收到两个参数,分别为:之前的状态(perState),动作对象(action)
* * 3. reducer 其实就是用于初始化数据,操作数据的逻辑的函数
*/
// 引入常量
import { INCREMENT } from './constant.js'
// 初始化状态
const initState = 0;
// 定义 reducer 并暴露出去
export default function countReducer(preState = initState, action) {
// 获取type,data
const { type, data } = action
switch (type) {
case INCREMENT: // 如果是加
return preState + data
default:
return preState;
}
}
reduce/store.js,该文件用于创建 store 对象
注意: redux-thunk 需要安装 yarn add --save redux-thunk
// 引入 redux-thunk,用于支持异步 action
import thunk from 'redux-thunk'
// redux-thunk 是个中间件,必须引入 applyMiddleware
import { legacy_createStore as createStore, applyMiddleware } from "redux";
// 引入 reducer
import count_reducer from './count_reducer'
// 安装中间件 applyMiddleware(thunk)
export default createStore(count_reducer, applyMiddleware(thunk))
component/Count/index.jsx
import React, { Component } from 'react'
import store from '../../redux/store'
// 引入action
import { incrementAction, incrementAsyncAction } from '../../redux/count_action'
/**
* store 的几个 API
* store.getState() 获取状态的数据
* store.dispatch() 通知 reduce 更新状态,参数是个对象
* store.subscribe() 监听状态发生变化则执行的回调
*/
export default class Count extends Component {
// 如何调用 render?
// 第一种方法:在组件挂载完成之后,调用 subscribe() API,调用更新state的方法,this.setState({})
componentDidMount() {
// 检测 redux 中状态的变化,只要一发生变化,就调用 render
store.subscribe(() => {
this.setState({})
})
}
// 加法
increment = () => {
store.dispatch(incrementAction(1))
}
// 异步加
incrementAsync = () => {
const { value } = this.selectNumber
setTimeout(() => {
store.dispatch(incrementAsyncAction(1))
}, 500);
}
render() {
return (
<div>
当前求和为:{store.getState()}
<button onClick={this.increment}>+</button>
<button onClick={this.incrementAsync}>异步加</button>
</div>
)
}
}
App.jsx
import React, { Component } from 'react'
import Count from './components/Count'
export default class App extends Component {
render() {
return (
<div>
<Count/>
</div>
)
}
}
index.js
import { createRoot } from 'react-dom/client'
import App from './App'
import store from './redux/store'
const root = createRoot(document.getElementById('root'))
root.render(<App />)
// 第二种方法:在状态发生变化则执行的回调中,重新渲染App
store.subscribe(() => {
root.render(<App/>)
})
store.dispatch(action(data)) 通知 reduce 更新状态yarn add react-redux
react-Redux 是 Redux的官方 React 绑定库。它能够使你的 React 组件从 Redux store 中读取数据,并且向 store 分发 actions 以更新数据
import { createRoot } from 'react-dom/client'
import App from './App'
// 引入 Provider 组件
import { Provider } from 'react-redux'
// 引入 store
import store from './redux/store'
const root = createRoot(document.getElementById('root'))
root.render(
// * 优化一:在整个应用里面,但凡需要 store 的容器组件,Provider 组件都会传递过去
// * 使用 Provider 包裹 App,目的是让 App所有的后代容器组件都能接收到 store
<Provider store={store}>
<App />
</Provider>
)
// 引入 connect 用于连接 UI 组件与 redux
import { connect } from 'react-redux'
// 使用 connect()() 创建并暴露一个 Count 的容器组件
export default connect(
mapStateToProps,
mapDispatchToProps
)(MyComponent)
// 1. mapStateToProps 函数返回的是一个对象
// 2. 函数返回的对象中的属性值,就作为传递给UI组件props的属性值
// 3. mapStateToProps 用于传递 '状态'
// 默认接收一个 state 参数,值为 count_reducer 里面初始化的值
function mapStateToProps(state) {
// 这里传递了 count,所以UI组件接收的就是:this.props.count
return {count: state}
}
import {
incrementAction,
} from '../../redux/count_action'
// 1. 操作状态的方法
// 2. mapDispatchToProps 函数返回的是一个对象
// 3. 函数返回的对象中的属性值,就作为传递给UI组件props的属性值
// 4. mapStateToProps 用于传递 '操作状态的方法'
// 默认接收 dispatch 方法
function mapDispatchToProps(dispatch) {
// 这里传递了 increment,所以UI组件接收的就是:this.props.increment(data)
return {
// 这里可以接收到的参数,为调用是传递的数据
increment: number => dispatch(incrementAction(number)),
}
}
mapStateToProps, mapDispatchToProps 写在 connect 里面
import React, { Component } from 'react'
// 引入 connect 用于连接 UI 组件与 redux
import { connect } from 'react-redux'
// 引入action
import { increment } from '../../redux/actions/count.js'
// 1. 定义 UI 组件
class Count extends Component {
...
}
// 2. 使用 connect()() 创建并暴露一个 Count 的容器组件
export default connect(
// 映射状态,state 就是 react-redux保存的状态
// state.count: 这个 count 是 store.js 中,汇总 reducer 时定义的 key
state => ({
count: state.count,
}),
// mapDispatchToProps 的简写
{
// 直接映射 action,react-redux 会帮你 dispatch
increment,
decrement,
incrementAsync
}
)(Count)
containers
- Count
- index.jsx
- Person
- index.jsx
redux
-actions
- count.js
- person.js
- reducers
- count.js
- person.js
- index.js
- constant.js
- store.js
App.jsx
index.js
// !该模块用于定义 action 对象中 type 类型的常量值
// count
export const INCREMENT = 'increment'
// person
export const ADD_PERSON = 'add_person'
2.2 actions/count.js
// !该文件专门为 Count 组件生成 action 对象
// 引入常量
import { INCREMENT, DECREMENT} from '../constant'
// 加法action
export const increment = data => ({ type: INCREMENT, data })
actions/person.js
// 引入 type 常量
import { ADD_PERSON } from '../constant'
// 定义 action 并导出
export const addPerson = personObj => ({type: ADD_PERSON , data: personObj})
2.3 reducers/count.js
// 引入常量
import { INCREMENT } from '../constant'
// 初始化状态
const initState = 0;
export default function countReducer(preState = initState, action) {
// 获取type,data
const { type, data } = action
switch (type) {
case INCREMENT: // 如果是加
default:
return preState;
}
}
reducers/person.js
// 引入 type 常量
import { ADD_PERSON } from '../constant'
// 初始化状态
const initState = [{id: '001', name: 'coderbin', age: 18}]
// 定义 reducer,并暴露出去
export default function personReducer(preState = initState, action) {
const { type, data } = action
switch (type) {
// 如果是添加一个人,就执行相关的逻辑操作
case ADD_PERSON:
// ! 不可写下面这一行代码,这样会导致 preState 被改写,personReducer 就不是纯函数了
// preState.unshift(data)
// 注意:只有返回的是一个新数组,react才会进行渲染,更新页面
return [data, ...preState]
default:
return preState
}
}
reducers/index.js 统一在这里导出总 reducer
// !该文件用于汇总所有的 reducer 为一个总的 reducer
// 引入 reducer
import count from './count.js'
import persons from './person.js'
// 引入 combineReducers,进行汇总
import { combineReducers } from "redux";
// * 使用 combineReducers() 汇总所有的 reducer,变成一个总的 reducer
export default combineReducers({
count,
persons
})
2.4 store.js
// ! 该文件用于创建一个 react-redux 仓库
// 引入 redux-thunk,用于支持异步 action
import thunk from 'redux-thunk'
// redux-thunk 是个中间件,必须引入 applyMiddleware
import { legacy_createStore as createStore, applyMiddleware } from "redux";
// 引入 redux-devtools-extension
import { composeWithDevTools } from 'redux-devtools-extension'
// 引入汇总后的 reducer
import allReducer from '../redux/reducers/index.js'
// 创建一个 store 并导出
// composeWithDevTools 用于激活 redux 开发者工具
// 安装中间件 applyMiddleware(thunk)
export default createStore(allReducer, composeWithDevTools(applyMiddleware(thunk)))
注意: redux-devtools-extension 是 redux的开发者工具库,需要安装
yarn add redux-devtools-extension
import React, { Component } from 'react'
// 引入 connect 用于连接 UI 组件与 redux
import { connect } from 'react-redux'
// 引入action
import {
increment,
decrement,
incrementAsync
} from '../../redux/actions/count.js'
// 1. 定义 UI 组件
class Count extends Component {
// 加法
increment = () => {
const { value } = this.selectNumber
// 调用 props 里面的方法,进行加减
this.props.increment(Number(value))
}
render() {
const { count } = this.props
return (
<div>
我是Count组件
<h3>当前求和为:{count}</h3>
<h2>【拿到Person组件数据:总人数为: { this.props.persons.length}】</h2>
<button onClick={this.increment}>+</button>
</div>
)
}
}
// 2. 使用 connect()() 创建并暴露一个 Count 的容器组件
export default connect(
// 映射状态,state 就是 react-redux保存的状态
state => ({
count: state.count,
persons: state.persons
}),
{
// 直接映射 action,react-redux 会帮你 dispatch
increment,
decrement,
incrementAsync
}
)(Count)
Person/index.jsx
import React, { Component } from 'react'
import { nanoid } from 'nanoid'
import { connect } from 'react-redux'
import { addPerson } from '../../redux/actions/person.js'
class Person extends Component {
// 添加
addPerson = () => {
const name = this.nameRef.value.trim()
const age = Number(this.ageRef.value.trim())
if(!name || !age) return alert('请输入!')
const personObj = { id: nanoid(), name, age }
this.props.addPerson(personObj)
this.nameRef.value = ''
this.ageRef.value = ''
}
render() {
return (
<div>
我是Person组件
<h2>【拿到Count组件的数据:求和为: { this.props.count}】</h2>
<input ref={c=>this.nameRef=c} type="text" placeholder='请输入姓名'/>
<input ref={c=>this.ageRef=c} type="text" placeholder='请输入年龄' />
<button onClick={this.addPerson}>添加</button>
<ul>
{
this.props.persons.map(item => {
return <li key={item.id}>{ item.name} -- { item.age }</li>
})
}
</ul>
</div>
)
}
}
export default connect(
// 当前组件需要什么数据(状态),就从这里映射什么数据(状态)
state => ({
persons: state.persons,
count: state.count
}),
{ addPerson }
)(Person)
import React, { Component } from 'react'
// 引入容器组件
import Count from './containers/Count'
import Person from './containers/Person'
export default class App extends Component {
render() {
return (
<div>
<Count/>
<hr />
<Person/>
</div>
)
}
}
import { createRoot } from 'react-dom/client'
import App from './App'
// 引入 Provider 组件
import { Provider } from 'react-redux'
// 引入 store
import store from './redux/store'
const root = createRoot(document.getElementById('root'))
root.render(
<Provider store={store}>
<App />
</Provider>
)
(1).定义好UI组件---不暴露
(2).引入connect生成一个容器组件,并暴露,写法如下:
connect(
state => ({key:value}), //映射状态
{key:xxxxxAction} //映射操作状态的方法
)(UI组件)
(4).在UI组件中通过this.props.xxxxxxx读取和操作状态
Date.now() 或者 Math.random() 等不纯的方法每文一句:虚假的学问比无知更糟糕。无知好比一块空地,可以耕耘和播种;虚假的学问就象一块长满杂草的荒地,几乎无法把草拔尽。本次的分享就到这里,如果本章内容对你有所帮助的话可以点赞+收藏。文章有不对的地方欢迎指出,有任何疑问都可以在评论区留言。希望大家都能够有所收获,大家一起探讨、进步!
导读语言模型给我们的生产生活带来了极大便利,但同时不少人也利用他们从事作弊工作。如何规避这些难辨真伪的文字所产生的负面影响也成为一大难题。在3月9日智源Live第33期活动「DetectGPT:判断文本是否为机器生成的工具」中,主讲人Eric为我们讲解了DetectGPT工作背后的思路——一种基于概率曲率检测的用于检测模型生成文本的工具,它可以帮助我们更好地分辨文章的来源和可信度,对保护信息真实、防止欺诈等方面具有重要意义。本次报告主要围绕其功能,实现和效果等展开。(文末点击“阅读原文”,查看活动回放。)Ericmitchell斯坦福大学计算机系四年级博士生,由ChelseaFinn和Chri
目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称
@作者:SYFStrive @博客首页:HomePage📜:微信小程序📌:个人社区(欢迎大佬们加入)👉:社区链接🔗📌:觉得文章不错可以点点关注👉:专栏连接🔗💃:感谢支持,学累了可以先看小段由小胖给大家带来的街舞👉微信小程序(🔥)目录自定义组件-behaviors 1、什么是behaviors 2、behaviors的工作方式 3、创建behavior 4、导入并使用behavior 5、behavior中所有可用的节点 6、同名字段的覆盖和组合规则总结最后自定义组件-behaviors 1、什么是behaviorsbehaviors是小程序中,用于实现
遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg
ES一、简介1、ElasticStackES技术栈:ElasticSearch:存数据+搜索;QL;Kibana:Web可视化平台,分析。LogStash:日志收集,Log4j:产生日志;log.info(xxx)。。。。使用场景:metrics:指标监控…2、基本概念Index(索引)动词:保存(插入)名词:类似MySQL数据库,给数据Type(类型)已废弃,以前类似MySQL的表现在用索引对数据分类Document(文档)真正要保存的一个JSON数据{name:"tcx"}二、入门实战{"name":"DESKTOP-1TSVGKG","cluster_name":"elasticsear
我有一个将某些事件写入队列的Rails3应用。现在我想在服务器上创建一个服务,每x秒轮询一次队列,并按计划执行其他任务。除了创建ruby脚本并通过cron作业运行它之外,还有其他稳定的替代方案吗? 最佳答案 尽管启动基于Rails的持久任务是一种选择,但您可能希望查看更有序的系统,例如delayed_job或Starling管理您的工作量。我建议不要在cron中运行某些东西,因为启动整个Rails堆栈的开销可能很大。每隔几秒运行一次它是不切实际的,因为Rails上的启动时间通常为5-15秒,具体取决于您的硬件。不过,每天这样做几
我安装了ruby、yeoman,当我运行我的项目时,出现了这个错误:Warning:Running"compass:dist"(compass)taskWarning:YouneedtohaveRubyandCompassinstalledthistasktowork.Moreinfo:https://github.com/gruUse--forcetocontinue.Use--forcetocontinue.我有进入可变session目标的路径,但它不起作用。谁能帮帮我? 最佳答案 我必须运行这个:geminstallcom
文章目录1.任务背景2.任务目标3.相关知识点4.任务实操4.1安装配置JDK4.2启动FISCOBCOS4.3下载解压WeBASE-Front4.4拷贝sdk证书文件4.5启动节点4.6访问节点4.7检查运行状态5.任务总结1.任务背景FISCOBCOS其实是有控制台管理工具,用来对区块链系统进行各种管理操作。但是对于初学者来说,还是可视化界面更友好,本节就来介绍WeBASE管理平台,这是一款微众银行开源的自研区块链中间件平台,可以降低区块链使用的门槛,大幅提高区块链应用的开发效率。微众银行是腾讯牵头设立的民营银行,在国内民营银行里还是比较出名的。微众银行参与FISCOBCOS生态建设,一定
TCL脚本语言简介•TCL(ToolCommandLanguage)是一种解释执行的脚本语言(ScriptingLanguage),它提供了通用的编程能力:支持变量、过程和控制结构;同时TCL还拥有一个功能强大的固有的核心命令集。TCL经常被用于快速原型开发,脚本编程,GUI和测试等方面。•实际上包含了两个部分:一个语言和一个库。首先,Tcl是一种简单的脚本语言,主要使用于发布命令给一些互交程序如文本编辑器、调试器和shell。由于TCL的解释器是用C\C++语言的过程库实现的,因此在某种意义上我们又可以把TCL看作C库,这个库中有丰富的用于扩展TCL命令的C\C++过程和函数,所以,Tcl是
文章目录一、项目场景二、基本模块原理与调试方法分析——信源部分:三、信号处理部分和显示部分:四、基本的通信链路搭建:四、特殊模块:interpretedMATLABfunction:五、总结和坑点提醒一、项目场景 最近一个任务是使用simulink搭建一个MIMO串扰消除的链路,并用实际收到的数据进行测试,在搭建的过程中也遇到了不少的问题(当然这比vivado里面的debug好不知道多少倍)。准备趁着这个机会,先以一个很基本的通信链路对simulink基础和相关的debug方法进行总结。 在本篇中,主要记录simulink的基本原理和基本的SISO通信传输链路(QPSK方式),计划在下篇记