补充一个知识点:
组件props的React内部操作
一个充满疑惑的问题, 组件之间的通信
-
假如props从super()中删掉, 可以正常显示
-
明明没有保存props, 却有值, 为什么会有值? => 看源码
思路, 源码通篇读过, 找到对应的包, 源码不是很熟悉, 要对官方文档熟悉, API REFERENCE -> Test Renderer(告诉你这个包是干嘛的)
-
JSX转化成React.createElement
- 分析源码, 做过一个赋值
- 为什么要这样做? React的骚操作, 担心有些人忘记在super()中给props做个保存, 保证一定有保存
组件间的通信
子组件传递父组件
父组件通过props把属性传递给子组件
默认值
子组件发生了某一个事件, 传递到父组件
-
某些情况, 我们也需要子组件向父组件传递消息:
-
父组件里面定义一个函数, 把这个函数传递给子组件, 子组件里产生一个事件, 调用函数, 父组件中的函数会被回调
提一个需求, 把Button封装到一个子组件里面
Chrome插件 React Developer Tools
- 注意this绑定! 箭头函数或bind(this)
组建通信案例练习
- TabControl, 封装成一个组件
- 数据的传递, 子组件传递事件到父组件
- 非常综合的案例
-
正规的目录结构做一个组织, App.js, 真实开发中搞一个文件夹
- titiles要是一个数组类型,
import PropTypes from 'prop-types';
- 先对外面的东西Flex布局, 水平方向做一个等分
- React中加样式, style.css文件, 在里面写样式
- webpack从入口开始, 看依赖了哪些东西, 打包进去
- 引用图结构中
- 默认选中第一个, 需要一个记录, 点击的时候变成红色
- 动态的添加className
- 监听div的点击, 代码长的话需要做一个代码组织优化, 换行
- 下划线, span包裹item添加内边距, 底部添加一个边框
- 浮动的出现是为了做图文环绕, 不是为了做布局
.tab-control {
display: flex;
height: 44px;
line-height: 44px;
}
.tab-item {
flex: 1;
text-align: center;
}
.tab-item span {
padding: 5px 8px;
}
.tab-item.active {
color: red;
}
.
- 父组件根据子组件的选中操作, 显示文本
- 先来到父组件里面
- 记录的东西, 有两种方式Index、Title, 选择哪种方式根据业务需求, 用到index的场景多不多
this.state = {
currentIndex: 0,
currentTitle: "新款"
}
再补充一个知识点
- Vue里面有一个插槽的功能, React里面没有这个概念
- 真实开发中有这种需求, React实现slot
- m.jd.com 导航的功能, 各种导航不一样, 多个页面, 多个导航, 有相似, 但是不一样
- 开发中怎么封装这些组件? Vue预留一个插槽, 之后可以插入组件, React里面没有这个概念
-
React是非常灵活的, 根本就不需要插槽, jsx -> 数据 -> 子组件
双标签里面可以跟很多东西
body默认有个内边距, 要去除
nav-item, 做抽取
开发中比较推荐的办法, 一个东西不需要在乎顺序, 如果有多个, Vue命名插槽, React索引值顺序不能乱, 另一个方案重新封装一下 NavBar2.js
-
单标签, jsx可以做数据传递给下层的组件, 精准的拿到每一个属性
-
报了一个警告, link警告
加一个路径, 消除警告
<a href="/#">ccc</a>
css权重大的覆盖权重小的
Vue模板的限制, React非常的灵活
跨组件之间的通信, props
- 一层一层的传, 比较麻烦
- 跨组件的嵌套, Profile组件, 函数式组件也可以, 看有没有内部状态需要维护
- $ * 4快速生成
- 昵称之类的东西, 以后可能会发生变化 -> 放在state里面
- 一层一层的传递有很大的一个缺陷, 中间层用不到属性, 才能传到下一层, Profile中间层用不到不应该写这些东西
-
有一个语法, Vue里面也有, 属性展开attributes spread? 文档 -> 高级指引 -> 深入JSX -> 属性展开
- 跟展开对象不一样, 变成了一个一个的属性, JSX语法
- 即使做了一个简化, 但耦合性还是太多 -> Context
Context应用场景
-
非父子组件数据的共享:
Context相关API
- React.createContext
- 创建一个需要共享的Context对象
- 如果一个组件订阅了Context, 那么这个组件会从离自身最近的那个匹配的Provider中读取到当前的context值;
-
defaultValue是组件在顶层查找过程中没有找到对应的Provider, 那么就是用默认值
-
- Class.contextType
-
到底指向哪一个东西
-
- 创建Context对象
// 创建Context对象
const UserContext = React.createContext({
nickname: "aaa",
level: -1
})]
- 类组件有一个属性, context
- 源码里有大量的验证代码, 看的时候可以先跳过去
-
Profile如果放到了外面, 还能展示, 不过展示的是默认数据
- 可以搞一个共享的context.js文件
考虑另一个情况, context函数式组件
- Flutter借鉴了React
- 特殊的语法{}
function ProfileHeader() {
return (
<UserContext.Consumer>
{
value => {
<div>
<h2>用户昵称: {value.nickname}</h2>
<h2>用户等级: {value.level}</h2>
</div>
}
}
</UserContext.Consumer>
)
}
多个Context
-
再来做一层嵌套
- 真实开发中使用Redux, hooks中会有更简单的办法, 重点难点