react3:受控组件(表单受控)- 组件通信 - TS项目 (tabbar底部导航)

受控组件:表单

  1. 非受控组件表单元素值不受所在组件状态的控制, 这样的表单元素称作: 非受控组件
  2. 受控组件受控组件 : 值受到 React 组件状态控制的表单元素一般是通过 defaultValue 属性, onChange 事件配合将非受控组件变为受控组件
  3. 多表单元素操作 :4,5,6
  4. 给表单元素添加 name 属性,名称与 state 相同
  5. 根据表单元素类型获取对应值
  6. change 事件处理程序中通过 [name] 来修改对应的 state

通过value和onChange事件,让表单元素变成 受控组件

复选框,是否勾选 checked={ }, 配合onChange事件

获取最新input值

操作value使其变成受控组件(文本框、富文本框、下拉框)

name判断点的哪个

[ ]:可以对其中的表达式进行取值预算:取值结束,[ ] 就没有了

e.target        获取目标对象

e.target.type        获取元素类型

e.target.name        获取元素的name

e.target.type="checkbox"         获取元素的复选状态

e.target.value        获取元素的值

 

 代码如下:::

import React, { Component } from 'react';
import './App.scss'
// react应用的组件有两种创建方式:函数式组件,类组件
// rcc 创建calss组件
// rsf创建函数式组件

class App extends Component {
  constructor(props){
    super(props)
    // 定义组件状态
    this.state={
      loginname:'',
      password:'',
      isread:false
    }
  }
  handleChange(e){
    console.log(e.target);
    // if (e.target.name == 'loginname') {
    //   this.setState({loginname:e.target.value})
    // }else if(e.target.name == 'password'){
    //   this.setState({password:e.target.value})
    // }

    //[] 可以对其中的表达式进行取值运算,取值结束,[] 就没有了

    // e.target  //获取目标对象
    // e.target.type  //获取元素类型
    // e.target.name //获取元素的name
    // e.target.type='checkbox' //元素的复选状态
    // e.target.value //元素的值

    // name名和state中名一样,那就可以这样简写了,一次修改所有表单元素的值 
    this.setState({[e.target.name]:e.target.type == "checkbox" ? e.target.checked : e.target.value})
  }
  login(){
    console.log(this.state);
  }
  render() {
    return (
      <div className='login'>
        <div className='block'>
            {/* 通过 value属性 和 onChange事件 让表单元素变成 受控元素 */}
            <input name='loginname' type="text" placeholder='输入账号' value={this.state.loginname} onChange={(e)=>{this.handleChange(e)}} />
        </div>
        <div className='block'>
            {/* 通过value属性 和 onChange事件 让表单元素变成 受控元素 */}
            <input name='password' type="password" placeholder='输入密码' value={this.state.password} onChange={(e)=>{this.handleChange(e)}} />
        </div>
        <div className='block'>
            {/* 通过value属性 和 onChange事件 让表单元素变成受控元素 */}
            <input name='isread' type="checkbox" checked={this.state.isread} onChange={(e)=>{this.handleChange(e)}} />勾选用户协议
        </div>
        <div className='block'>
            {/* input type=buttom 相当于提交表单 */}
            <input type="button" value='登录' onClick={()=>{this.login()}}/>
        </div>
      </div>
    );
  }
}

export default App;

 组件通信:

//父组件向子组件传值: 父组件通过自定义属性传值给子组件, 子组件内部通过props获取值

//子组件向父组件传值: 父组件通过自定义属性传一个函数给子组件, 子组件内部通过props获取该函数并在合适的时机回调该函数完成传值.

//兄弟组件传值: 借助events库 先实例化一个公共的通信对象eventBus文件,导入eventBus, 其中一个组件提前on监听事件, 另一个兄弟组件在合适的时机 emit 触发事件传值off 取消监听.

//跨组件传值: 借助createContext方法 先实例化一个公共的上下文通信对象, 外层组件通过Provider组件的value属性传值, 内层组件和上下文通信对象建立连接, 然后再通过this.context获取值.

