0%

介绍

引用 MDN 的介绍:

IndexedDB 是一个事务型数据库系统,类似于基于 SQL 的 RDBMS。 然而不同的是它使用固定列表,IndexedDB是一个基于JavaScript的面向对象的数据库。 IndexedDB允许您存储和检索用键索引的对象; 可以存储structured clone algorithm支持的任何对象。 您只需要指定数据库模式,打开与数据库的连接,然后检索和更新一系列事务中的数据。

IndexedDB 是一种低级API,用于客户端存储大量结构化数据(包括, 文件/ blobs)。该API使用索引来实现对该数据的高性能搜索。虽然 Web Storage 对于存储较少量的数据很有用,但对于存储更大量的结构化数据来说,这种方法不太有用。IndexedDB 提供了一个解决方案。

区别

这是我整理的 WebStorage 和 indexedDB 的之间区别,有问题的地方还请指出。

用法

1. 打开数据库

阅读全文 »

当我们在开发 React 项目中,第一次调用 ReactDOM.render 的时候都发生了什么呢?
今天就从源码角度来追踪一下这个问题(主要看流程, 而不纠结与细节)。

ReactDOMStackEntry

首先我们可以从 ReactDOM 的入口文件 ReactDOMStackEntry.js 中找到 render 方法。可以看到,render 方法是 ReactMount 组件提供的。

var ReactDOMStack = {
findDOMNode: findDOMNode,
render: ReactMount.render,
unmountComponentAtNode: ReactMount.unmountComponentAtNode,
version: ReactVersion,

/* eslint-disable camelcase */
unstable_batchedUpdates: ReactGenericBatching.batchedUpdates,
unstable_renderSubtreeIntoContainer: ReactMount.renderSubtreeIntoContainer,
/* eslint-enable camelcase */

__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: {
// For TapEventPlugin which is popular in open source
EventPluginHub: require('EventPluginHub'),
// Used by test-utils
EventPluginRegistry: require('EventPluginRegistry'),
EventPropagators: require('EventPropagators'),
ReactControlledComponent: require('ReactControlledComponent'),
ReactDOMComponentTree,
ReactDOMEventListener: require('ReactDOMEventListener'),
ReactUpdates: ReactUpdates,
},
};

ReactMount.render

render: function(nextElement, container, callback) {
return ReactMount._renderSubtreeIntoContainer(
null,
nextElement,
container,
callback,
);
},

又调到了 _renderSubtreeIntoContainer 方法, 这个方法核心内容如下:

阅读全文 »

这个模块的代码非常简单,短短十几行。

var ReactElement = require('ReactElement');

var invariant = require('fbjs/lib/invariant');
function onlyChild(children) {
invariant(
ReactElement.isValidElement(children),
'React.Children.only expected to receive a single React element child.',
);
return children;
}

module.exports = onlyChild;

就是判断传入的 children 是不是一个合法的 React 元素,否则就抛错出来。判断的逻辑就在 ReactElement 模块里面:

ReactElement.isValidElement = function(object) {
return (
typeof object === 'object' &&
object !== null &&
object.$$typeof === REACT_ELEMENT_TYPE
);
};
阅读全文 »

ReactElement

这个模块定义了 React 元素的行为和方法,首先看 ReactElement 函数:

ReactElement

var ReactElement = function(type, key, ref, self, source, owner, props) {
var element = {
// This tag allow 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__) {
// The validation flag is currently mutative. We put it on
// an external backing store so that we can freeze the whole object.
// This can be replaced with a WeakMap once they are implemented in
// commonly used development environments.
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 里面的内容,其他部分很简单,定义了一个 React 元素应有属性。包括: type, key, ref, self, source, owner, props.

阅读全文 »

引入的模块

var ReactElement = require('ReactElement');

var emptyFunction = require('fbjs/lib/emptyFunction');
var invariant = require('fbjs/lib/invariant');

我们来看一下 ReactElement 模块,其他两个都是工具函数,不用关心。

Export 的对象

var ReactChildren = {
forEach: forEachChildren,
map: mapChildren,
count: countChildren,
toArray: toArray,
};

module.exports = ReactChildren;

依次来看一下这个四个 API

forEach

function forEachChildren(children, forEachFunc, forEachContext) {
if (children == null) {
return children;
}
var traverseContext = getPooledTraverseContext(
null,
null,
forEachFunc,
forEachContext,
);
traverseAllChildren(children, forEachSingleChild, traverseContext);
releaseTraverseContext(traverseContext);
}

入参: children, forEachFunc, forEachContext.
首先通过 getPooledTraverseContext 拿到一个遍历的上下文对象 traverseContext,然后调用 traverseAllChildren 方法来遍历所有传入 children 的后代节点。
最后释放当前的 traverseContext.

阅读全文 »