React基础学习(第二天)

虚拟DOM

  • JSX 涉及到 虚拟DOM ,简单聊一下

定时器渲染问题

// 方法
function render() {//2. 创建react对象let el = (<div><h3>时间更新</h3><p>{ new Date().toLocaleTimeString()}</p></div>)//3. 渲染ReactDOM.render(el, document.getElementById('root'))
}//4. 开启一个定时器, 每秒渲染一次
setInterval(() => {render()
}, 1000)

渲染模式 :

/*** 最早的更新模式* 1. 数据* 2. 模板* 3. 数据+模板 => 真实的DOM* 4. 数据变了 => 最简单直接的方式 => 最新数据+模板 => 新的DOM* 5. 新的DOM 把 旧的DOM完全直接替换掉* 6. 显示新的DOM** 缺点 : 完全替换,  性能不好** 1. 数据* 2. 模板* 3. 数据+模板 => 真实的DOM* 4. 数据变化了 => 最新的数据 + 模板 => 新的DOM* 5. 新的DOM 和 旧的DOM 进行一一比较, 找到需要更新的地方* 6. 只需要更新需要改变的地方即可** 优点 : 不再是全部替换掉,* 缺点 : DOM比较就有性能问题了 , 会有多余的DOM和属性进行比较(打印一级属性),有损性能*  p 和 p对比  h3 和h3对比(多余的对比)** 1. 数据* 2. 模板* 3. 数据 + 模板 => 虚拟DOM (js对象) => 真实的DOM* 4. 数据发生改变(zs=>ls) => 最新的数据 + 模板 => 新的虚拟DOM* 5. 新的虚拟DOM 和 旧的虚拟DOM 通过 diff算法 进行比较* 6. 找到有差异的地方,(需要更新的地方)* 7. 更新一下就可以看到最新的DOM了*/
  • 打印属性 :
let root = document.querySelector('#root')let str = ''
let count = 0
for (let k in root) {str += k + ' 'count++
}
console.log(str, count)
  • 查看图片 : 演示对比找差异渲染
  • 文字描述 :
这就是所谓的 Virtual DOM 算法。包括几个步骤:- 1.用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中
- 2.当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异
- 3.2 所记录的差异应用到步骤 1 所构建的真正的 DOM 树上,视图就更新了

DIff 算法

React 中有两种假定:

  • 1 两个不同类型的元素会产生不同的树
  • 2 开发者可以通过 key 属性指定不同树中没有发生改变的子元素

Diff 算法的说明 - 1

  • 如果两棵树的根元素类型不同,React 会销毁旧树,创建新树
// 旧树
<div><Counter />
</div>// 新树
<span><Counter />
</span>执行过程: 删除 div , 创建 span

Diff 算法的说明 - 2

  • 对于类型相同的 React DOM 元素,React 会对比两者的属性是否相同,只更新不同的属性
  • 当处理完这个 DOM 节点,React 就会递归处理子节点。
// 旧
<div className="before" title="stuff"></div>
// 新
<div className="after" title="stuff"></div>
只更新:className 属性// 旧
<div style={{color: 'red', fontWeight: 'bold'}}></div>
// 新
<div style={{color: 'green', fontWeight: 'bold'}}></div>
只更新:color属性

Diff 算法的说明 - 3

  • 1 当在子节点的后面添加一个节点,这时候两棵树的转化工作执行的很好
// 旧
<ul><li>1</li><li>2</li>
</ul>// 新
<ul><li>1</li><li>2</li><li>3</li>
</ul>执行过程:
React会匹配新旧两个<li>1</li>,匹配两个<li>2</li>,然后添加 <li>3</li> tree
  • 2 但是如果你在开始位置插入一个元素,那么问题就来了:
// 旧
<ul><li>1</li><li>2</li>
</ul>// 新
<ul><li>3</li>   li3 插入最前面<li>1</li><li>2</li>
</ul>执行过程:
React将改变每一个子节点,而非保持 <li>1</li><li>2</li> 不变

key 属性

为了解决以上问题,React 提供了一个 key 属性。当子节点带有 key 属性,React 会通过 key 来匹配原始树和后来的树。

// 旧
<ul><li key="1">1</li><li key="2">2</li>
</ul>// 新
<ul><li key="3">3</li><li key="1">1</li><li key="2">2</li>
</ul>执行过程:现在 React 知道带有key '3' 的元素是新的,对于 '1''2' 仅仅移动位置即可

