React基础学习(一)

news/2024/11/19 14:49:34/

一、虚拟DOM和真实DOM

<script type="text/babel"> // 此处一定要写babel!!!!!!!// 1. 创建虚拟DOM// const VDOM = <h1 id="title">Hello, React!</h1> // 此处一定不要写引号 因为这不是字符串!!!!!!!const VDOM = ( // 如果有多层嵌套,使用jsx更加方便快捷 更为符合开发方式<h1 id="title"><span>Hello, React!</span></h1>)// 2. 渲染虚拟DOM 参数:虚拟DOM、容器ReactDOM.render(VDOM, document.getElementById('box'))// ----------------------------------------------------const TDOM = document.getElementById('test')console.log('虚拟DOM', VDOM) // Objectconsole.log('真实DOM', TDOM) // <div id="test"></div>debugger;</script>
关于虚拟DOM:
  1. 本质是Object对象(一般对象)
  2. 虚拟DOM比较“轻”(属性和方法少),真实DOM比较“重”(属性和方法多),因为虚拟DOM是React内部在用,无需真实DOM上那么多属性
  3. 虚拟DOM最终都会被React转换为真实DOM,最终呈现在页面。

二、jsx的语法规则

  1. 定义虚拟DOM时,不要用引号
  2. 标签中混入js表达式时,使用{}
  3. 样式的类名指定不能用class,要使用className,因为要与es6中的关键字类(class)做区分
  4. 内联样式,要使用{{key:value}}的形式去写,外层{}表示里边的内容为js,内层{}表示对象
  5. 只能有一个根标签
  6. 标签必须闭合
  7. 标签首字母:
    1)首字母小写开头,则将该标签转为html中的同名元素,若html中无与之对应的同名元素,则报红色警告
    2)首字母大写开头,react会去渲染对应的组件,若组件没有定义,则报错。
<script type="text/babel">const myId = 'container'const myData = 'Hello, React'// 创建虚拟DOMconst VDOM = (<div><h1 className="title" id={myId}><span style={{color: 'white'}}>{myData}</span></h1> <h1 className="title" id={myId+'2'}><span style={{color: 'white'}}>{myData}</span></h1> <good>222</good>   // 无与之对应的html标签 会报警告// <Good>333</Good>   // 报错 首字母大写表示使用的是组件 Good组件未定义</div>)// 渲染虚拟DOM到页面ReactDOM.render(VDOM, document.getElementById('box'))</script>

三、组件实例的三大属性

  1. state
<script type="text/babel">// 1.创建一个组件class Weather extends React.Component {// 构造器调用几次?------一次constructor(props) {console.log('constructor')super(props)// 初始化状态// 给state添加属性 就需要在组件实例初始化时赋值this.state = {isHot: false, wind: '微风'}// 解决changeWeather中this指向问题this.changeWeather = this.changeWeather.bind(this)// 【this指向问题解释】实际上也可以这么写:// 右边的this.changeWeather.bind(this):this指向Weather实例对象,改变(bind)原型对象上changeWeather方法的this指向为 Weather实例对象// 左边的this.demo:this指向Weather实例对象,表示初始化给实例对象一个名为demo的方法// 把右边的表达式赋值给左边// this.demo = this.changeWeather.bind(this)}// render调用几次?----1+n次,1是初始化调用1次,n是状态更新的次数render() {console.log('render')// 读取状态let {isHot, wind} = this.state// console.log(this) // this指向的是 Weather 组件实例,state是组件实例的属性 // react中的点击事件为onClick(原生为onclick)// 此处不使用changeWeather()的原因是:页面一加载时就执行了onClick={changeWeather},相当于直接执行了changeWeather函数体中的内容,所以使用changeWeather 相当于是把changeWeather函数赋值给onClick事件return <h1 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '寒冷'}{wind}</h1>// 【this指向问题解释】实际上也可以这么写:// 调用的并不是原型对象上的changeWeather,而是初始化时实例对象上的名为demo的方法// return <h1 onClick={this.demo}>今天天气很{isHot ? '炎热' : '寒冷'}</h1>}// changeWeather调用几次?------点几次调几次changeWeather() {console.log('changeWeather')// changeWeather放在了 类Weather的原型对象 上,供实例使用// 由于changeWeather作为onClick的回调,所以不是通过实例调用的,是直接调用// 类中的方法默认开启了严格模式,所以changeWeather中的this指向为undefined// console.log(this)const isHot = this.state.isHot// 【严重注意】:状态必须要通过setState进行更新,且更新是合并(只更新setState中传入的属性),不是替换(setState中其他未传入的属性不会被删除)。this.setState({isHot: !isHot})// 【严重注意】:状态(state)不可直接更改,下面这行就是直接更改!!!// this.state.isHot = !isHot   // 这是错误的!!!}}// 2.渲染到页面ReactDOM.render(<Weather/>, document.getElementById('box'))</script>
简写方式
<script type="text/babel">// 1.创建一个组件class Weather extends React.Component {// 初始化状态// 给Weather的实例对象上直接添加state属性state = {isHot: false, wind: '微风'}render() {let {isHot, wind} = this.statereturn <h1 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '寒冷'}{wind}</h1>}// 自定义方法----使用赋值语句+箭头函数 替代bind方法changeWeather = () => {const isHot = this.state.isHotthis.setState({isHot: !isHot})}}// 2.渲染到页面ReactDOM.render(<Weather/>, document.getElementById('box'))</script>
  1. props
