React note3(map列表渲染&元素重新渲染&遍历对象&函数组件&class组件&props&模块化与组件化)

React列表渲染


在实际应用中, **数据展示** 是最基本的功能 。

1、React中使用 map() 进行列表的渲染。

react中遍历列表用 map ,记得给每一次添加的内容加上唯一标识,就是把key值插进去。 下面提出了三种方法,建议第二种,层次感高,代码复杂度低。

<div id="demoSky"></div>
<script type="text/babel">
    let arr = ["galen", "sen", "uu", "lll"]
    // 写法1
    // let com6 = (
    //     // jsx 的区域,写jsx加个()比较好 jsx中插变量用{}
    //     <div>
    //         {
    //             arr.map((item, index) => {
    //                 return (
    //                     <p key={index}>{item}</p>
    //                 )
    //             })
    //         }
    //     </div>
    // )
    // 写法2 先单独在外面计算完成,然后插入到jsx区域中
    let newhtml=arr.map((item,index)=>{
        return (
            <p key={index}>{item}</p>
        )
    })
    let com6 = (
        <div>
            {newhtml}
        </div>
    )
    // 写法3 将计算写在一个函数里面,再将函数引入到jsx区域
    // function list(){
    //     return arr.map((item,index)=>{
    //         return (
    //             <p key={index}>{item}</p>
    //         )
    //     })
    // }
    // let com6 = (
    //     <div>
    //         {list()}
    //     </div>
    // )
	// 写法4 用表格进行遍历 注意按照完整表格的html语法,thead tbody tfooter 建议写上
    let arr = [
        { name: "sky1", age: 18 },
        { name: "sky2", age: 15 },
        { name: "sky3", age: 12 },
        { name: "sky4", age: 19 },
    ]
    let newHtml = arr.map((item, index) => {
        return (
            <tr>
                <td>{item.name}</td>
                <td>{item.age}</td>
            </tr>
        )
    })
    let com7 = (
        <table>
            <tbody>
                {newHtml}
            </tbody>
        </table>
    )
    ReactDOM.render(com6, document.querySelector("#demoSky"))
</script>

在这里插入图片描述 在这里插入图片描述

2、-----Keys-----

Keys 可以在 DOM中某些元素被 增加/删除 时,帮助 React 识别哪些元素发生了变化。因此要给数组中的每一个元素赋予一个唯一的标识

一个元素的key最好是这个元素在列表中拥有的一个独一无二的字符串。
在这里插入图片描述
观察下面代码,看看能运行成功吗?在return换行了。
在这里插入图片描述
解决方式:用个()包裹代码即可。

3、其他遍历、循环方式

除了map也可以用其他循环方式,比如下面的写法:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我试着自己用for循环写了一下:

<!-- 其他遍历列表的方式 -->
<script type="text/babel">
    let arr = [
        { name: "sky1", age: 18 },
        { name: "sky2", age: 15 },
        { name: "sky3", age: 12 },
        { name: "sky4", age: 19 },
    ]
    // 写法5:基本for循环
    function funlist1(){
		let html=[];
		for(let i=0;i<arr.length;i++){
		    let list1=(
		        <tr key={i}>
		            <td>{arr[i].name}</td>
		            <td>{arr[i].age}</td>
		        </tr>
		    )
		    html.push(list1)
		}
		return html;
	}
    let comlist1=(
       <table>
        <tbody>
            {funlist1()}
            {console.log("0000000000000000")}
        </tbody>
       </table>
    )
    ReactDOM.render(comlist1,document.querySelector("#demoSky"))
</script>

React render重新渲染


我们通过一个小栗子:完成点击变色的demo,来看一下在react里面,render是怎么重新渲染的。

因为涉及到点击事件,所以我们先来看一下react中事件的触发机制。

1、事件

事件的添加,一定是小驼峰命名法(亲测,只能小驼峰)。

在react中,绑定使用的事件与传统js一样,不过有几注意项:
(1)事件名必须小驼峰式 。
(2)在调用方法的时候,不能使用传统的 " " 来引用方法,而要使用jsx中的 {} 来包裹方法 。
(3)调用的方法不能加(),否则,页面初始化时就会被自动调用 。

