Ref
组件分类(控件方式不同):受控组件 与 非受控组件
大多数情况下,建议使用受控组件。
有一种称为非受控组件的方法可以通过使用Ref来处理表单数据。
在非受控组件中,Ref用于直接从DOM访问表单值,而不是事件处理程序。
使用React.createRef() 定义Ref并传递该输入表单。
class Test extends Component{
constructor() {
super();
this.user = React.createRef();
}
sumbit(){
console.log(this.user.current.value);
}
render(){
return (<div>
<input type="text" ref={this.user} placeholder='请输入内容'/>
<br/>
<button onClick={()=>this.sumbit()}>提交</button>
</div>)
}
}
findDOMNode
findDOMNode 用于访问组件 DOM 元素节点,但只能用在已经挂载的组件上。react 推荐使用 ref 模式。
如果组件渲染内容为 null 或者是 false,那么 findDOMNode返回值也是 null。
findDOMNode 不能用于函数组件。
class Index extends React.Component{
handerFindDom=()=>{
console.log(ReactDOM.findDOMNode(this))
}
render(){
return <div style={{ marginTop:'100px' }} >
<div>hello,world</div>
<button onClick={ this.handerFindDom } >获取容器dom</button>
</div>
}
}
受控组件
//对象的键名,可以写成变量; 使用[]包起来就认为里面写的是变量
//写value属性值 ,一定要写onChange事件,不然报错.或者使用默认值defaultValue
class Test extends Component{
constructor() {
super();
this.state={
user:'',
pwd:'',
email:'yangyang@126.com'
}
}
userLogin(){
// 获取 user pwd email
}
handleChange(e,type){
this.setState({
[type]:e.target.value
//注意键名在setState中是变量的时候是使用[]而不是{}
})
}
render(){
let {user,pwd,email} = this.state;
return (<div>
<h2>登录</h2>
<p>{user}</p>
<p>{pwd}</p>
<p>{email}</p>
<p><input type="text"
value={user}
onChange={(e)=>this.handleChange(e,'user')}
placeholder='用户名'/></p>
<p><input type="password" value={pwd}
onChange={(e)=>this.handleChange(e,'pwd')}
placeholder='密码'/></p>
<p><input type="text"
value={email}
onChange={(e)=>this.handleChange(e,'email')}
placeholder='email'/></p>
<p><button onClick={()=>this.userLogin()}>登录</button></p>
</div>)
}
}
默认值
<input type="checkbox"> 和 <input type="radio"> 支持 defaultChecked,
<input type="text"">、<select> 和 <textarea> 支持 defaultValue。
插槽
匿名插槽:this.props.children ; 可以获取父组中使用组件时的标签之间写的内容。
具名插槽:
import Test from "./Pages/test";
function App() {
const h = <h2>这是头部</h2>;
const f = <h2>这是底部</h2>;
return (
<div className="App">
<Test header={h} footer={f}>
<p>匿名插槽</p>
</Test>
</div>
);
}
class Test extends Component{
render(){
return (<div>
//匿名插槽
{this.props.children}
<header>
{this.props.header}
</header>
<section>
<h2>这是测试内容</h2>
</section>
<footer>
{this.props.footer}
</footer>
</div>)
}
}
组件传值
父组件向子组件通信:父组件通过 props 向子组件通信。(props)
//父组件
import Test from './Components/Test';
function App() {
constructor(){
super();
this.state = {
list:[1,2,3]
}
}
return (
<div className="App">
<Test list={this.state.list}></Test>
</div>
);
}
//子组件
class Test extends Component{
render(){
const {list} = this.props;
return(
<div>
{list}
</div>
)
}
}
子组件传父组件通信:子组件通过事件回调向父组件通信。父组件中写处理程序 ,给父组件中子组件的标签加上事件;子组件中触发事件,并向事件传值。
//父组件
function App() {
function handleClick(obj) {
console.log('这是父组件的内容', obj);
}
return (
<div className="App">
<Test onTest={handleClick}></Test>
</div>
);
}
//子组件
class Test extends Component {
constructor() {
super();
this.state = {}
}
handleClick() {
this.props.onTest('子组件传递的参数')
}
render() {
return (
<div>
<button onClick={()=>{this.handleClick()}}>向父组件中传值</button>
</div>
)
}
}
Context 实现数据通信
Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法。
Context (上下文对象)、 Provider(提供者) 、Consumer(消费者) 的关系。
// 第一步:创建 Context: MyContext.js
import React from "react";
const MyContext = React.createContext();
export default MyContext;
const MyContext = React.createContext(defaultValue); // 可以设置默认值
// 第二步、创建 Provider:
let {Provider } = MyContext;
<Provider value={}></Provider>
//第三步: 定义消费者
let {Consumer } = MyContext;
<Consumer >
{
( data )=>{ // data 与provider 的value值 一致
return <div></div>
}
}
</Consumer>
实例:
Context(平台)
import React from 'react';
const MyContext = React.createContext();
export default MyContext;
Provider(提供者)
import React, { Component } from 'react';
import MyContext from './MyContext';
class MyProvider extends Component {
state = {
cars: [
{ name: 'dazhong', price: '200000' },
{ name: 'baoma', price: '500000' }
]
}
render() {
return (
<MyContext.Provider value={
{
cars: this.state.cars,
//除了数据也可以放方法在提供者中
add: (obj) => {
this.setState({
cars: [...this.state.cars, obj]
})
},
del: (i) => {
let newCar = [...this.state.cars].splice(i, 1);
this.setState({ cars: newCar })
}
}
}>
{this.props.children}
</MyContext.Provider>
)
}
}
export default MyProvider;
Consumer(消费者)
import MyContext from "./MyContext";
import React from "react";
import Car from './Car';
const Cars = () => (<MyContext.Consumer>
{
//context.cars就已经能拿到提供者传过来的数据了
//这里把数据再传给了它的子组件Car
(context) => context.cars.map(
(item, index) => (<Car key={index}
name={item.name}
price={item.price}
add={context.add}
del={context.del}
></Car>)
)
}
</MyContext.Consumer>)
export default Cars;
上文消费者的子组件:
import { Component } from "react";
class Car extends Component {
render() {
let { name, price, add, del } = this.props;
return (
<div>
<p>{name}</p>
<p>{price}</p>
<p><button onClick={add}>添加</button></p>
<p><button onClick={del}>删除</button></p>
</div>
)
}
}
export default Car;