〇、看前准备

1.自行clone react最新代码

2.自行搭建一个能跑react的test项目

一、看表面:那些插件 如何解析JSX

有如下一段代码:

// ---- hearder.jsx 组件
import React,{Component} from 'react'; export default (props)=>(
<h1 ref="h1">我是header.{props.kk}</h1>
); // ---- Home.jsx 页面级组件
import React,{Component} from 'react';
import Header from '../components/header';
class Home extends Component {
constructor(props){
super(props);
}
componentWillMount(){
console.log('willMount');
}
render(){
let {name} = this.props;
console.log(this);
return (
<div ref="home">
<Header kk="jsx"/>
<div>主页</div>
<div>
<p>哈哈哈哈</p>
</div>
</div>
)
}
} export default Home; // React入口文件 app.js import ReactDOM from 'react-dom';
import React from 'react';
import Home from './page/home';
let abc = ReactDOM.render(
<div>
<Home name="home"/>
</div>
,
document.getElementById('app')
);

发现每一个出现jsx语法的地方都要出现import React from 'react';

其实react 的引入就是为了将解析完的jsx 能有createElement方法被执行,在浏览器里打开控制台,我们发现代码被整成了这个样子:

// ----header.jsx

var _default = function _default(props) {
return _react2.default.createElement(
"h1",
{ ref: "h1" },
"\u6211\u662Fheader.",
props.kk
);
}; exports.default = _default; // home.jsx var Home = function (_Component) {
_inherits(Home, _Component); function Home(props) {
_classCallCheck(this, Home); return _possibleConstructorReturn(this, (Home.__proto__ || Object.getPrototypeOf(Home)).call(this, props));
} _createClass(Home, [{
key: 'componentWillMount',
value: function componentWillMount() {
console.log('willMount');
}
}, {
key: 'render',
value: function render() {
var name = this.props.name; console.log(this);
return _react2.default.createElement(
'div',
{ ref: 'home' },
_react2.default.createElement(_header2.default, { kk: 'js' }),
_react2.default.createElement(
'div',
null,
'\u4E3B\u9875'
),
_react2.default.createElement(
'div',
null,
_react2.default.createElement(
'p',
null,
'\u54C8\u54C8\u54C8\u54C8'
)
)
);
}
}, {
key: '__reactstandin__regenerateByEval',
// @ts-ignore
value: function __reactstandin__regenerateByEval(key, code) {
// @ts-ignore
this[key] = eval(code);
}
}]); return Home;
}(_react.Component); var _default = Home;
exports.default = _default; // app.js _reactDom2.default.render(_react2.default.createElement(
'div',
null,
_react2.default.createElement(_home2.default, { name: 'home' })
), document.getElementById('app'));

二、为啥外面非得包一个

我们知道我们在写react的时候,不管你用的是webpack也好还是fis3 、gulp 或者直接撸js+html,都需要引入jsx语法转义插件,这些插件把jsx语法的字符转变成了我们在浏览器看到的样子。

每个组件都有render方法,每个render方法都会return一个React.createElement 执行后的东西

我将header.jsx改为

export default (props)=>(
<h1 ref="h1">我是header.{props.kk}</h1>
<p>hahaha</p>
);

当我们在jsx中写若干个标签而外面不包东西的话,以babel-loader为例,丫会提示:

SyntaxError: Adjacent JSX elements must be wrapped in an enclosing tag

我们通过追溯得到jsx语法的解析其实是在 baabel-core/node_modules/babylon/index.js 中解析的

我们注释掉出现的报错信息,因能力有限水平一般且对babylon有任何了解,所以只通过粗浅的改动以下代码让webpack能够编译通过(当然js语法肯定是不成功的)

