React 组件三大核心属性 state、props、refs

23 篇文章 0 订阅

React的特点

  • 声明式编码
  • 组件化编码
  • React Native 编写原生应用
  • 高效(优秀的Diffing算法)

React高效的原因

使用虚拟(virtual)DOM, 不总是直接操作页面真实DOM。

DOM Diffing算法, 最小化页面重绘。

相关js库

react.js:React核心库。

react-dom.js:提供操作DOM的react扩展库。

babel.min.js:解析JSX语法代码转为JS代码的库。Babel 可以将 ES6 代码转为 ES5 代码,这样我们就能在目前不支持 ES6 浏览器上执行 React 代码。Babel 内嵌了对 JSX 的支持。通过将 Babel 和 babel-sublime 包(package)一同使用可以让源码的语法渲染上升到一个全新的水平。

以在官网 React – A JavaScript library for building user interfaces 下载最新版。

你也可以直接使用 Staticfile CDN 的 React CDN 库,地址如下:

<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<!-- 生产环境中不建议使用 -->
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>

官方提供的 CDN 地址:

<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<!-- 生产环境中不建议使用 -->
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>

注意: 在浏览器中使用 Babel 来编译 JSX 效率是非常低的。

BootCDN - Bootstrap 中文网开源项目免费 CDN 加速服务

组件三大核心属性

一、 state

state是组件对象最重要的属性, 值是对象(可以包含多个key-value的组合)

组件被称为"状态机", 通过更新组件的state来更新对应的页面显示(重新渲染组件)

组件中render方法中的this为组件实例对象

组件自定义的方法中this为undefined,如何解决?

a) 强制绑定this: 通过函数对象的bind()

constructor(props: Readonly<IProps>) {
  super(props);
  this.handleBtnClick = this.handleBtnClick.bind(this);
}

b) 箭头函数

状态数据,不能直接修改或更新

示例:

需求:定义一个展示天气信息的组件

1. 默认展示天气炎热 或 凉爽

2. 点击文字切换天气

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>展示天气炎热 或 凉爽</title>
</head>
<body>
<!-- 准备好一个“容器” -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<script type="text/babel">
    //创建组件
    class Demo extends React.Component {
        state = {isHot: false}
        changeWeather = () => {
            //获取原来的状态
            const {isHot} = this.state
            //更新状态
            this.setState({isHot: !isHot})
        }

        render() {
            const {isHot} = this.state
            return (
                <div>
                    <h2>今天天气很{isHot ? '炎热' : '凉爽'}</h2>
                    <button onClick={this.changeWeather}>点我切换天气</button>
                </div>
            )
        }
    }

    //渲染组件到页面
    ReactDOM.render(<Demo/>, document.getElementById('test'))
</script>
</body>
</html>

二、 props

每个组件对象都会有props(properties的简写)属性

组件标签的所有属性都保存在props中

作用

通过标签属性从组件外向组件内传递变化的数据

注意: 组件内部不要修改props数据

内部读取某个属性值

this.props.name

使用prop-types库进限制(需要引入prop-types库)

Person.propTypes = {
  name: PropTypes.string.isRequired,
  age: PropTypes.number. 
}

扩展属性: 将对象的所有属性通过props传递

Person {...person}/>

默认属性值:

Person.defaultProps = {
  age: 18,
  sex:'男'
}

组件类的构造函数

  constructor(props){
  super(props)
  console.log(props)//打印所有属性
}

示例:

需求:自定义用来显示一个人员信息的组件

1. 姓名必须指定,且为字符串类型;

2. 性别为字符串类型,如果性别没有指定,默认为男

3. 年龄为字符串类型,且为数字类型,默认值为1**8

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>自定义用来显示一个人员信息的组件</title>
</head>
<body>
<!-- 准备好一个“容器” -->
<div id="test1"></div>
<div id="test2"></div>
<div id="test3"></div>
<!-- 引入react核心库 -->
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<!-- 引入prop-types,用于对组件标签属性进行限制 -->
<script src="https://cdn.bootcdn.net/ajax/libs/prop-types/15.8.1/prop-types.js"></script>

<script type="text/babel"> /* 注意2:此处一定要写babel,表示里面写的不是js,而是jsx,是通过babel将jsx转为js的 */
// 创建类式组件
class Person extends React.Component {