<script type="text/babel">// 创建组件class Person extends React.Component {render() {const {name, age, gender} = this.propsreturn (<ul><li>姓名:{name}</li><li>性别:{age}</li><li>年龄:{gender}</li></ul>)}}// 渲染组件到页面ReactDOM.render(<Person name="tom" age="28" gender="男"/>, document.getElementById('box1'))// ReactDOM.render(<Person name="daisy" age="20" gender="女"/>, document.getElementById('box2'))const p = {name: 'daisy', age: '21', gender: "女"}// ReactDOM.render(<Person name={p.name} age={p.age} gender={p.gender}/>, document.getElementById('box2'))// 下面这种写法(...p)是上面这种写法的语法糖,在组件中的{...p}---{}表示的是里边要写js语句了 并不是对象的意思// 在react和babel的共同作用下,是允许使用展开运算法展开一个对象(...p是被允许的)ReactDOM.render(<Person {...p}/>, document.getElementById('box2'))
</script>
简写方式
<script type="text/babel">// 创建组件class Person extends React.Component {// 对标签属性进行必要性以及类型限制static propTypes = {name: PropTypes.string.isRequired, // 限制name必传,且为string类型age: PropTypes.number, // 限制age为number类型gender: PropTypes.string, // 限制gender为string类型}// 指定标签属性默认值static defaultProps= {age: 10, // age默认为10gender: '男' // gender默认为男}render() {const {name, age, gender} = this.props// props是只读的// this.props.name = 'jerry'   // 会报错,因为props是只读的return (<ul><li>姓名:{name}</li><li>年龄:{age + 1}</li><li>性别:{gender}</li></ul>)}}// 渲染组件到页面ReactDOM.render(<Person name="tom"/>, document.getElementById('box1'))
</script>
函数式组件使用props
<script type="text/babel">// 创建组件function Person(props) {const {name, age, gender} = propsreturn (<ul><li>姓名:{name}</li><li>年龄:{age + 1}</li><li>性别:{gender}</li></ul>)}// 对标签属性进行必要性以及类型限制Person.propTypes = {name: PropTypes.string.isRequired, // 限制name必传,且为string类型age: PropTypes.number, // 限制age为number类型gender: PropTypes.string, // 限制gender为string类型}// 指定标签属性默认值Person.defaultProps= {age: 10, // age默认为10gender: '男' // gender默认为男}// 渲染组件到页面ReactDOM.render(<Person name="tom"/>, document.getElementById('box1'))</script>
  1. ref
<script type="text/babel">//创建组件class Demo extends React.Component{// React.createRef 调用后返回一个容器,该容器可以存储被ref所标识的节点,该容器是“专人专用”myRef = React.createRef()myRef2 = React.createRef()// 展示左侧数据showData = () => {alert(this.myRef.current.value)}// 展示右侧数据showData2 = () => {alert(this.myRef2.current.value)}render() {return (<div><input ref={this.myRef} type="text" placeholder="点击按钮提示数据" />&nbsp;<button onClick={this.showData}>点我提示左侧数据</button>&nbsp;<input ref={this.myRef2} type="text" placeholder="失去焦点提示数据" onBlur={this.showData2}/></div>)}}// 渲染组件到页面ReactDOM.render(<Demo/>, document.getElementById('box'))
</script>

四、事件处理

