场景:
实现组件切换
实现:
定义初始数据:
isLogin=false,即默认没有登陆;当点击按钮时将isLogin设置为true。用来切换函数组件。
state = { isLogin: false } //false 未登录
return (
<div>
<div>123<div/>
</div>
)
书写函数组件:
两个函数组件:登录与欢迎。对应login与Welcome
function Login() {
return (
<div>
<h1>请先登录</h1>
<button>登录</button>
</div>
)
}
function Welcome() {
return (
<div>
<h1>欢迎,您已登录</h1>
<button >退出</button>
</div>
)
}
于是可以将render的页面修改为:
return (
<div>
<Login/> //默认为登陆页面
</div>
)
使用isLogin实现组件切换,首先定义两个函数修改isLogin状态。
handleLogin = async () => {
this.setState({ isLogin: true })
}
handleLogout = async () => {
this.setState({ isLogin: false })
}
然后将修改状态的true,false的两个函数分别传入到函数组件中
return (
<div>
{
this.state.isLogin ? <Welcome logout={this.handleLogout} /> : <Login login={this.handleLogin} />
}
</div>
)
在两个函数组件中通过props实现点击后切换组件
function Login(props) {
const {login} = props
return (
<div>
<h1>请先登录</h1>
<button onClick={login}>登录</button>
</div>
)
}
function Welcome(props) {
const {logout} = props
return (
<div>
<h1>欢迎,您已登录</h1>
<button onClick={logout}>退出</button>
</div>
)
}
完成。
大致流程总结:
分析:状态 页面 事件
定义状态(state)
定义页面 (两个函数组件)
状态和页面关系 (true,false分别对应两个组件)
定义改变状态事件 (状态在哪 定义事件就在哪里,点击切换true/false的两个方法)
button 和 事件关系(组件实例上定义) 事件传递(props)
就是这样。
增加功能,登陆后显示简单的标题,
显示,如下:
两个页面通过点击按钮自由交换。
开始编写:
首先写好标题内容的数据存放在数组中,当页面渲染完之后调用,放于钩子函数中。
state = { isLogin: false, posts: [] } //未登录,初始数据为空
在函数组件中传入post的初始数据:
<Welcome logout={this.handleLogout} posts={this.state.posts} />
当render完之后自动调用钩子函数,改变posts的状态内容。
componentDidMount() {
//获取文章数据
const posts = [{
id: 1, title: 'title1', content: 'welcome to habin heilongjiang'
}, {
id: 2, title: 'title2', content: 'welcome to habin heilongjiang'
}, {
id: 3, title: 'title2', content: 'welcome to habin heilongjiang'
}]
//同步组件状态👇
this.setState({ posts: posts })
}
写好文章内容的函数组件:
function Posts() {
return (
<div>
内容
</div>
)
}
将post组件放置欢迎页面中一同显示:并将post数据传给Post函数组件方便调用
function Welcome(props) {
const { logout, posts } = props
return (
<div>
<h1>欢迎,您已登录</h1>
<button onClick={logout}>退出</button>
{/*文章内容列表*/}
<Posts posts={posts} />
</div>
)
}
现在已经接收到post数据了,于是可以开始排版Post函数组件了。通过props接收到post数组。
将内容又分为:左侧边栏sidbar组件与中间正文content组件。先利用数组中的map遍历出每一项内容
function Posts(props) {
const {posts} = props
const contents = posts.map(item => {
return (
<Content key={item.id} title={item.title} content={item.content} />
)
})
const sidbar = <ListContainer data={posts} />
return (
<div>
<div>{sidbar}</div>
<div>{contents}</div>
</div>
)
}
已经遍历出数据,下一步将数据通过props在函数组件中使用。
function Content(props) {
const { title, content } = props
return (
<div >
<h3>{title}</h3>
<span>{content}</span>
</div>
)
}
内容组件书写完毕👆。
下面书写左侧边栏组件。
function ListContainer(props) {
let { data } = props
let listItems = data.map(item=><li key={item.id}><span>{item.title}</span></li>) // jsx => {变量}
return (
<ul>
{listItems}
</ul>
)
}
观察上面代码,在第三行的索引key被放置在li中,是会报错的,以为li本身就是单独的一小只,加上key是多此一举,例如将每个li再次封装成一个组件。
解决方法:将几个li再次封装成函数组件,通过map遍历数组得到每一条数据,实现显示,实现在组件中添加key。
于是更改为:
function ListContainer(props) {
let { data } = props
let listItems = data.map(item => <Title key={item.id} title={item.title} />) // jsx => {变量}
return (
<ul>
{listItems}
</ul>
)
}
Title组件用li去接收遍历数组得到的每一条数据。
function Title(props) {
const { title, id } = props
return (
<li ><span>{title}</span></li>
)
}
以上:完成一个简易的登录、退出,以及显示数据的过程。
知识点涉及:
我认为该案例只是在反复的巩固如何书写jsx语法,如何让抽离出函数组件,如何让在类组件中写状态值,并且修改状态值,以及如何通过props去传递数据 进而接收数据的过程。是前几篇文章知识点的综合。
额外的知识点只是以前学过的数组中map方法,遍历得到每一条item内容。
今天的自己真棒。