Tokenizer.prototype.readRegexp = function readRegexp() {
......
for (;;) {
// if (this.state.pos >= this.input.length) this.raise(start, "Unterminated regular expression");
var ch = this.input.charAt(this.state.pos);
if (lineBreak.test(ch)) {
// this.raise(start, "Unterminated regular expression");
break; // 增加一个break
}
..............
return this.finishToken(types.regexp, {
pattern: content,
flags: mods
});
}; pp$9.jsxParseElementAt = function (startPos, startLoc) {
............
// if (this.match(types.relational) && this.state.value === "<") {
// this.raise(this.state.start, "Adjacent JSX elements must be wrapped in an enclosing tag");
// }
return this.finishNode(node, "JSXElement");
};

编译出来的代码结构如下:

var _default = function _default(props) {
return _react2.default.createElement(
"h1",
{ ref: "h1" },
"\u6211\u662Fheader.",
props.kk
) < p > hahaha < /p>/;
}; exports.default = _default;

可见babylon在解析jsx的时候会默认将第一个闭合标签 return 出去,就算第二个咱们改babylon改的再成功能正确解析p标签这个jsx,岂不是return 两个东西出去了,函数里怎么可能有两个return呢!

所以react的所有组件必须放在一个闭合标签里(当然了16 版本也可以是一个数组,不用放在闭合标签里,以后再说)。

看到

SyntaxError: Adjacent JSX elements must be wrapped in an enclosing tag

SyntaxError: Unterminated regular expression

的报错

一定要检查自己的jsx是否在一个闭合标签中,同时是否语法正确

React 16 源码瞎几把解读 【前戏】 为啥组件外面非得包个标签?的更多相关文章

  1. React 16 源码瞎几把解读 【二】 react组件的解析过程

    一.一个真正的react组件编译后长啥样? 我们瞎几把解读了react 虚拟dom对象是怎么生成的,生成了一个什么样的解构.一个react组件不光由若干个这些嵌套的虚拟dom对象组成,还包括各种生命周 ...

  2. React 16 源码瞎几把解读 【三 点 一】 把react组件对象弄到dom中去(矛头指向fiber,fiber不解读这个过程也不知道)

    一.ReactDOM.render 都干啥了 我们在写react的时候,最后一步肯定是 ReactDOM.render( <div> <Home name="home&qu ...

  3. React 16 源码瞎几把解读 【一】 从jsx到一个react 虚拟dom对象

    一.jsx变createElement 每一个用jsx语法书写的react组件最后都会变成 react.createElement(...)这一坨东西, // 转变前 export default ( ...

  4. React 16 源码瞎几把解读 【三 点 二】 react中的fiberRoot

    〇.先来看看常用的常量 NoWork = 0 noTimeout = undefined HostRoot = 3 NoContext = 0b000; AsyncMode = 0b001; Stri ...

  5. React Fiber源码分析 (介绍)

    写了分析源码的文章后, 总觉得缺少了什么, 在这里补一个整体的总结,输出个人的理解~ 文章的系列标题为Fiber源码分析, 那么什么是Fiber,官方给出的解释是: React Fiber是对核心算法 ...

  6. 《React Native 精解与实战》书籍连载「React Native 源码学习方法及其他资源」

    此系列文章将整合我的 React 视频教程与 React Native 书籍中的精华部分,给大家介绍 React Native 源码学习方法及其他资源. 最后的章节给大家介绍 React Native ...

  7. React的React.createContext()源码解析(四)

    一.产生context原因 从父组件直接传值到孙子组件,而不必一层一层的通过props进行传值,相比较以前的那种传值更加的方便.简介. 二.context的两种实现方式 1.老版本(React16.x ...

  8. React的React.createElement源码解析(一)

    一.什么是jsx  jsx是语法糖  它是js和html的组合使用  二.为什么用jsx语法 高效定义模版,编译后使用 不会带来性能问题 三.jsx语法转化为js语法  jsx语法通过babel转化为 ...

  9. vue 源码详解(二): 组件生命周期初始化、事件系统初始化

    vue 源码详解(二): 组件生命周期初始化.事件系统初始化 上一篇文章 生成 Vue 实例前的准备工作 讲解了实例化前的准备工作, 接下来我们继续看, 我们调用 new Vue() 的时候, 其内部 ...

随机推荐

  1. 【数据库】SQL两表之间:根据一个表的字段更新另一个表的字段

    1. 写法轻松,更新效率高:update table1 set field1=table2.field1,field2=table2.field2from table2where table1.id= ...

  2. Android四大组件之Intent(续)

  3. Day22-1-知识回顾

    1. 知识点概要 --Session --CSRF --Model操作 --Form验证(ModelForm) --中间件 --缓存 2.知识回顾 2.1客户端请求及服务器端返回,都包含请求头和bod ...

  4. What Is The Promiscuous Mode

    What Is The Promiscuous Mode? Some Network Interface Cards (NICs) may not allow network traffic afte ...

  5. CF1093F Vasya and Array DP

    题面 题面 \(\Delta\)题面有点问题,应该是数列中没有长度大于等于\(len\)的连续数字才是合法的. 题解 设\(f[i][j]\)表示DP到\(i\)位,以\(j\)为结尾的方案数, \( ...

  6. 【TopCoder10697】RabbitNumbering

    [TopCoder10697]RabbitNumbering 题面 Vjudge 给定\(n\)个数,每个数的范围是\([1,ai]\),求所有数都不同的方案数. 题解 把这个直接当做一个套路来用 对 ...

  7. redis安全性 添加访问密码

    设置客户端连接访问redis服务器必须进行身份验证. vi打开编辑redis配置文件:[root@martin etc]# vi /usr/local/redis/etc/redis.conf 在约1 ...

  8. (转载)Cobalt Strike tutorial下针对CVE-2017-0199利用

    CVE-2017-0199利用OLE对象嵌入Word / RTF文档的方式,使得可以在没有用户交互的情况下执行其内容.OLE由许多不同的程序支持,OLE通常用于使在另一个程序中可用的程序中创建的内容. ...

  9. 64位win10系统无法安装.Net framework3.5的两种解决方法【转】

    近日有网友反映在windows10_64位系统电脑上安装Net framework3.5,操作时总失败,怎么办呢?小编下面就介绍win10 64位系统无法安装Net framework3.5的两种解决 ...

  10. flex的使用实例

    之前的随笔从阮一峰老师那里学到了flex的基本用法及作用,现在来把flex具体运用到实例中,看看flex的弹性布局效果. 1.  flex设置元素垂直居中对齐 在之前的一篇文章中记载过如何垂直居中对齐 ...