组件传值
(一)正向传值—使用props
正向传值,父组件向子组件传值,通过props来传递。
但是注意:props的值是不能修改的,如果想修改的话,配合state使用,通过state来修改值。
props正向传值小栗子:
父组件在传值的时候有两种方式:
(1)直接在调用的子组件里面传值—直接传值;
(2)通过ES6扩展运算符给子组件传值—ES6扩展运算符传值。
子组件在接收父组件传过来的数据时也有两种方式:
(1)直接this.props.xxx
;
(2)解构赋值 let {demo1,demo2,demo3}=this.props
下面就能直接使用demo1变量名了 。
>>Father.jsx
import React, { Component } from 'react'
import Son from "./Son.jsx"
export default class home extends Component {
render() {
let obj={demo1:"111",demo2:"222",demo3:"333"}
return (
<div>
<h3>I'm Father.</h3>
-----直接传值-----
<Son demo1="aaa" demo2="bbb" demo3="ccc"/>
-----ES6扩展运算符传值-----
<Son {...obj} />
</div>
)
}
}
>>Son.jsx
import React, { Component } from 'react'
export default class home extends Component {
render() {
let {demo2,demo3}=this.props;
return (
<div>
<h4>I'm Son.</h4>
{/* 第一种:直接this.props.xxx */}
<p>{this.props.demo1}</p>
{/* 第二种:解构赋值 let {demo1,demo2,demo3}=obj 下面就能直接使用了 */}
<p>{demo2}</p>
<p>{demo3}</p>
</div>
)
}
}
(二)逆向传值—函数传值
通过事件调用函数传递。
在子组件中使用this.props.调用的函数名,绑定发送数据:
在父组件中进行函数传递:
事件函数逆向传值小栗子:
>>Father.jsx
import React, { Component } from 'react'
import Son from "./Son.jsx"
export default class home extends Component {
fuFun=(text)=>{
console.log(text)
}
render() {
let obj={demo1:"111",demo2:"222",demo3:"333"}
return (
<div>
<h3>I'm Father.</h3>
子组件逆向传值 在父组件中传递过去一个函数 sonFun
<Son sonFun={this.fuFun}/>
</div>
)
}
}
>>Son.jsx
import React, { Component } from 'react'
export default class home extends Component {
render() {
let {demo2,demo3}=this.props;
return (
<div>
<h4>I'm Son.</h4>
子组件中正向接收一个函数 sonFun ,使用this.props.函数名.bind(this,"数据") ,绑定发送数据
<button onClick={this.props.sonFun.bind(this,"子传给父的数据")}>点击-逆向传值</button>
</div>
)
}
}
(三)同级传值—pubsub-js
同级传值使用 pubsub-js。
下载:npm install --save pubsub-js
在第一个组件中进行数据抛出 PubSub.publish("事件名","数据")
在第二个组件中接收PubSub.subscribe("监听的事件",(事件,数据)=>{})
pubsub-js兄弟传值小栗子:
一个兄弟组件里面抛出一个事件 eventName :
>>Bro1.jsx
import React, { Component } from 'react'
import Pubsub from "pubsub-js"
export default class Bro1 extends Component {
fun=()=>{
// 事件名 数据
Pubsub.publish("eventName","Bro1发出的数据")
}
render() {
return (
<div>
<h4>I'm big bro1.</h4>
{/* 通过一个事件触发 */}
<button onClick={this.fun}>点击-向兄弟传递数据</button>
</div>
)
}
}
第二兄弟组件里面监听这个事件,然后我是通过state将数据动态更新到页面上:
>>Bro2.jsx
import React, { Component } from 'react'
import Pubsub from "pubsub-js"
export default class Bro1 extends Component {
constructor(props) {
super(props)
this.state = {
texta: "empty",
textb: "empty"
}
}
// 在钩子里面接收兄弟传过来的数据 比如在组件创建完成后
componentDidMount() {
Pubsub.subscribe("eventName", (a, b) => {
console.log("a:",a)
console.log("b:",b)
this.setState({
texta: a,
textb: b
})
})
}
render() {
return (
<div>
<h4>I'm little bro2.</h4>
<p>事件名:{this.state.texta}   数据:{this.state.textb}</p>
</div>
)
}
}
然后将这两个兄弟组件引入到父组件里面,再把父组件引入到根组件里面,就能查看效果啦。
>>Father.jsx
import React, { Component } from 'react'
import Bro1 from "./Bro1.jsx"
import Bro2 from "./Bro2.jsx"
export default class home extends Component {
render() {
return (
<div>
<h3>I'm Father.</h3>
{/* 兄弟传值 */}
<Bro1/>
<Bro2/>
</div>
)
}
}
跨组件传值context
react 组件间传递数据是通过 props 向下,单向传递的。从父级一层一层地通过 props 地向下传递到子子孙孙,有的时候我们组件一层一层的嵌套多层,这样这种方式一层一层传递麻烦,如果想跃层传递,这就会用到context。
context:上下文对象。很好的解决了跨组件传值的复杂度,可以快速的进行跨组件数据的传递。
如果想要使用context进行跨组件传值,那么就要使用createContext()
方法,同时方法中给我们提供了两个对象:
- Provider对象 生产者---->用来生产数据
- Consumer对象 消费者---->用来使用数据
注意: context 只能传 不能改。
(一)context使用
在src下创建文件与文件夹,用来容纳context对象
。
创建内容并且引用createContext对象
,然后通过this.props.children
来进行子内容的调用。
在根组件
中使用。这里注意一下,原本包裹< App/> 的是react中的严格模式组件,不过我们把严格模式替换掉成了自定义context上下文对象组件了。
创建Provider生产者
与Consumer消费者
对象,并且创建数据。
在需要的组件中进行使用,比如使用某个数据。
如果需要传递多个值,那么就传递一个对象。
(二)context在js中使用
导出context。
import React, { Component, createContext } from 'react'
let context = createContext()
let { Provider, Consumer } = context
class MyContext extends Component {
render() {
return (
<div>
<Provider value={{ name: "sky", age: 18 }}>{this.props.children}</Provider>
</div>
)
}
}
export { MyContext, Consumer, context }
在需要使用的组件中引用使用。
(三)跨层级传值 小例子
在src下新建一个文件夹,用来存放context相关文件。
传递单个value。
>>index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import {MyContext} from "./myContext/MyContext.js"
ReactDOM.render(
<MyContext>
{/* <React.StrictMode> */}
<App />
{/* </React.StrictMode>, */}
</MyContext>,
document.getElementById('root')
);
serviceWorker.unregister();
React.StrictMode是在react中开启严格模式,参考博文:https://www.jianshu.com/p/d100c6a86c75
>>MyContext.js
import React, { Component, createContext } from 'react'
let context = createContext()
let { Provider, Consumer } = context
class MyContext extends Component {
render() {
return (
<div>
{/* 上下文对象 --- 凌驾于所有组件之上--
-把所有组件当成自己的子组件--
使用this.props.children
{this.props.children} */}
{/* 生产者 传递单个值*/}
{/* <Provider value={123}>{this.props.children}</Provider> */}
{/* 传递多个只值,放在对象里 */}
<Provider value={{ name: "sky", age: 18 }}>{this.props.children}</Provider>
{/* 消费者 在需要用数据的地方使用消费者
<Consumer></Consumer> */}
</div>
)
}
}
export { MyContext, Consumer, context }
``
然后在Bro1中使用
```js
>>Bro1.jsx
import React, { Component } from 'react'
import Pubsub from "pubsub-js"
import { Consumer } from "../myContext/MyContext.js"
export default class Bro1 extends Component {
render() {
return (
<div>
<h4>I'm big bro1.</h4>
消费者消费数据
<Consumer>
{
// value就是数据
(value) => {
return (
// 1、value为非对象类型的值,则获取方法如下
// <div>{value}</div>
// 2、value为对象类型的值,则获取方法如下
// <div>{value.name}</div>
// 3、还可以转化对象为数组,然后遍历出值
<p>{
Object.values(value).map((item, index) => {
return (
<span key={index}>{item} </span>
)
})
}</p>
)
}
}
</Consumer>
</div>
)
}
}
传递多个数据------看上面
如何在js中使用context?
>>Bro1.jsx
//先引入
import { Consumer,context } from "../myContext/MyContext.js"
//然后在一个组件中先定义,再使用
static contextType=context
componentDidMount() {
console.log("在js中使用context上下文对象:",this.context.name);
}
React脚手架中设置样式
其实跟本地模式没啥区别。
创建样式文件。
引入样式文件。
注意添加类使用的是className
。
条件渲染
跟本地模式也没啥区别。
创建按钮并且添加事件与函数:
使用三目判断是否显示:(第一次见还能直接这么写)
循环渲染
(一)根据数据动态生成
创建数据:
通过map遍历生成内容,注意要加key要不然会报错。
不过最好不要把index作为key值,因为当数组变化了,index也会变化,从而lastIndex和index不再能正确代表新旧index,应该用元素的一个唯一标识id作为key值。
react VS Vue diff算法:https://www.jianshu.com/p/a5a02511eb9a
不使用index作为key标识:https://blog.csdn.net/qq_43351249/article/details/102995481
(二)循环渲染—删除内容
父组件正向传递函数给子组件:
子组件再逆向传值给父组件要删除的内容:
父组件接收到值开始删除:
ref使用
在脚手架环境中使用createRef()
。