用了react一年,很多东西用的也是迷迷糊糊的,这里报了来自于拉钩教育的修言老师的课程来系统的学习一下react。下面算是我对于课程的笔记记录以及自我的一点理解吧。在此作出记录以及分享。如果想要一起加入学习之路的可以 点击这里 或者下面评论里说出来~ 共勉!
本节主要围绕JSX这三大问题来讲JSX:
1. JSX 的本质是什么,它和 JS 之间到底是什么关系?
2. 为什么要用 JSX?不用会有什么后果?
3. JSX 背后的功能模块是什么,这个功能模块都做了哪些事情?
首先:
- JSX 的本质是什么,它和 JS 之间到底是什么关系?
JSX的本质是遵循以一定逻辑结构的 JS形式来描述的DOM节点。它其实就是JS,你可以把它理解为一个对象,然后react准备了一套规则(或者说标准(毕竟如果没有规则不好辨认敌友呀是吧))。是遵循reactDom描述的一个对象。就好像下面这个对象是我用来描述张三的一个对象。我知道这个规则是干嘛的,最后用我自己的东西把我的描述给"画"出来:
cosnt obj={
name:"张三",
val:"zs",
item:{
...balabala
}
}
- 为什么要用 JSX?不用会有什么后果?
JSX解析出来是React.createElement方法(不信去babel官网吧JSX复制上去看看)。如果用React.createElement方法的话,代码会很冗长,也不像JSX那样长的像html,不利于维护。
- JSX 背后的功能模块是什么,这个功能模块都做了哪些事情?
一个平常的JSX:
<div>我是一个JSX</div>
解析出来是:
React.createElement("div", null, "\u6211\u662F\u4E00\u4E2AJSX");
然后React.createElement又做了什么呢?
function createElement(type, config, children) { var propName;
//提取保留名称
var props = {};
var key = null;
var ref = null;
var self = null;
var source = null;
//标签的属性不为空时 说明标签有属性值 特殊处理:把key和ref赋值给单独的变量
if (config != null) {
//有合理的ref
if (hasValidRef(config)) {
ref = config.ref;
}
//有合理的key
if (hasValidKey(config)) {
key = '' + config.key;
}
self = config.__self === undefined ? null : config.__self;
source = config.__source === undefined ? null : config.__source;
//config中剩余属性,且不是原生属性(RESERVED_PROPS对象的属性),则添加到新props对象中
for (propName in config) {
if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {
props[propName] = config[propName]; //config去除key/ref 其他属性的放到props对象中
}
}
}
// Children can be more than one argument, and those are transferred onto
// the newly allocated props object.
//子元素数量(第三个参数以及之后参数都是子元素 兄弟节点)
var childrenLength = arguments.length - 2;
if (childrenLength === 1) {
props.children = children;
} else if (childrenLength > 1) {
var childArray = Array(childrenLength); //声明一个数组
//依次将children push到数组中
for (var i = 0; i < childrenLength; i++) {
childArray[i] = arguments[i + 2];
}
{
//冻结array 返回原来的childArray且不能被修改 防止有人修改库的核心对象 冻结对象大大提高性能
if (Object.freeze) {
Object.freeze(childArray);
}
}
props.children = childArray; //父组件内部通过this.props.children获取子组件的值
}
//为子组件设置默认值 一般针对的是组件 //class com extends React.component 则com.defaultProps获取当前组件自己的静态方法
if (type && type.defaultProps) { //如果当前组件中有默认的defaultProps则把当前组件的默认内容 定义到defaultProps中
var defaultProps = type.defaultProps;
for (propName in defaultProps) {
if (props[propName] === undefined) { //如果父组件中对应的值为undefinde 则把默认值赋值赋值给props当作props的属性
props[propName] = defaultProps[propName];
}
}
}
{
//一旦ref或者key存在
if (key || ref) {
//如果type是组件的话
var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;
if (key) {
defineKeyPropWarningGetter(props, displayName);
}
if (ref) {
defineRefPropWarningGetter(props, displayName);
}
}
}
//props:1.config的属性值 2.children的属性(字符串/数组)3.default的属性值
return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);
}
注:此部分源码转载于 https://www.cnblogs.com/sunxiaopei/p/12205447.html
实际上就是整理了下传进来的参数,最后反回调用一个 ReactElement 方法,并把之前整理的参数传进去。
那ReactElement 方法又做了什么呢?下面是该方法的源码:
const ReactElement = function(type, key, ref, self, source, owner, props) {
const element = {
// This tag allows us to uniquely identify this as a React Element
$$typeof: REACT_ELEMENT_TYPE,
// Built-in properties that belong on the element
type: type,
key: key,
ref: ref,
props: props,
// Record the component responsible for creating this element.
_owner: owner,
};
if (__DEV__) {
element._store = {};
// To make comparing ReactElements easier for testing purposes, we make
// the validation flag non-enumerable (where possible, which should
// include every environment we run tests in), so the test framework
// ignores it.
Object.defineProperty(element._store, 'validated', {
configurable: false,
enumerable: false,
writable: true,
value: false,
});
// self and source are DEV only properties.
Object.defineProperty(element, '_self', {
configurable: false,
enumerable: false,
writable: false,
value: self,
});
// Two elements created in two different places should be considered
// equal for testing purposes and therefore we hide it from enumeration.
Object.defineProperty(element, '_source', {
configurable: false,
enumerable: false,
writable: false,
value: source,
});
if (Object.freeze) {
Object.freeze(element.props);
Object.freeze(element);
}
}
return element;
};
__DEV__状态先不管的会话,其实也就是把传进来的数据组装好再返回去就是了。
再由上层方法继续往上反。最后的结果是传进去的JSX返回了一个用JS描述的html结构。这,就是虚拟DOM。
done.