2、点击变色小demo

操作流程:
1、创建数据,然后使用map遍历;
2、给每一条遍历的数据加上一个点击事件;
3、创建一个变量iii来保存当前点击的下标;
4、创建style行内样式,三元运算,判断当前元素下边是否恒等于iii。如果恒等,说明用户点击的元素是应该设置样式的元素,反之则不设置;
5、出了一个bug,发现页面内容没有变化,原因是ReactDOM.render在页面初始化时已经执行一次了,再次点击时不会自动执行,所以我们需要在点击事件触发时重新执行一次rende方法。那么解决办法就是把render封装成一个函数,在每次点击的时候调用这个控制渲染的函数。

在这里插入图片描述
在这里插入图片描述
再次强调一下,封装好的函数至少调用一次,然后在点击触发事件时也要再次触发。

<!-- 一、render重复渲染 -->
<script type="text/babel">
    var iii = -1;//数组下标是0~无穷大,以用来保存用户具体保存的内容
    var arr = ["aaa", "bbb", "ccc", "ddd"];
    function con1() {
        let newList = arr.map((item, index) => {
            return (
                <h1 key={index} onClick={() => { iii = index; console.log(index, iii); renderDemo(); }} style={{ color: iii === index ? "#fd5b78" : "" }}>{item}</h1>
            )
        })
        // 每次点击,把下标赋值给iii,然后通过iii来判断是否改变样式
        // 不过,因为我们在初始化的时候,页面已经被渲染了,所以现在要考虑的一个问题是如何让render再次调用
        // 处理办法,我们可以把render封成一个函数,重复调用
        let com1 = (
            <div>{newList}</div>
        )
        return com1;
    }
    function renderDemo() {
        ReactDOM.render(con1(), document.querySelector("#demoSky"))
    }
    renderDemo();
</script>

在这里插入图片描述

3、用类来改变颜色

刚刚是用内联样式修改的,也可以那个用类也修改样式。

只要修改内联判断为className判断即可

style={{ color: iii === index ? "#fd5b78" : "" }}
改成
className={iii===index?"style_demp":""}

看一下效果:

在这里插入图片描述

对象的遍历


1、对象如何取值

两种方式 :1.用点的方式 ; 2.用[]来取值 。
在这里插入图片描述
也可以重新定义一个变量,被赋值对象里的某个key 。

var outval = "abc";
console.log(obj[outval] === obj["abc"]); //true

在实际项目中一般使用点,因为比较方便。但是如果key作为变量的话就不能使用点了,因为js会理解变量为对象的key值,造成混淆。

2、对象方法

object.keys() 返回一个数组类型,值是方法中对象的键(key)
在这里插入图片描述
Object.values() 返回一个数组类型,值是方法中对象的值(value)
在这里插入图片描述

Object.entries() 返回一个数组类型,值是方法中对象的键和值
在这里插入图片描述

3、遍历对象

<script>
    // 以键key返回,然后遍历
    Object.keys(obj).map((item,index)=>{
        // console.log(item);//键名
        console.log(obj[item]);//键值
    })
    
    // 以键值value返回,然后遍历
    Object.values(obj).map((item,index)=>{
        console.log(item)//键值
    })
    
    // 以键名、键值返回,然后遍历 用得不多
    Object.entries(obj).map((item,index)=>{
        // console.log(item);//键名+键值
        console.log(item[1]);//可以一数组索引的形式选择key或者value
    })
    
    // 其实上面的写法就相当于:
    [["name", "sky"], ["age", 18], ["sex", "女"]].map((item, index) => {
         console.log(item);//键名
    })
    
    /*其实吧,我发现,原理是一样的,只不过通过不同的对象方法返回不同的数组,
    然后用数组的 map() 方法进行遍历*/
</script>

在这里插入图片描述

4、React 遍历对象

之前学到的map是数组方法,那么如何在react中遍历对象呢?