<script type="text/babel">//创建组件class Demo extends React.Component{// 创建ref容器myRef = React.createRef()myRef2 = React.createRef()// 展示左侧数据showData = () => {alert(this.myRef.current.value)}// 展示右侧数据showData2 = (event) => {alert(event.target.value)}render() {return (<div><input ref={this.myRef} type="text" placeholder="点击按钮提示数据" />&nbsp;<button onClick={this.showData}>点我提示左侧数据</button>&nbsp;<input type="text" placeholder="失去焦点提示数据" onBlur={this.showData2}/></div>)}}// 渲染组件到页面ReactDOM.render(<Demo/>, document.getElementById('box'))
</script>
事件处理总结:
  1. 通过onXxx属性指定事件处理函数(注意大小写)
    a)React使用的是自定义(合成)事件,而不是使用的原生DOM事件 ----为了更好的兼容性
    b)React中的事件是通过事件委托方式处理的(委托给组件最外层的元素) ---- 为了更高效
  2. 通过event.target得到发生事件的DOM元素对象 ---- 不要过度使用ref

五、组件的生命周期(详细代码在下一篇笔记)

旧版与新版对比图示:

react生命周期对比图

附:使用html学习React基础代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>demo</title>
</head>
<body><!-- 准备好一个容器 --><div id="box"></div><!-- 引入react核心库 --><script type="text/javascript" src="https://unpkg.com/react@16/umd/react.development.js"></script> <!-- 引入react扩展库 --><script type="text/javascript" src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script><!-- 引入babel,用于将jsx转换为js --><script type="text/javascript" src="https://unpkg.com/@babel/standalone/babel.min.js"></script><!-- 引入prop-types,用于对组件标签的限制 --><script type="text/javascript" src="../../../js/prop-types/prop-types.js"></script><script type="text/babel"></script></body>
</html>

http://www.ppmy.cn/news/50995.html

相关文章

移远通信笔试题

限时60分钟 1.下列关于栈叙述正确的是 A A) 栈顶元素最先能被删除 B&#xff09;栈顶元素最后才能被删除 C&#xff09;栈底元素永远不能被删除 D&#xff09;以上三种都不对 在栈中&#xff0c;最后被压入的元素总是在栈顶上方&#xff0c;而栈顶元素总是最先被弹出的元…

动态链接库的链接和运行

本文对动态链接库的链接和运行进行一个总结&#xff0c;为什么要分开说呢&#xff1f;因为链接通过生成可执行文件并不代表运行时能找到依赖的动态库。这与静态库是不一样的&#xff0c;因为静态库在编译完成后会库会编译到可执行程序中&#xff0c;但是动态链接库则不然&#…

OSCP-Fish(GlassFish、SynaMan、查看卸载软件、TotalAV提权)

目录 扫描 扫描 nmap 192.168.213.168 -sS -sV -p- -PnPORT STATE SERVICE VERSION 3389/tcp open ms-wbt-server? 3700/tcp open giop CORBA naming service 4848/tcp open http Sun GlassFish Open Source Edition 4…

网络作业7【计算机网络】

网络作业7【计算机网络】 前言推荐网络作业7一. 单选题&#xff08;共11题&#xff0c;33分&#xff09;二. 多选题&#xff08;共2题&#xff0c;10分&#xff09;三. 填空题&#xff08;共4题&#xff0c;30分&#xff09;四. 阅读理解&#xff08;共1题&#xff0c;27分&…

进程通信(同一主机)

1.概述 进程通信机制包括&#xff1a; 传统的UNIX进程间通信&#xff1a;无名管道、有名管道、信号 System V 进程间通信&#xff1a;消息队列、信号量、共享内存 2.管道通信 2.1无名管道 1.特点 &#xff08;1&#xff09;适用具有亲缘关系的进程 &#xff08;2&#x…

微信小程序php+vue 校园租房指南房屋租赁系统

本着诚信的原则&#xff0c;平台必须要掌握出租方必要的真实可信的信息&#xff0c;这样就可以防止欺诈事件的发生&#xff0c;事后也可以联系找到出租方。并且租金等各方面规范标准化&#xff0c;在这易租房诚信可信的平台让承租方与出租方充分有效对接&#xff0c;既方便了承…

JavaScript字符串操作

ASCII&#xff08;as key&#xff09; 字符集&#xff08;了解&#xff09; 我们都知道&#xff0c;计算机只能存储 0101010 这样的二进制数字&#xff0c;那么我们的 a ~ z / A ~ Z / $ / /… 之类的内容也有由二进制数字组成的 我们可以简单的理解为&#xff0c; a ~ z / …

Linux服务器出现503 服务不可用错误怎么办?

​  HTTP 503 服务不可用错误代码表示网站暂时不可用。无论您是网站访问者还是管理员&#xff0c;503 页面都很麻烦。尽管该错误表明存在服务器端问题&#xff0c;但对于访问者和网络管理员来说&#xff0c;有一些可能的解决方案。本文将解释Linux服务器出现503 服务不可用错…