React笔记之入门-React初体验(2)

前置简介

上一节: https://juejin.im/post/6866966785032355848/

本章旨在通过react实现一个小功能,为了演示效果就先使用cdn的方式进行引入react。

创建项目

请通过上节说的cdn方式自行创建一个如下图红框中的文件结构目录下来。

index.css

.red {
    color: red;
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="index.css">
</head>
<body>
    <div id="root">
    </div>
    <script src="https://cdn.bootcdn.net/ajax/libs/react/16.9.0/umd/react.development.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/react-dom/16.9.0/umd/react-dom.development.js"></script>
    <script src="index.js"></script>
</body>
</html>

index.js

// 获取React对象
const React = window.React
// 获取ReactDOM对象
const ReactDOM = window.ReactDOM
// 获取id是root的元素
const root = document.querySelector("#root")
// 定义一个n变量
let n = 0
// 使用React创建一个div对象,class属性是red,内容是变量n 以及  一个button元素,点击事件是让n这个变量+1
const App = React.createElement('div', {className: 'red'}
    ,
    [n , React.createElement('button', {
        onClick: () => {
            n += 1
        }
    }, '+1')])
// 将App这个div对象放到root元素里面去
ReactDOM.render(App, root)

React的元素创建各种使用基本都是在js中完成的,可以看一下上面的js以及每行的注释,

完成上面的步骤之后,我们刷新界面就会出现下面的效果:

根据js里的写法,我们点击网页中的button就会让左边的数字加1,对不对,

但是事实我们点击其实没有任何效果,这是为啥呢?

首先我们看下 ReactDOM.render(App, root) 这行代码,这行代码是进行元素的渲染,

只调用了一次,在我们点击button事件的时候并没有重新渲染,所以这个是其中问题之一,

下面我们可以在点击时间里重新渲染一下这个元素:

....
// 使用React创建一个div对象,class属性是red,内容是变量n 以及  一个button元素,点击事件是让n这个变量+1 , 并且重新渲染App元素
const App = React.createElement('div', {className: 'red'}
    ,
    [n , React.createElement('button', {
        onClick: () => {
            n += 1
            // 重新渲染
            ReactDOM.render(App, root)
        }
    }, '+1')])
....

但是这样真的可以了嘛? 我们尝试一下后,发现还是没有任何反应,这是为什么呢?

我们看一下 App 这个元素的赋值操作,n在代码执行的时候 就已经当时的值 0 存放到 App这个元素中了,

所以事后我们再怎么改变n的值,也和App这个元素没有关系了,

所以在onclick重新渲染是对的,已经生效了的,只是我们的App元素里放的内容一直都是0,所以看起来没效果,

下面我们将App这个元素改成一个函数,让每次调用的时候都重新获取一下最新n的值看看,

// 获取React对象
const React = window.React
// 获取ReactDOM对象
const ReactDOM = window.ReactDOM
// 获取id是root的元素
const root = document.querySelector("#root")
// 定义一个n变量
let n = 0
// 使用React创建一个div对象,class属性是red,内容是变量n 以及  一个button元素,点击事件是让n这个变量+1 , 并且重新渲染App元素
const App = () => React.createElement('div', {className: 'red'}
    ,
    [n , React.createElement('button', {
        onClick: () => {
            n += 1
            // 重新渲染
            ReactDOM.render(App(), root)
        }
    }, '+1')])
// 将App这个div对象放到root元素里面去
ReactDOM.render(App(), root)

最后我们将App改为一个箭头函数之后,每次重新渲染,+1的效果就出来啦。

总结:React的很多坑的地方,其实是需要用到JS的基础知识的,它并没有像vue一样,帮我们做了自动渲染等等机制,我们要用原生JS的基础知识思考,来思考React。

回顾JS的基础知识

let i 
for (i=0; i<6; i++) {
	setTimeout(()=>{console.log(i)},1000)
}

上述代码的执行结果:一秒钟后输出6个6,因为函数执行时遇到外部变量会去读取其最新的值。

这里解释一下setTimeout,setTimeout会将你要执行的代码放入到类似一个队列里面去,它告诉浏览器,就在多少毫秒后尽快执行这个代码逻辑,

所以上面的for循环里的setTimeout即使你设置的是0毫秒,他也要等到for循环执行完毕之后,才会执行,这时候获取到的最新值,自然是6。

如果打印出0,1,2,3…这种值呢?

for (let i=0; i<6; i++) {
	setTimeout(()=>{console.log(i)},1000)
}

将let放入到for循环内即可,这是一个作用域的问题,let标记的变量i,作用域只存在于 {}括号内,

事后每个setTimeout查找作用域i的时候,找到都是当时的那个i,也就是0,1,2,3这种,

读者可以自己实验一下。

还有一种方式,就是使用立即执行函数:

for(var i=0; i<6; i++) {
 !function(j) {
 	setTimeout(console.log(j),1000)
 }(i)
}

这种立即执行函数,将i传递给方法里的形参j,j就保存了当时i的值,所以在最后输出的时候,也是当时的值。

So,说这个基础知识,其实是想映射的是,既然函数是可以获取到外部变量最新的值得,所以在上面的index.js里,我们渲染元素的时候,

将App改为了一个函数,每次调用这个函数,都会获取到n的最新值,所以这正是我们想要的结果,

这里总结一下,函数可类比为延迟执行的代码,只有当你调用它的时候,它才会真正执行内部的逻辑。

最终总结

总结一下我们这里接触到的React知识

  1. React元素

    1.1 createElement的返回值 element 可以代表一个div

    1.2 element并不是真正的div(DOM对象)

    1.3 我们一般称element为虚拟DOM对象

  2. ()=>React元素

    2.1 返回element的函数,也可以代表一个div

    2.2 这个函数可以多次执行,每次得到最新的虚拟div

    2.3 React会对比两个虚拟div,找出不同,局部更新视图,找不同的技术称为 DOM Diff算法,什么叫找不同呢,意思就是我们每次点击按钮重新调用渲染的时候,只会更新n元素的值,button按钮因为没有变动不会被重新渲染。

下一节:https://juejin.im/post/6867027735979261959

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值