<script type="text/babel">
    var obj={
        name:"sky",
        age:18,
        sex:"false",//直接写false,react不会渲染显示在页面上
    }
    function fun(){
        return Object.keys(obj).map((item,index)=>{
            return (
                <p key={index}>{obj[item]}</p>
            )
        })
    }
    let list=(
        <div>{fun()}</div>
    )
    ReactDOM.render(list,document.querySelector("#demoSky"))
</script>

在这里插入图片描述


面向组件编程


1、组件基本概念

组件是React中非常重要的概念。组件允许你将UI切分成一些独立的、可复用的部件,这样你就只需专注于构建每一个单独的部件。

组件,从概念上类似于 JavaScript 函数。它接受任意的入参(即 “props”),并返回用于描述页面展示内容的 React 元素。

官网:组件 & Props

react官方推荐的创建组件的方式有两种:函数组件 与 class 组件(常用)。

注意: 组件名称必须以大写字母开头

React 会将以小写字母开头的组件视为原生 DOM 标签。例如,<div /> 代表 HTML 的 div 标签,而<Welcome />则代表一个组件,并且需在作用域内使用 Welcome。

2、函数组件 / 无状态组件

函数的名字首字母必须大写,然后return一段jsx语法代码块。

function MyCom() {
    return jsx语法代码块
}

演示一下:

<div id="demoSky"></div>
<script type="text/babel">
	function MyCom() {
	    return (
	        <p>一个无状态组件</p>
	    )
	}
	let com = (
	    <div>
	        {/*组件的本质是标签*/} 
	        <MyCom></MyCom>
	    </div>
	)
	ReactDOM.render(com, document.querySelector("#demoSky"))
</script>

2.2 定义父子组件

通过创建多个组件来合成一个组件,即把组件的不同功能点进行分离。又可以说成组合组件、提取组件(详情请看官网)。

函数组件中的 父子组件 组件嵌套:

<div id="demoSky"></div>
<script type="text/babel">
	function Son(){
	    return <p>我是子组件</p>
	}
	function Father(){
	    return <div>我是父组件<Son/>子组件在父组件里</div>
	}
	let com2=(
	    <div>
	        <Father/>
	    </div>
	)
	ReactDOM.render(com2, document.querySelector("#demoSky"))
</script>

在这里插入图片描述

3、ES6 class类组件 / 有状态组件

首先注意类名的首字母必须大写 。

一个组件类必须要实现一个 render 方法。这个方法必须要返回一个jsx元素。必须要用一个外层的jsx元素把所有的内容包裹起来,如果要返回并列的多个元素,需要有个父元素进行包裹。

class MyCom extends React.Component{
    render(){
        return <div>我是组件</div>
    }
}

注意:原生 HTML 元素名以小写字母开头,而自定义的 React 类名以大写字母开头,比如 HelloMessage 不能写成 helloMessage。除此之外还需要注意组件类只能包含一个顶层标签,否则也会报错。

3.2类组件中的父子组件

<div id="demoSky"></div>
<script type="text/babel">
	class Son2 extends React.Component {
	    render() {
	        return (
	            <div>子类组件</div>
	        )
	    }
	}
	class Father2 extends React.Component {
	    render() {
	        return (
	            <div>父类组件<Son2/>子在父中</div>
	        )
	    }
	}
	ReactDOM.render(<Father2/>, document.querySelector("#demoSky"))
</script>

在这里插入图片描述

props


组件中通过Props传入参数。

props 是组件对外的接口。使用props就可以从外部向组件内部进行数据传递,完成父组件传值给子组件的过程。

注意:props对于使用它的组件来说,是只读的,一旦赋值不能修改。也就是说props的值是不可变的,只能在渲染的时候传入无法动态赋值

组件中无论是使用无状态组件,还是通过类组件声明,都决不能修改自身的 props 。

1、 props传入单个参数

当一个组件被注入props 值时,属性值来源于它的父级元素,从父级传递到子元素。

(1)无状态组件中使用props

组件在定义时就写入一个参数,然后在使用组件时传入一个值,在组建中通过props.title来展示这个值。

