React基础(基础使用)-第一部分

目录

 

1.条件渲染

2.列表循环

3.事件

4.表单

5.父子组件通信

6.setState不可变值

7.生命周期

8.函数组件

9.非受控组件

10.portals

11.异步组件


1.条件渲染

     方式1:利用函数方法输出组件

renderButton(){
    const isLoggedIn = this.state.isLoggedIn;
    if(isLoggedIn)
    {
       return (<LogoutButton onClick={this.handleLogoutClick} />);
    }
    else
    {
      return (<LoginButton onClick={this.handleLoginClick} />);
    }
}

render() {
    return (
      <div>
        <Greeting />
        {this.renderButton()}
      </div>
    );
  }

        方式2:用变量来储存元素

render() {
    const isLoggedIn = this.state.isLoggedIn;
 
    let button = null;
    if (isLoggedIn) {
      button = <LogoutButton onClick={this.handleLogoutClick} />;
    } else {
      button = <LoginButton onClick={this.handleLoginClick} />;
    }
 
    return (
      <div>
        <Greeting isLoggedIn={isLoggedIn} />
        {button}
      </div>
    );
}

2.列表循环

<ul>
    {props.posts.map((item) =>
	    return (
	        <li key={item.id}>
	           {item.title}
	        </li>
	    )
	  )}
</ul>

3.事件

  1. 定义事件时,要对this进行绑定,建议写在constructor中,写在事件绑定后时,那么每一次事件执行都要进行一次this绑定
  2. 关于event参数
    1. event是SyntheticEvent,但模拟DOM事件所有能力
    2. 可以通过event.nativeEvent获取原生对象
    3. 所有的事件,都被挂在到document上,vue中事件绑定和触发都在一个元素上
    4. vue中的事件就是原生的事件
clickHandler(){
	// 这里需要对this进行绑定,因为这里的this默认是undefined
}
clickHandler = () => {
	// 这里不需要对this进行绑定
}
// 第一种:event会追加在最后一个参数
<div onClick={this.clickHandler.bind(this, id, title)}></div>
clickHandler(id, title, event){
	// event会追加在最后一个参数
}
// 第二种:事件对象作为第二个参数传递
<button onClick={e => this.handleClick('zhangjie', e)}>点击事件</button>
handleClick = (...args) => {
  	console.log(args);
}
// 第三种:返回一个函数,事件对象在返回的函数中
<button onClick={this.handleClick('zj')}>点击事件</button>
handleClick = (name) => {
   return (e) => {
     console.log(e, name);
   }
}

4.表单

  1. 受控组件
    1. 即表单中的值受state中的值控制
    2. 例如将input的值与state值关联起来,input的值可以通过state中的值来进行控制
    3. 如果需要实现双向数据绑定,那么可以监听change事件
<textarea value={this.state.text}></textarea>


<select value={this.state.city} onChange={this.onSelectCHange}>
	<option value="beijing">北京</option>
	<option value="shanghai">上海</option>
	<option value="shenzhen">深圳</option>
</select>


<input type="checkbox" checked={this.state.flag} onChange={this.checkboxChange} />


<input type="radio" name="gender" value="male" checked={this.state.gender === 'male'} onChange={this.radioChange} />
<input type="radio" name="gender" value="female" checked={this.state.gender === 'female'} onChange={this.radioChange} />

5.父子组件通信

  • 父组件向子组件传递数据,子组件通过props进行接收
<SubComponent title="传递给子组件的数据"></SubComponent>


// 子组件通过props进行接收
function SubComponent(props){
  return (
    <div>
      {props.title}
    </div>
  )
}
  • 子组件向父组件传递数据,父组件向子组件传递props,传递的props为父组件自身函数,子组件调用该函数,将信息作为函数的参数传递给父组件的作用域中
// 父组件
class App extends React.Component {
  render(){
    return (
      <div>
        <SubComponent callback={this.callback.bind(this)}></SubComponent>
      </div>
    );
  }
  callback(msg){
    console.log(msg)
  }
}

// 子组件
class SubComponent extends React.Component{
  render(){
    return (
      <div>
        <button onClick={this.sendDataToParent.bind(this, '我们通信吧')}>点击我</button>
      </div>
    )
  }
  sendDataToParent(msg){
     this.props.callback(msg);
  }
}
  • 跨级组件通信context,例如将公共信息(语言,主题)传递给每个组件,此时用props太繁琐,用redux小题大,那么可以使用context
const ThemeContext = React.createContext({
  theme:'light'
});

class App extends React.Component{
  constructor(props){
    super(props);
    this.state = {
      theme: 'light'
    }
  }
  render(){
    return (
      <ThemeContext.Provider value={this.state}>
        <Toolbar></Toolbar>
        <button onClick={this.changeTheme}>change theme</button>
      </ThemeContext.Provider>
    )
  }
  changeTheme = () => {
    this.setState({
      theme: this.state.theme === 'light' ? 'dark' : 'light'
    })
  }
}

class Toolbar extends React.Component{
  render(){
    return (
      <div>
        <ThemeButton></ThemeButton>
      </div>
    )
  }
}
class ThemeButton extends React.Component{
  render (){
    return (
      <ThemeContext.Consumer>
        {
          ({theme}) => 
              <p>link's theme is {theme}</p>
        }
      </ThemeContext.Consumer>
    )
  }
}