补充说明:

  • key 属性在 React 内部使用,但不会传递给你的组件

  • 推荐:在遍历数据时,推荐在组件中使用 key 属性:<li key={item.id}>{item.name}</li>

  • 注意:key 只需要保持与他的兄弟节点唯一即可,不需要全局唯一

  • 注意:尽可能的减少数组 index 作为 key,数组中插入元素的等操作时,会使得效率底下 。 如果数组比较简单, 开发中没有删除和移动操作,使用 index 也是可以的

组件

组件1 - 函数组件

基本使用

  • 函数组件 : 使用函数创建的组件叫组函数组件
  • 约定:
    • 约定1 : 组件名称必须是大写字母开头, 也就是函数名称需要首字母大写
    • 约定2 : 函数组件必须有返回值
      • 不渲染内容 : return null
      • 渲染内容 : return JSX
    • 约定3 : 只能有一个唯一的根元素
    • 约定4 : 结构复杂, 使用() 包裹起来
  • 使用 : 把 组件名 当成 标签名 一样使用
// 函数组件
function Hello() {// return nullreturn <div>这是我的第一个函数组件</div>
}
// 渲染组件
ReactDOM.render(<Hello />, document.getElementById('root'))

传参

  • 传参 :
//1. 头标签内演示
//2. age='30'  age是字符串30age={30}   age是number 30
ReactDOM.render(<Child name='zs' age={30}/>, document.getElementById('root'))
  • 接收 :
    • 函数的参数接收 props
      • funciton Hello (props) { ... }
    • 读取 : { props.name } 、 { props.age }
    • 注意 :
      • 传过来的props 不能添加属性
      • 传过来的props 不能修改属性值
    • 也可以直接解构 props里的属性
      • funciton Hello ({ name, age }) { ... }

箭头函数改造

const  Child = () => (<div><div>这是一个div</div><div>这是一个div</div></div>
)const Hello = ()=> <div>这是哈哈的啊</div>

组件2 - 类组件

基本使用

  • 类组件 : 使用 ES6 中class 创建的组件, 叫类组件
  • 约定 (同 函数组件)
    • 其他约定1 : 类组件必须继承自 React.Component 父类 , 然后,才可以使用父类中提供的属性或方法
    • 其他约定2 : 必须提供 render 方法, 来指定要渲染的内容, render 方法必须有返回值
// 2 创建类组件
class Hello extends React.Component {// 钩子 render() {// return nullreturn <div>这是我的第一个class组件</div>}
}

传参

  • 传参 : 同函数组件一样
ReactDOM.render(<Child name='zs'/>, document.getElementById('root'))
  • 接收参数
// 类组件
class Child extends React.Component { constructor(props) { super(props)// 接收方式1console.log(props);}render () { // 接收方式2console.log(this.props);// 解构const { name, age } = this.propsreturn <div>哈哈{ this.props.name }</div>}
}

ES6 - class

介绍

 ** es6 之前 创建对象 都是通过构造函数 实现的, 给原型添加方法,  给实例添加属性* es6 之后, 给我们提供了一个字段 class *  通过class 创建对象 *   class :*     -: 一类对象, 对象的抽象 , 我们可以通过类创建对象*     - 动物        人 * *     - 对象: 具体的事物, 它有特征(属性)和行为(方法)*     -//鸟     张三/王春春*/

使用 class 创建对象

  • 使用class 创建一个类 class Person { }
  • 创建对象 let p = new Person()
  • 添加属性 在类里面的 constructor() { } 的里面添加属性
  • 添加方法 直接在类里面添加方法
class Person { constructor() { this.name = 'zs';this.age = 30}say () { console.log('说话了');}
}let p = new Person()
console.log(p);
p.say()

继承

  • 继承 : 之前混入, 原型继承… 都是对象继承… (对象与对象之间,只要拿过来用就是继承)
  • class 继承 : 是 类与类之间的继承 extends
// 人
class Person {constructor() {this.maxAge= 120}
}let p = new Person()
console.log(p)// ---------------------------------------------
/*** 以后凡是 extends 继承* 当前类里面的 constructor 里面一定要加上super()* 因为底层都是给我们加的super,所以我们才能够继承过来,* 如果我们直接写 constructor,而不写super,意外着,底层的constructor会被覆盖掉*/
// 中国人
class Chinese extends Person {constructor() {super() // super 其实就是调用父类的constructorthis.name = 'zs'}
}let c = new Chinese()
console.log(c)

函数组件和类组件的小结