父向子,子向父

兄弟组件通信:自带 events 不用装(尝试自己封装eventBus库)

eventBus库

emit触发传值

 

on监听:

off 写在取消监听(性能优化):不是同一个函数名不能取消监听,绑定相同函数名可以取消监听

和事件监听,取消事件监听很像

 

跨组件通信:需要借助createContext方法,先实例化一个 utils文件夹下

React.createContext 实例化一个功能的通信上下文对象

创建上下文

MyContext.Provider 的value属性传值

app主文件。我的上下文

eg:中间有隔层文件

Class.contextType 和组件通信建立连接

类 构造函数

 

非嵌套组件间通信

1.利用二者共同父组件进行通信

2.使用自定义事件的方式

创建新项目typescript项目:::已有项目添加typescript则需要另加配置项

npx create-react-app my-app --template typescript

tabbar底部导航:另类写法:主要用来子向父传递了索引,父判断。

import './App.scss';
// React应用的组件有两种创建方式: 函数式组件, 类组件
// rcc 创建class组件
// rsf 创建函数式组件
import React, { Component } from 'react';

import TopNav from '@/components/TopNav';
import Swiper from '@/components/Swiper';
import CateList from '@/components/CateList';
import Tabbar from '@/components/Tabbar';
import Cate from '@/components/Cate/Cate';

class App extends Component {
  constructor(props){
    super(props);
    this.state = { index:0 }
  }
  getIndex = (i)=>{
    this.setState({ index: i })
  }
  render() {
    return (
      <div>
        {/* 顶部导航 */}
        {/* 轮播图 */}
        {/* 分类导航 */}
        {
          this.state.index == 0 && 
            <>
              <TopNav />
              <Swiper />
              <CateList />
            </>
        }

        {
          this.state.index == 1 && <Cate />
        }


        {/* 底部导航 */}
        <Tabbar getIndex={this.getIndex} />

      </div>
    );
  }
}

export default App;

import React, { Component } from 'react';
import './index.scss'
class Tabbar extends Component {
    constructor(props) {
        // props和state的区别
        // 分别介绍两个技术的概念,先回答相同点,再回到不同点,最后总结一下(个人感悟,注意事项)

        // props是个对象,用来接收父组件传来的值,props默认是只读的(如果某个属性是引用类型,则引用数据的属性是可以修改)
        // state是个对象,用来定义组件自身的状态,可以通过setState来修改
        super(props)
        // 定义组件状态
        this.state = {
            tabs: [
                { text: '首页', img: '' },
                { text: '分类', img: '' },
                { text: '首页', img: '' },
                { text: '首页', img: '' },
            ],
            currentIndex: 0,
        }
    }
    handleClick(index) {
        // 回调父组件的方法
        this.props.getIndex(index)
        // this.state.currentIndex = index //这个写法可以保存数据到组件状态中,但是无法触发组件更新
        // setState会保存数据到组件状态中,同时会触发组件更新
        this.setState({ currentIndex: index }, () => {
            // 想要获取setState保存的最新状态值,必须在第二个参数的回调函数中获取(setState本身是异步的)
            // console.log('handleClick', this.state.currentIndex);
        })
    }
    render() {
        return (
            <div className='tabbar'>
                {
                    this.state.tabs.map((item, index) => {
                        return(
                            <div className={`btn ${this.state.currentIndex == index? 'active':''}`} key={index} onClick={()=>{this.handleClick(index)}}>
                                <img src={item.img} alt="" />
                                <div className='text'>{item.text}</div>
                            </div>
                        )
                    })
                }
            </div>
        );
    }
}

export default Tabbar;
.tabbar{
    position: fixed;
    bottom: 0;
    width: 100%;
    display: flex;
    justify-content: space-around;
    align-items: center;
    margin: 15px;
    border-top: 1px solid #ccc;
    .btn.active{
        color: red;
        font-weight: bold;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值