    // 需求:自定义用来显示一个人员信息的组件
    // 1). 姓名必须指定,且为字符串类型;
    // 2). 性别为字符串类型,如果性别没有指定,默认为男
    // 3). 年龄为数字类型,默认值为18

    // 对props进行限制时,可放在类里面,在其前加个static即可
    // 对标签属性进行类型、必要性的限制
    static propTypes = {
        name: PropTypes.string.isRequired, // 姓名必须指定,且为字符串类型
        sex: PropTypes.string, // 性别为字符串类型
        age: PropTypes.number, // 年龄为数值类型
        speak: PropTypes.func, // func表示传函数类型
    }

    // 指定默认标签属性值
    static defaultProps = { // 设置未传值时的默认值
        sex: '男', // 如果性别没有指定,默认为男
        age: 18, // 如果年龄没有指定,默认为18
    }

    // render必须写,且有返回值
    render() {
        // 组件中render方法中的this为组件实例对象
        console.log(this);
        console.log(this.props);
        // es6-对象解构
        const {name, age, sex} = this.props;

        // props是只读的
        // this.props.name = 'jack' // 此行代码会报错,因为props是只读的

        return (
            <ul>
                <li>姓名:{name}</li>
                <li>性别:{sex}</li>
                <li>年龄:{age + 1}</li>
            </ul>
        )
    }

}

// 渲染组件到页面
// 第一种写法
ReactDOM.render(<Person name="tom" sex="女" speak={speak}/>, document.getElementById('test1'));
ReactDOM.render(<Person name="jerry" age={19}/>, document.getElementById('test2'));
// 第二种写法
const p = {name: '老刘', age: 18, sex: '女'}
console.log(...p); // 输出没有内容,因为通过babel+react确实可以让展开运算符展开一个对象滴,但是不允许你随便使用
// 这儿的{...p}里的大括号并不是表示赋值,而是表示里面装js表达式,然后这儿的...p是展开运算符,通过babel+react确实可以让展开运算符展开一个对象滴,但是不允许你随便使用
ReactDOM.render(<Person {...p}/>, document.getElementById('test3'));

function speak() {
    console.log('我说话了');
}
</script>
</body>
</html>

二、refs与事件处理

组件内的标签可以定义ref属性来标识自己

字符串形式的ref

<input ref="input1"/>

 回调形式的ref

<input ref={(c)=>{this.input1 = c}}

 createRef创建ref容器·

myRef = React.createRef() 
<input ref={this.myRef}/>

事件处理

  • 通过onXxx属性指定事件处理函数(注意大小写)
  • React使用的是自定义(合成)事件, 而不是使用的原生DOM事件
  • React中的事件是通过事件委托方式处理的(委托给组件最外层的元素)
  • 通过event.target得到发生事件的DOM元素对象

示例:

需求:自定义用来显示一个人员信息的组件

需求: 自定义组件, 功能说明如下:

1. 点击按钮, 提示第一个输入框中的值

2. 当第2个输入框失去焦点时, 提示这个输入框中的值

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>自定义用来显示一个人员信息的组件</title>
</head>
<body>
<!-- 准备好一个“容器” -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<!-- 引入prop-types,用于对组件标签属性进行限制 -->
<script src="https://cdn.bootcdn.net/ajax/libs/prop-types/15.8.1/prop-types.js"></script>

<script type="text/babel"> /* 注意2:此处一定要写babel,表示里面写的不是js,而是jsx,是通过babel将jsx转为js的 */
// 创建类式组件
// 创建组件
class Demo extends React.Component {

    // 点击展示左侧输入框的数据
    showData = () => {
        console.log(this); // 这儿的this是类Demo的实例对象

        const {input1} = this;
        alert(input1.value);
    }

    // 右侧输入框失去焦点后展示其输入框里的数据
    showData2 = () => {
        console.log(this); // 这儿的this是类Demo的实例对象

        const {input2} = this;
        alert(input2.value);
    }

    render() {
        return (
            <div>
                <input ref={currentNode => this.input1 = currentNode} type="text" placeholder="点击按钮提示数据"/>&nbsp;
                <button onClick={this.showData}>点我提示左侧的数据</button>  &nbsp;
                <input ref={currentNode => this.input2 = currentNode} onBlur={this.showData2} type="text"
                       placeholder="失去焦点提示数据"/>
            </div>
        )
    }
}

// 渲染组件到页面
ReactDOM.render(<Demo/>, document.getElementById('test'));
</script>
</body>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

javafanwk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值