6.setState不可变值

  • state中的值不可以直接进行修改, 需要通过setState进行修改
const list5Copy = this.state.list5.slice();
list5Copy.splice(2, 0, 'a');
this.setState({
	list1: this.state.list1.concat(100), // 追加
	list2: [...this.state.list2, 100], // 追加
	list3: this.state.list3.slice(0,3), // 截取
	list4: this.state.list4.filter(item => item>100), // 筛选
	list5: list5Copy
})
this.setState({
	obj1: Object.assign({}, this.state.obj1, {'a': 100}),
	obj2: {...this.state.obj2, 'a': 100}
})
  • setState可能是异步操作

	// 直接使用是异步
	this.setState({
		count: this.state.count++
	}, () => {
		console.log('count by callback', this.state.count);
	})
	// setTimeout中setState是同步的
	setTimeout(() => {
		this.setState({
			count: this.state.count++
		})
		console.log(this.state.count);
	}, 0)
	// 自己定义的DOM事件,setState是同步的
	const bodyClickHandler = () => {
		this.setState({
			count: this.state.count++
		})
		console.log(this.state.count)
	}
	componentDIdMount(){
		docuement.body.addEventLisetener('click', this.bodyClickHandler)
	}
	componentWillUnmount(){
		// 及时销毁DOM事件及timer
		docuement.body.removeEventLisetener('click', this.bodyClickHandler)
	}
  • 可能会被合并

	// 以下会进行合并,及只执行一次,即最后count为1
	// 类似于Object.assign({count:1},{count:1})
	this.setState({
		count: this.state.count++
	})
	this.setState({
		count: this.state.count++
	})
	this.setState({
		count: this.state.count++
	})
	// 传入参数不会被合并,即最后count为3
    // 因为传入的是函数,函数本身是不会被合并的
	this.setState((prevState, props) => {
		 return {
		 	count: prevState.count+1
		 }
	})
	this.setState((prevState, props) => {
		 return {
		 	count: prevState.count+1
		 }
	})
	this.setState((prevState, props) => {
		 return {
		 	count: prevState.count+1
		 }
	})

7.生命周期

  1. 可参考react生命周期

8.函数组件

  1. 当组件只接收props,可以使用函数组件
  2. 纯函数:输入props,输出JSX
  3. 没有实例,没有生命周期,没有state
	class List extends React.Component{
		constructor(props){
			super(props)
		}
		render(){
			const {list} = this.props;
			return (
				<ul>
					list.map((item) =>
					    return (
					        <li key={item.id}>
					           {item.title}
					        </li>
					    )
					  )
				</ul>
			)
		}
	}
	// 函数组件
	function List (props){
		const {list} = this.props;
		return (
			<ul>
				list.map((item) =>
				    return (
				        <li key={item.id}>
				           {item.title}
				        </li>
				    )
				  )
			</ul>
		)
	}

9.非受控组件

  • 一般用于需要操作DOM,不能通过state来完成操作时使用,例如文件上传,上传之后获取文件内容。
  • defaultValue:在非受控组件中,如果希望react能赋予一个初始值,但是不进行后续的更新,此时可以指定一个defaultValue属性
  • <input type="checkbox"> 和 <input type="radio"> 支持 defaultChecked<select> 和 <textarea> 支持 defaultValue
    class App extends React.Component{
		constructor(props){
			super(props);
			this.state = {
				name: 'name'
			}
			this.nameInputRef = Reatc.createRef();
		}
		render(){
			return (
				<input defaultValue={this.state.name} ref={this.nameInputRef} />
				<button onClick={this.alertName}></button>
			)
		}
		alertName = () => {
			const ele = this.nameInputRef.current;
			// 不是state中值,是input中的值,即input中的值不受state中控制,input中输入的值和state并没有关系
			alert(ele.value);	
		}
	}
  • 如下实现在进行提交时获取文件信息的demo

class FileInput extends React.Component {
  constructor(props) {
    super(props);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.fileInput = React.createRef();
  }
  handleSubmit(event) {
    event.preventDefault();
    alert(
      `Selected file - ${this.fileInput.current.files[0].name}`
    );
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Upload file:
          <input type="file" ref={this.fileInput} />
        </label>
        <br />
        <button type="submit">Submit</button>
      </form>
    );
  }
}

10.portals

  1. 组件默认会按照既定层次嵌套渲染
  2. 如果父组件overflow:hidden;父组件z-index太小,且某个组件需要实现fixed放在body第一层,那么可以使用portal实现使子组件逃离父组件进行渲染
	// 父组件
	render(){
		return (
			<portalsDemo>
				Model Content
			</portalsDemo>
		)
	}

	// 子组件
	render(){
		// this.props.children类似于vue中的插槽,可以获取到组件引用时嵌套的内容
		return ReactDOM.createPortal(
			<div className="modal">{this.props.children}</div>,
			document.body  // DOM节点,表示该组件会挂载body上
		)
	}

11.异步组件

  1. 组件比较大,路由需要懒加载,就需要使用异步组件
  2. React.lazy与React.suspense
const ContextDemo = React.lazy(() => import('./ContextDemo'))

class App extends React.Component{
  render(){
    return (
      <div>
        <p>引入一个动态组件</p>
        <br/>
        <React.Suspense fallback={<div>loading...</div>}>
          <ContextDemo /> 
        </React.Suspense>
      </div>
    )
  }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值