React samples 1|学习笔记

简介: 快速学习React samples 1

开发者学堂课程【高校精品课-上海交通大学 -互联网应用开发技术:React samples 1】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址:https://developer.aliyun.com/learning/course/76/detail/15746


React samples 1

我们来看一下他给的这个类似的代码,就是它定义了一个类,

class test extends Component {

constructor(props){

super(props);

this.statei= {

liked:false

};

}

handleClick(event){

this.setstate({liked:!this.state.liked});

}

render() {

var text = this.state.liked ?'喜欢’:'不喜欢';

return(

<div onClick={this.handleClick}>

你<b>{text}</b>我。点我切换状态。

</div>

);

}

export default test;

它在构造器里面,有一个state,是like:false,这个state的指向非常明确,就是指的当前要创建的text的实例,即Component的一个实例。

单纯的讲这个对象,它的state里面有一个叫like的false,下面有它定义的成员函数,就是handle click,意思是如果有人点击handle click,会传递一个实践进入,即把当前这个对象属于text实例,因为handleclick是这个类的一个成员,属于这个实例,就在这个实例上去调setstate,相当于把这个like的属性和状态给反一下,就原来是false,给它改成true,否则的话改成反过来,切换一下,底下是render就像画这个test,要把它渲染出来,前面不需要进行操作,下端可以看到,它会是分离的div,div上就会有一个点击的动作,在这一片空间内那个div所在这空间的一侧点击。

调this handle click函数,一旦在div这个地方click一下,去去handle click函数,这个函数就会把当前的状态改写掉,这个程序就是类似书上的例子,如果直接将它改写成一个类的话,去执行会出现这类似的问题,查一下这个问题,他就会报这个错误,即TypeError:Cannot read property‘setState’of underfine这个setState,没有定义过,虽然听起来很奇怪,但是意思就是在这里面setState没有定义过,代码中的this就是当前这个test的setState,这里面有一个问题,当把这个函数放到这里的时候,javascript里面的这个this的作用就是,如果你写的这个是普通函数,它这个意思是动态绑定,看一下这个过程,它是在div里面调了,这个this handle click这里没问题,这个this是动态绑定,它肯定绑不是这个当前的steState,它极有可能绑的就是这个div,所以他会爆出这个div上是没有steState的。处理这个方法的方式有两个方法,第一个就是我们上节课看到举的例子里面也有这类似的一句话,

第一种解决方法是:手动绑定this。将

constructor(props) {

super(props);

this.state = {

liked:false

};

}

改为 

constructor(props){

super(props);

this.state = {

liked: false

};

this.handleClick = this.handleClick.bind(this);//手动绑定

}

在构造器里面,这个this一定指的是当前这个对象,在这里面把他绑死,就是handleclick这个方法里面的this,就是绑着当前的这个对象。

所以一种方法是你用这种方式,但这么做比较麻烦。一个最简单的方法就是用箭头函数。箭头函数实际上我们看他像个箭头,本质上来说,他就是个拉姆达表达式,其他的语言里面也有这个特性。这个简便写法相当于定义了一个匿名的函数,函数没有名字,他有个参数列表,这就源括号里的参数列表,这像个关键字,后面是他要执行的东西,它执行的就是你要写的,就像上面写的函数题一样,把你要的执行代码写进去,那这时候这个我们看到的这个。

在这上面它就调用这个setState,现在我们来看这个this,他就不是动态绑定了。因为箭头函数的这个这个字,它是静态绑定的,也就是说这个博客底下还讲了很多其他的话,但最重要的是在最后他讲了这样一句话。就是这个拉姆达表达式,他不是动态绑定这个作用力。他不是根据这个程序运行的位置来确定它的值是什么,它是一个静态的,把这个方式做出来的,它会根据你当时在进行定义的时候的那个位置确定。换句话说,其实在写代码的时候,你在写到这个地方的时候,它在加载的时候就已经给他绑定了。就像我们在构建类似于构造器一样的,在创建对象的时候直接绑死他也是一样,当时在声明的时候,我就已经绑死他,跟当前这个对象绑定就不会在。

这里面这个类似游戏动态去绑定,它属于哪个对象。这就是用箭头函数来进行处理的一个原因,关于箭头函数的使用本身。在这边,英文的网站是这个,JavaScript: Arrow Functions for Beginners他写的比较全面,那针对他有中文的一个翻译,上节课的内容中只是给大家讲了一下this指代如果不用箭头函数会出错,现在看这边的解释就知道,如果不用建造函数的类似的绑定是不确定的,就不是动态的去绑定它,取决于你在调用他的那一刻,上面写的这个东西。

其实调用这个handleclick的时候,当时他的商家跟环境怎么样。那在这里,它指向的应该就是这个div,所以才会报这个错,把它变成这种函数,它在声明的时候尽快去绑定,就不会出现这个错了。那今天这个PPT要介绍的就是类似于图书的一个展示的东西,如下图:

Book

Author

Language

Published

Sales

Dream of the Red Chamber

Cao Xueqin

Chinese

1754-1791

100 million

She: A History of Adventure

H.Rider Haggard

English

1887

100 million

The Hobbit

J.R. R. Tolkien

English

1937

100 million

And Then There Were None

Agatha Christie

English

1939

100 million

Le Petit Prince(The Little Prince)

Antoine de Saint-Exupéry

French

1943

140 million

The Lord of the Rings

J.R.R.Tolkien

English

1954-1955

150 million

Harry Potter and the Philosopher's Stone

J. K. Rowling

English

1997

107 million

那是通过创建一个静态的一个react的APP来开发这个系统的。在开发的时候会碰上,创建了一个系统,创建这个工程之后,需要等很长时间。下载的比较慢,因为他在下载这边,我们所看到的node modules里面的东西,需要依赖到的所有东西,他在下载,,你的工程里的东西,你可以看到全部是自己的要用的东西,包括一个静态页面,包括用到的一些图,还有自己写的,其他东西都没有,全部都需要去通过下载得到,现在速度慢也没有解决办法。在这个root底下画一个标签,剩下的事情就是我们自己来开发,自己可以组织自己的代码,因为这个例子比较简单,没有再去把它划分,用这个例子大家可以看到,其实这里面有两个js。

一个是系统,在创建这个工程组成默认的代理,还有一个是为了出现这样的效果。这个按钮的效果,我用了这个书上的例子写的这个js,两个js都用的,所以我们在作业里面就是说,如果多个js,你该怎么去处理的处理方法。如果想实现上表中的功能,要先定义两个常量,一个是表头

Book

Author

Language

Published

Sales

起常量名叫header,在二维数组中写死,放入对应表格五列中的值,

后面的例子就会改写这些例子,会从后台抓取,现在的页面实际上是从后面的后台中动态抓取的,如果不用现在的页面或者构架,需要每次自己生成页面,是不可取的。

class Excel extends React.Component {

constructor(props){

super(props);

this.state ={

data: this.props.initialData,

soctby: null,

descending: false,

edit: null, // [row index, cell index],

search: false,

preSearchData: null,

};

}

这个例子里面有一个构造器,这个构造器中有外面传递进来的属性,在绘制时传递的属性即下段程序中的header和data,这就是上述代码在创建excel时所需要的参数,会把所有参数放入props,把initialdata赋给data,data就是将来在表格页面呈现的数据,可以在表格页面search一旦做search就会过滤页面中的数据,data是会变化的,所以它是个state,而不是props,副节点传递进来的不能直接去改变数值,只能是data赋值给state去修改。

function App() {

return (

ReactDOM.render(

React.createElement(Excel, props:{

headers: headers,

initialData: data

}),

document.getElementById( elementld: "root")

));}

表格的排序,在某一列这个属性也在不断变化,升序和降序也会因为用户的点击发生变化,也要被设为state,然后底下edit这个是什么意思呢?

它是我们在任何一个位置上,如果双击它,你就会看到它可以变成进入可编辑状态是一个输入框了,可以看到,你可以继续写完之后点回车,它就改写掉,那eidt指明的是到底哪一个单元可以进行修改。那它实际上它的值应该是一个他的行索引和列索引,就是行索引和真正这个行里面的这个index列索引,所以他应该是个二维数组,那他的状态肯定也在发生变化,有一点不同地方就不同。

然后这个search再说,我到底这边要不要去显示,刚才我们看到search这一行,很显然他也是个标志位,它在不断的发生变化。然后我们看到在search的时候,如果我真输进去的东西,比如输如lord,它只有这个lord出,这个指环王出现了,其他的没有了,就不出现。但是如果我把它点掉就不search了,它就会恢复出原来的样子,所以我们要有一个中间变量。

到底存之前是个啥状态,可能会疑惑不search不就是最初的数据嘛,但是还有一点是我们还可以去排序,就是在search的时候,那个数据还是那些数据,但它顺序可能有点变化,有没有专门用了一个变量来存储他,这些东西看起来都是在当前这个操作过程当中,他只可能会发生变化的东西,所以我们把它变成了一个state,就不是当前的这个,这个构建的一个props。我们去修改,然后要注意一个问题,我们现在没有这个例子,里面没有做更复杂的操作,所以它就属于这类的。

sort =(e) => {

let column =e.target.cellIndex;

let data = this.state.data.slice();

letdescending=this.state.sortby===column&& !this .state.descending

data.sort(compareFn:function(a:number,b:number){

return descending

?(a[column]<b[column]?1:-1)

:(a[column] >b[column]?1:-1);

});

this.setstate( state:{

data: data,

sortby: column,

descending: descending,

});

};

这段代码是在做排序,排序是在某一列升序或者降序,是一种实践,target.cell是系统封装的程序,e.target.cellIndex是在系统中点击的值,在系统内谁点击事件给你封装过来,这个e实际上是点击完以后有个实践,这个实践会给你传递过来。

那么如果要是说这个sort,它得到了这个事件之后,他就要先去知道你在谁上面在进行这个点击,那就得到了你在哪一列上点击,所以就表示在哪一列上。

slice这个函数是在说,我要把当前的这一个数组给他复制出来,一份赋给这个叫做data的一个局部变量,注意这个data和前面我们这里定义的,它不是一回事儿,这个data是在sort这个函数里面定义的,所以他只在sort这个函数里面有效,这个是state里的一个成员,那现在我们就得到了所有的数据,然后我们来看一看之前这个soft有没有排序。

如果他排序的之前就排序过,并且就是当前这一例。那么你在上面做一下点击的话。就意味着我要对这个排序,要么是他原来是大家看这里是降序,我再点一下它变成升序,再点一下就变成降序,所以呢,要看一下,那你原来是不是就在这个上头,去进行过设置,并且你这个原来是降序或者升序,这个结果作为这一次排序。他升序或者降序的一个依据,如果说原来不是在这一类上排的,这一条就不成立,他是false那它默认值就是false。

我们按升序排,你在一个没有点过的另外一列上,在当前这一列上再排序,在另外一个点,它默认就是让升序。如果你原来就在这一列上点的,并且原来就已经排过了,就把它取消,说明原来是降序,现在变升序,再降序升序,不是在一列上排,然后底下说把这个数据给sort一下,Sort是集合类,所谓集合类就是数组啊,列表啊,site,mab这些东西它的一个统称sort,就意味着他可以去把整个这个集合类里的所有元素去排个序。排序的时候可以用你给定的排序的函数来排序,那么我们给了一个排序的函数,就假设要传递A,B,两个值进去,那么我们要看你的这个升序还是降序的,通过代码来实现,而这个a和b是指的在data里面所有的元素,两两之间在比较中,一个是a一个是b。

取的在哪一列上去进行操作,把data里面每两行都拿出来进行比较的时候,出去取他们在排序的这一列上的这个值,他们进行比较,然后根据升序或降序的定义去判断到底是大于还是等于,这是个三元操作符,三元操作符,大家在C++或者Java里面都用过,就说他为true的时候就选上面,然后他为false就选下面,然后这个表达式里面他们又是一个三元操作,再判断两个,在讨论这一列上到底谁大谁小,那么处理完之后,这个数据就按照你想要的逻辑做了一个排序。那排序完了之后,其实这个页面是不会重绘的,那我们上节课说过触发页面重绘的唯一的就是用this.setstate。

就是你要去重绘要重新设置它的状态,设置状态的时候,这个数据这时候是指的是这个data,这个变量,然后sortbank就指的是一点的那一列,然后这个降序还是升序的,就是我们刚刚处理过的降序升序这个东西。这个setstate之后,这三个状态发生变化,那么我们知道一旦发生变化,他要触发render这个动作。

render =()=>{

return(

<div>

{this.renderToolbar()}

{this.renderTable()}

</div>

);};

就会去render ,render上面的工具条儿和底下的这个表。所以他就重复一次,重复一次就得到了我们想要的结果。这个重绘是的动作,这就是sort的逻辑。

接下来看这个show editor。

showEditor =(e) => {

this.setState( state: {

edit:{

row:parseInt(e.target.dataset.row, radix: 10), cell:e.target.cellIndex,

});};

在这个地方随便的双击就会有一个事件发生,会传递给你。做的事情就是说editor要让那个状态挨着状态,在表示,你当前要绘制哪一个,就是要去修改哪一个单元格的内容,因为它是一个数组,包含了它的行号和列号,那所以在show editor里面可以把这个状态给它改一下,就是改掉他的行和列它们的值,分别给改写的。

第一个是说我要拿到e,我们刚才说的是那个事件,事件标示点击的位置,现在的位置是table的表格,我们要在dataset里面取row,row可以解析dataset在哪一行做了动作,

后面数字10的意思是十进制,这里我们没有什么特殊要求按照十进制转换即可。即可得出在操作时,操作位置的行和列。

接下来看保存

save = (e)=>{

e.preventDefault();

let input = e.target.firstChild;

let data = this.state.data.slice();

datal[this.state.edit.row][this.state.edit.cell] = input.value; this.setstate( state:{

edit: null,

data: data,

});};};

首先按照正常情况这是一个input,input在回车之后一般有默认动作提交之类,接下来要获取target的firstchild,firstchild即input文本的数据,接下来要将之前确定的要改变行列的值告知input,这样可以将input的值将data中的替换掉,接下来调setstate重绘,输入回车,edit变为空,用替换掉的data代替data,这就是save做的动作。

toggleSearch = () => {

if(this.state.search) {

this.setstate( state:{

data:this.preSearchData,

search: false,

});

this.preSearchData = null;

} else {

this.preSearchData =this.state.data;

this.setstate( state:{

search: true,

});}};

Search做切换,这个函数的作用,判断这search空间的位置,要把search的东西保存起来,把search的标记变成true,如果已经在search状态,在表格页面点击,表格的内容将恢复到保存下来的状态,把search记成false,把中间变量记成空。

真正要做search的代码

search=(e)=> {

let needle = e.target.value.toLowerCase();

if(!needle) {

this.setState( state: {data: this.preSearchData});

return;

}

let idx = e.target.dataset.idx;

let searchdata =this.preSearchData.filter(function (row:T) {

return row[idx].toString().toLowerCase().index0f(needle) >-1

});

this.setstate( state: {data: searchdata});

};

首先需要知道输入的值并转为小写,如果输入的·东西被删掉,就恢复成search之前的状态,如果不是,马上return,如果输入东西,首先明确是在哪一列输入的,然后过滤没有search的所有原始数据,

过滤之后把它放入变量,用变量更新状态,过滤掉的数据不会出现,其余数据被保留,保留的数据赋给setstate,页面重绘,其中的逻辑是因为过滤当中的每一行,每一行将内容转化为字符串用来观察有没有needle,观察needle是否是字符串的子字符串,如果是将会返回该字符串在起始字符串的所有,如果不是就返回-1,只要大于-1就表示有这个东西就会被保留,否则不会被保留。

所以fuctum表示的是某一行是否被留下,true将被留下,false将不被留下,但是其中的问题就是,只在单独的一列搜索,并不能做联合的搜索,出来的结果在行上并没有很好的联合。

download(format,ev){

let contents = format === 'json'

?JsoN.stringify(this.state.data)

:this.state.data.reduce(function (result, row){

return result

+ row.reduce(function (rowresult, cell, idx) {

return rowresult

+’”’

+ cell.replace(/"/g,"…"')+::!

+’”’

+(idx<row.length -1? ',':'');

},'')

+ "\n";

},'');

let URL = window.URL II window.webkituRl;

let blob =new Blob(blobParts:[contentsl,options:{type:'text/' ev.target.href = URL.create0bjectURL(blob); ev.target.download ='data.' + format;

};

观察字符串是否为jasn,如果是jasn,直接用stringtry这个函数,如果不是将字符串转化为jasn字符串。组了一个字符串,把它放入contents,contents的内容变成flob中,二进制大对象,要把二进制大对象写出到data.jasn或者cs文件。

试一下可以发现,打开就是上面的表格。用文本编辑器把它打开,cs本质上是用逗号隔开的一行一行的数据,每个字段用双引号引起来。Reduce是对data里面所有的元素都做一下处理,处理完的结果是一个然后返回,返回在result。

Row是对每一行的元素进行处理,每一行要在每一列里进行操作,所以要有双引号,加cell里面做的全局替换,把转移字符恢复,如果是最后一列,什么不加,是最后一列要加都好,每一行做完要回车。

接下来是绘制工作。

Setstate工作的时候会触动render

renderToolbar = () => {

return (

<div className="toolbar">

<button onClick={this.toggleSearch}>Search</button>

<aonClick={this.download.bind(this,'json')} href="data.json">Export JSON</ a>

<a onClick={this.download.bind(this, 'csv')}

href="data.csv">Export CSV</ a>

</div>

);}:

Render分为工具栏和table,工具栏绘制的时候只需要绘制search,jasn,导出jasn,导出csv,csv search,就这三个按钮,前两个做成按钮,最后一个做成超链接。

无论怎样,在上面点击时都会有一个动作,这个动作要和刚刚的函数进行绑定,一带search就是切换search这个函数,就可以重绘之前函数状态,其他的两个都是在调download,他俩download的format一样,一个是jsan一个是csv。

下面是table,画table就是render search就是判断是否要文本框,当前状态不需要search,就什么都不画,如果当前状态需要search,要多加一行,无论在哪里操作都要调用search函数,判断在哪里做search,map是对表头,每一行字符都要生成一个td,这个td里面是input,input类型是text可以输入文本的,data/index,是在定义一个属性,输入data/的名字,就是data。输入文本框,文本框的内容属性被定义为idx。

就等于在处理哪一列,就是第几列的值,都是会导致属性变成idx。行需要row出来,列也是,后面有idx。这就可以把这一排画出来。最复杂的就说把rander table画出来。

相关文章
|
6月前
|
资源调度 前端开发 JavaScript
React的测试:使用Jest和React Testing Library进行深入探索
【4月更文挑战第25天】本文探讨了使用Jest和React Testing Library进行React测试的方法。Jest是Facebook推出的JavaScript测试框架,适合React测试,提供全面的API和功能。React Testing Library侧重于组件行为,提倡按用户交互方式测试。安装这两个工具后,可通过编写测试用例(如模拟点击事件)来验证组件功能。运行Jest可执行测试并显示结果。此外,还介绍了高级测试技巧和模拟功能,强调了它们对于确保组件正确性、提升开发效率的重要性。
|
19天前
|
资源调度 前端开发 JavaScript
React 测试库 React Testing Library
【10月更文挑战第22天】本文介绍了 React Testing Library 的基本概念和使用方法,包括安装、基本用法、常见问题及解决方法。通过代码案例详细解释了如何测试 React 组件,帮助开发者提高应用质量和稳定性。
30 0
|
5月前
|
前端开发 JavaScript
vue的v-model、v-if、v-for用react语法实现
vue的v-model、v-if、v-for用react语法实现
|
前端开发 JavaScript
react开发插件-ES7 React/Redux/GraphQL/React-Native snippets(二)
react开发插件-ES7 React/Redux/GraphQL/React-Native snippets
116 0
|
SQL 前端开发 JavaScript
react开发插件-ES7 React/Redux/GraphQL/React-Native snippets(一)
react开发插件-ES7 React/Redux/GraphQL/React-Native snippets
270 0
dva和Umi中两个小用法
dva和Umi中两个小用法
211 0
|
存储 缓存 JavaScript
React实战精讲(React_TS/API)
TS_React:使用泛型来改善类型 TS_React:Hook类型化 TS_React:类型化事件回调 React API
123 0
React实战精讲(React_TS/API)
|
前端开发 数据安全/隐私保护
React高阶组件(Higher-Order Components)及其应用
React高阶组件(Higher-Order Components)及其应用
87 0
|
移动开发 前端开发 JavaScript
Vite 2.x + React + Zarm + Less + React Router v6 + Axios + flexible.js 搭建前端 H5 开发环境
Vite 2.x + React + Zarm + Less + React Router v6 + Axios + flexible.js 搭建前端 H5 开发环境
429 0
Vite 2.x + React + Zarm + Less + React Router v6 + Axios + flexible.js 搭建前端 H5 开发环境
|
移动开发 JSON 前端开发
Vite 2.x + React + Zarm + Less + React Router v6 + Axios + flexible.js 搭建前端 H5 开发环境2
Vite 2.x + React + Zarm + Less + React Router v6 + Axios + flexible.js 搭建前端 H5 开发环境
286 0
Vite 2.x + React + Zarm + Less + React Router v6 + Axios + flexible.js 搭建前端 H5 开发环境2