<div id="demoSky"></div>
<script type="text/babel">
	function MyCom3(props){
	    return (
	        <div>我是无状态组件中接收props传过来的参数
	            <p>{props.title}</p>
	
	        </div>
	    )
	}
	ReactDOM.render(<MyCom3 title="我是值"/>, document.querySelector("#demoSky"))
</script>

在这里插入图片描述

(2)类组件中使用props

在类组件中,接收props参数的方式是this.props.title。然后当然不管是哪种创建组件的方式,都可以将传入的值单独以变量形式展示,然后传入。

<div id="demoSky"></div>
<script type="text/babel">
	var name="变量---值值值";
	class MyCom4 extends React.Component{
	    render(){
	        return(
	            <div>
	                <p>类组件中接收props参数:this.props.xxx</p>
	                <p>{this.props.title}</p>
	            </div>
	        )
	    }
	}
	let com4=<MyCom4 title={name}/>
	ReactDOM.render(com4, document.querySelector("#demoSky"))
</script>

在这里插入图片描述

(3)组件props小练习

来个简单的小栗子,这里用的是函数组件方式,不过以后我们一般就不用这种方式了,用类组件比较多。

<div id="demoSky"></div>
<script type="text/babel">
	var arr = [
	    { title: "标题1", content: "内容简介1" },
	    { title: "标题2", content: "内容简介2" },
	    { title: "标题3", content: "内容简介3" },
	    { title: "标题4", content: "内容简介4" },
	    { title: "标题4", content: "内容简介4" },
	]
	// 根据数据动态生成内容 传多个数据
	function ListDemo(props) {
	    return (
	        <div>
	            <h1 style={{display:"inline"}}>{props.title}</h1>
	            <span>{props.content}</span>
	        </div>
	    )
	}
	var newArr=arr.map((item,index)=>{
	    return(
	        // 返回这个组件,然后每次传递一个值
	        <ListDemo key={index} title={item.title} content={item.content}/>
	        // 如果这种情况下一次性传递多个值呢 使用es6的扩展语法
	        // <ListDemo key={index} {...item}/>
	    )
	})
	// newArr变量
	ReactDOM.render(newArr, document.querySelector("#demoSky"))
</script>

在这里插入图片描述

2、props传入多个参数

用到了一个概念:扩展运算符。

扩展运算符(spread)是三个点(…)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。

…运算符主要用于数组和对象的一些操作。

参考:JS扩展运算符的用途
参考:数组的扩展 阮一峰
参考:Js es6中扩展运算符(…)

在参数较多的时候可以把Object类型进行传递:

在这里插入图片描述

我的练习—用简单的方式向组件内部传递多个参数:

<div id="demoSky"></div>
<script type="text/babel">
	function ListDemo2(props){
	    return(
	        <div>
	            <h1>{props.title}</h1>
	            <h1>{props.title2}</h1>
	            <h1>{props.title3}</h1>
	        </div>
	    )
	}
	// 如果希望往组件内部传递多个参数,我们可以把传递的数据定义成一个对象,
	// 但是注意对象的key必须和向内部传递的数据名一致
	let obj={
	    title:"内容1",
	    title2:"内容2",
	    title3:"内容3",
	    title4:"内容4",
	    title5:"内容5",
	    title6:"内容6",
	    title7:"内容7",
	}
	// 然后使用 ES6的扩展运算符... 向其内部进行传递obj
	let com5=<ListDemo2 {...obj} />
	ReactDOM.render(com5, document.querySelector("#demoSky"))
</script>

在这里插入图片描述


3、 Props默认值

(1)react版本 15x 以下的方法 ||

用管道符||来进行判断:

在这里插入图片描述


(2)react版本 16x 以下的方法 defaultProps

有些时候,我们需要设置一些默认属性, 在父级组件未向子级组件传递数据时, 填充默认值。

在这里插入图片描述

(3)我的尝试

先用 || 试一下。

<div id="demoSky"></div>
<script type="text/babel">
	function MyCom6(props){
	    props.text=props.text||"我是props默认值";
	    return(
	        <div>没有给组件传值--打印props默认值--
	           {props.text}为空。
	        </div>
	    )
	}
	ReactDOM.render(<MyCom6/>, document.querySelector("#demoSky"))