  • 函数组件 : 函数创建组件
    • 函数名首字母一定要大写
    • 把组件当成标签使用
    • 函数内部 通过 return jsx
  • 类组件 : 类创建组件
    • 首字母也要大写
    • 一定要继承(extends) React.Component
    • 类里面一定要有一个 render 函数
    • render 函数里面通过 return jsx
    • 类组件也是当成标签一样使用的

函数组件和类组件的区别?

  • 函数组件 : 没有状态的, 没有自己的数据
  • 类组件 : 有状态 , 有自己的数据

状态 State 的简单说明

state 的定义

  • 方式1 : constructor 里面
 constructor() { super()//设置状态1this.state = {name : 'zs'}}
  • 方法2 : 属性初始化语法
// 设置状态2
state = {name :'zhangsan '}

获取 状态 值 :

 // 直接获取<p> { this.state.name }</p>// 解构获取const { name } = this.state<p> { name }</p>

修改 状态 值

// 钩子函数 -  组件挂载完全  render调用完后会调用
componentDidMount() {//1. 直接修改// 如果使用 this.state.name = '春春' , 这样只会修改state里面的数据,但是无法更新视图// this.state.name = '春春'//2. 使用 setState 修改// 1-修改数据 2-重新调用render, 更新视图this.setState({name: '春春'})
}

安装 React 插件 ==> 查看 state 的值

  • react-developer-tools.crx
  • 安装步骤 : 后缀crx 改为 zip, 解压到当前文件, 安装 拓展程序

使用 state 修改定时器

//2. 类组件
class Child extends React.Component {state = {time : new Date()     # + }render() {return (<div><h3>我是h3</h3><p>{ this.state.time.toLocaleTimeString() }</p>   # + </div>)}componentDidMount () { setInterval(() => {this.setState({      # + time: new Date()   # + })                   # + }, 1000);}
}

总结 :

  • 函数组件
    • 没有状态 ( 没有自己的私有数据 )
    • 木偶组件, 组件一旦写好, 基本就不会改变
    • 传参 : function Child( props ) { } , props 只读
  • 类组件
    • 有状态 ( 有自己的私有数据 state )
    • 智能组件, 状态发生改变, 就会更新视图
    • 传参 :
      • this.props
  • 优点
    • 类组件 : 有状态,有生命周期钩子函数, 功能比较强大
    • 函数组件 : 渲染更快
  • 以后区分使用 ?
    • 就看要不要状态 , 要状态(类组件) , 不要状态 (函数组件)
  • props 和 state 区别?
    • state - 自己的私有数据 类似 vue 里的data
    • props - 外界传进来的 类似 vue 里面的props

事件处理

事件注册

  • 以前注册事件
<button onclick='fn'>按钮</button>
  • react 中注册事件
    • 注册事件属性采用的是驼峰的 onClick=…
    • 注册事件的事件处理函数 , 写为函数形式,不能为字符串
    • onClick={ this.fn }, {} 可以拿到它的原始类型
// 注册事件
<button onClick={ this.fn }>按钮</button>// 事件处理函数
fn() {console.log('我被点击了')
}

事件中 this 的处理

  • 演示this问题
// 注册
<button onClick={this.fn}>按钮</button>
// 事件
fn () { console.log('点击了');this.setState({name : 'ls'})
}
// 报错 : Uncaught TypeError: Cannot read property 'setState' of undefined
// react 中的this=undefined  是需要处理的
  • bind 和 call 的回忆使用
function f() {console.log(this)
}let obj = { name: 'zs' }bind 的使用
f.bind(obj) :  f里面的this 指向了obj
绑定之后没有打印,不是bind出了问题,而是bind和call,和apply()
call和apply 1-调用 2-指向
bind   1-指向 2-返回一个新函数
let newF = f.bind(obj)newF()
  • 方式1 : bind
- 第一种constructor() { super()this.fn1 = this.fn1.bind(this)}- 第二种 : <button onClick={   this.fn1.bind(this)    }>按钮</button>
  • 方式2 : 属性初始化语法
// 注册事件
return <button onClick={this.fn2}>按钮</button>
// 属性初始化语法
fn2 = () => { // 箭头函数里面的this指向了外部的thisthis.setState({name : 'ls'})}
  • 方式3 : 箭头函数
 <button onClick={     () =>  this.fn3()      }>按钮</button>// 箭头函数里面的this 指向外部的this
// 谁调当前this所在的函数, this就执行谁
fn3(){...
}
  • 总结
// 方法1 : bind (常用)
return <button onClick={     this.fn.bind(this) }>按钮</button>
// 方法2 : 属性初始化语法
return <button onClick={     this.fn1           }>按钮</button>
// 方法3 : 箭头函数
return <button onClick={    () => this.fn()     }>按钮</button>
  • 三者使用场景
- 方式1和方式3 常用
- 如果函数体内的代码比较少,比如就1~2=> 方式3
- 大部分情况下 => 优先使用 方式2
- 如果涉及到传参  => 方式3

点击事件传参 + 配合this处理

  • 演示效果
return <button onClick={this.fn(123)}>按钮</button>
不能这样传参,因为还没有开始点击,就已经开始调用了fn , 并且把参数传过去了
  • 处理this方式1 : bind
 // 注册事
return <button onClick={    this.fn.bind(this,123)     }>按钮</button>// 传参
fn( num ) { console.log('点击了',num);
}
  • 处理this方式2 : 属性初始化语法 – 不能传参
  • 处理this方式3 : 箭头函数
 // 注册事
return <button onClick={   () => this.fn(123)          }>按钮</button>// 传参
fn( num ) { console.log('点击了',num);
}

获取事件对象 + 配合this处理

// 方式1 : bind , `处理函数最后一个参数`就是 事件对象 e
return <button onClick={this.fn1.bind(this, 123, 456)}>按钮</button>
// 方式2 : 属性初始化语法  不传参数 默认形参就是事件对象 e
return <button onClick={this.fn2}>按钮</button>
// 方式3 : 箭头函数 通过箭头函数获取e,再继续传
return <button onClick={e => this.fn3(e)}>按钮</button>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/247921.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

iOS 去除字符串中的空格或多余空格(适合英文单词)

NSString -stringByTrimmingCharactersInSet: 是个你需要牢牢记住的方法。它经常会传入 NSCharacterSet whitespaceCharacterSet 或 whitespaceAndNewlineCharacterSet 来删除输入字符串的头尾的空白符号。 需要重点注意的是&#xff0c;这个方法 仅仅 去除了 开头 和 结尾 的…

华为交换机在Telnet登录下自动显示接口信息

因为用console连接交换机&#xff0c;默认是自动显示接口信息的&#xff0c;比如down掉一个接口后&#xff0c;会自动弹出接口被down掉的信息&#xff0c;但是在telnet连接下&#xff0c;默认是不显示这些信息的&#xff0c;需要开启后才可显示。 1、首先开启info-center(默认是…

React基础学习(第三天)

条件渲染 1. if / else render () {if (this.state.isLoading) { // 正在加载中return <h1>Loading...</h1>}return <div>这就是我们想要的内容</div>} // 钩子函数 五秒钟之后 修改状态值componentDidMount () { setTimeout(() > {this.setState(…

componentsJoinedByString 和 componentsSeparatedByString 的方法的区别

将string字符串转换为array数组 NSArray *array [Str componentsSeparatedByString:","]; &#xff1d;&#xff1d;反向方法 将array数组转换为string字符串 NSString *tempString [mutableArray componentsJoinedByString:","];--,是分隔符 可不加分隔…

java中的各种数据类型在内存中存储的方式

转载别人的附上链接&#xff1a;https://blog.csdn.net/zj15527620802/article/details/80622314 1.java是如何管理内存的 java的内存管理就是对象的分配和释放问题。&#xff08;其中包括两部分&#xff09; 分配&#xff1a;内存的分配是由程序完成的&#xff0c;程序员需要通…

vscode的 jsonp 配置文件

{ // 工具-字体大小 “editor.fontSize”: 15, // 工具-tab缩进 “editor.tabSize”: 2, // 工具-在视区宽度换行 “editor.wordWrap”: “on”, // 工具-缩放 “window.zoomLevel”: 1, // 工具-编写tab识别语言格式 “emmet.includeLanguages”: { “vue-html”: “html”, “…

NSString拼接字符串和NSPredicate详解

NSString* string; // 结果字符串 02 NSString* string1, string2; //已存在的字符串&#xff0c;需要将string1和string2连接起来 03 04 //方法1. 05 string [[NSString alloc]initWithFormat:"%,%", string1, string2 ]; 06 07 //方法2. 08 string [string1 …

线程模块

信号量 from threading import Semaphore,Thread import timedef func(a,b):time.sleep(1)sem.acquire()print(ab)sem.release()sem Semaphore(4) for i in range(10):t Thread(targetfunc,args(i,i5))t.start() 信号量事件 # 事件被创建的时候&#xff0c;默认为False状态 #…

React中级学习(第一天)

Props深入 children 作用 : 获取组件标签的 子节点获取方式 : this.props.children <App>此处的内容&#xff0c;就是组件的 children&#xff0c;将来通过组件的 props.children 就可以获取到这些子节点了 </App>props 校验 作用&#xff1a;规定组件props的类…

iOS 正则表达式判断纯数字以及匹配11位手机号码

1用正则表达式 //是否是纯数字(BOOL)isNumText:(NSString *)str{NSString * regex "(/^[0-9]*$/)";NSPredicate * pred [NSPredicate predicateWithFormat:"SELF MATCHES %", regex];BOOL isMatch [pred evaluateWithObject:st…

Elasticsearch集成ik分词器

1、插件地址https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.0.0/elasticsearch-analysis-ik-7.0.0.zip 2、找到对应版本的插件通过 http://192.168.1.8:9200查看ES的版本&#xff0c;找到对应的IK分词插件 下载与之对应的版本https://github.com/me…

React中级学习(第二天)

JSX 语法的转化过程 (了解) 演示 : babel中文网试一试 let h1 JSX 仅仅是createElement() 方法的语法糖 (简化语法)JSX 语法 被 babel/preset-react 插件编译为 createElement() 方法React 元素&#xff1a;是一个对象&#xff0c;用来描述你希望在屏幕上看到的内容React 元素…

【】MTCNN基于NCNN的测试过程

前言 操作过程 NCNN: https://github.com/Tencent/ncnn/wiki/how-to-build#build-for-linux-x86; vector初始化&#xff1a;int num[4] { 1, 4, 3, 2 }; int numLength sizeof(num) / sizeof(num[0]); vector<int> nums(num, num numLength); //使用数组初始化向量 Q&…

iOS NSTextAttachment - 图文混排

苹果在iOS7中推出了一个新的类NSTextAttachment&#xff0c;它是做图文混排的利器&#xff0c;本文就是用这个类&#xff0c;只用50行代码实现文字与表情混排&#xff0c;当然也可以实现段落中的图文混排。 首先说一下文字和表情的混排&#xff1a; 先来做点儿准备工作&#…

vuex的结构有哪些参数?

查看参考地址&#xff1a; https://vuex.vuejs.org/zh/ vuex 状态管理模式&#xff0c;相当于数据的中间商 注意&#xff1a; 为相同 属性有&#xff1a; 1.State vue中的data —> 存放数据 2.Getter vue中的计算属性computed —>将已有的数据进行计算再次利用 3.…

百炼OJ - 1004 - 财务管理

题目链接&#xff1a;http://bailian.openjudge.cn/practice/1004/ 思路 求和取平均。。。 #include <stdio.h>int main() {float sum0,a;for(int i0;i<12;i){scanf("%f",&a);sum a;}printf("$%.2f\n",sum/12);return 0; } 转载于:https://w…

iOS 自定义Cell按钮的点击代理事件

在实际开发工作中&#xff0c;我们经常会在自定义的Cell中布局一些按钮&#xff0c;并且很多时候我们会在点击这个按钮的时候使我们的UItableviewController跳转到下一界面&#xff0c;有的可能还要传值。那么如何使我们的控制器能够获知我们按下了cell的按钮呢&#xff1f;毫无…

Google 开源技术protobuf 简介与样例

今天来介绍一下“Protocol Buffers ”&#xff08;以下简称protobuf&#xff09;这个玩意儿。本来俺在构思“生产者/消费者模式 ”系列的下一个帖子&#xff1a;关于生产者和消费者之间的数据传输格式。由于里面扯到了protobuf&#xff0c;想想干脆单独开一个帖子算了。 ★prot…

VUE全局导航守卫、 请求、响应拦截器 的设置

文件设置参考地址&#xff1a;https://gitee.com/wang_yu5201314/headlines__news/tree/master/%E9%A1%B9%E7%9B%AE%E6%BA%90%E7%A0%81%E6%96%87%E4%BB%B6/src 文件夹 Router 文件夹 index.js 中设置 全局导航守卫 文件 mian.js 中设置 请求、响应拦截器 设置 请求、响应拦截器…

JRE System Library和 Referenced Libraries 的区别和来源

JRE System Library 安装jdk后&#xff0c;会有个目录叫做jrejre目录是核心类库&#xff0c;目录中装的是类库文件jre System Library顾名思义就表示系统类库文件 Referenced Libraries referenced libraries放的是你引用的jar包&#xff0c;这个不需要自己创建的&#xff0c;你…