</script>

发现报错了。

在这里插入图片描述
为什么会报错?因为这种props默认值的写法:props.text=props.text||"我是props默认值";,在高版本中不适用,如果想使用下面的这种写法,需要引入react低版本15x以下的包

但我现在使用的react版本是16x,该怎么办呢? 用defaultProps这种写法。

高版本 16x及以下(兼容性) 在组件之外,定义props默认值。

MyCom6.defaultProps={
   text:'我是defaultProps设置的默认值'
}

完整代码如下:

<div id="demoSky"></div>
<script type="text/babel">
	function MyCom6(props){
	    return(
	        <div>没有给组件传值--打印props默认值--
	           {props.text}
	        </div>
	    )
	}
	MyCom6.defaultProps={
	    text:'我是defaultProps设置的默认值'
	}
	ReactDOM.render(<MyCom6/>, document.querySelector("#demoSky"))
</script>

在这里插入图片描述

(4)补充

类方式创建使用defaultPropos进行默认值设置两种方式:

在这里插入图片描述


4、props 验证

15.5之前Props 验证使用 propTypes,它可以保证我们在应用组件的时候可以正确的传递值。
在这里插入图片描述
所以,现在如果我们想要使用prop-types,就要引入prop-types 库。

安装:npm install --save prop-types

然后如果是本地模式的话,就需要引入这个资源包:

<script src="./node_modules/prop-types/prop-types.js"></script>

如果是脚手架模式的话,直接rcc可以帮我们直接引入,就无须我们手动引入了。

在这里插入图片描述
在这里插入图片描述


react-developer-tools 谷歌浏览器开发者调试工具


安装:
进入谷歌浏览器扩展程序中打开开发者模式,选择加载以解压的扩展程序,添加文件。
在这里插入图片描述


模块 / 模块化 / 组件 / 组件化


模块与模块化

模块:向外提供特定功能的js文件,提高js的复用率,简化编写,提高运行效率。
用来封装能够重复使用的逻辑代码块

模块化:当应用的js都是用js模块编写的,那么这个应用就是模块化应用。

组件与组件化

组件:用来实现页面局部功能效果的代码合集(html/css/js 组合技),简化复杂页面的编码,提高运行效率。
用来封装可以重复使用的ui代码块

组件化:当应用多使用组件的方式来完成,这个应用就是一个组件化应用。


总结


元素(element)是构成 React 应用的最小砖块。想要将一个 React 元素渲染到根 DOM 节点中,只需把元素和“根” DOM 节点一起传入 ReactDOM.render()。

与浏览器的 DOM 元素不同,React 元素是创建开销极小的普通对象。React DOM 会负责更新 DOM 来与 React 元素保持一致。

ReactDOM.render(com, document.querySelector("#demoSky"))

然后我发现,这个传入的元素的写法有很多种,你可以传入一个变量,也可以是一个有返回值的函数,也可以是一个组件…

本文所用到的element的种类:
com(jsx语法变量)    <MyCom4 title={name}/>    fun()     newArr(es6语法变量)

这节介绍了react中怎么遍历渲染列表以及如何通过render重新渲染;然后对对象的取值、方法、遍历有了加深版了解;然后知道了react中的组件以及父子组件、组件的合并使用、提取组件为更小的部分;然后是组件通过props传值,包括传入单个、多个参数,以及默认值的相关知识。


补充:let 箭头函数 函数组件

<div id="demoSky"></div>
<script type="text/babel">
    let Son = (props) => {
        return (
            <div>
                Son
                {
                    props.con.map((item, index) => {
                        return (
                            <p key={index}>{item.val}{item.key}</p>
                        )
                    })
                }
            </div>
        )
    }
    let Father = () => {
        let arr = [
            { val: "111", key: "--1--" },
            { val: "222", key: "--2--" },
            { val: "333", key: "--3--" },
            { val: "444", key: "--4--" },
        ]
        return (
            <div>
                Father
                <Son con={arr} />
            </div>
        )
    }

    ReactDOM.render(<Father />, document.querySelector("#demoSky"))
</script>

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值