Gutenberg本体のコードを読む上で、とっかかりになりそうな部分をメモ。
registerBlockType()
https://github.com/WordPress/gutenberg/blob/master/blocks/api/registration.js#L51
色々バリデーションが書いてあって、最終的には
return blocks[ name ] = settings;
でローカル変数 blocks
に第1引数(name)をキー、第2引数(settings)を値として追加する。
setAttributes()
BlockListBlock
というブロックで定義されている。
https://github.com/WordPress/gutenberg/blob/master/editor/components/block-list/block.js#L184-L203
setAttributes( attributes ) {
const { block, onChange } = this.props;
const type = getBlockType( block.name );
onChange( block.uid, attributes );
const metaAttributes = reduce( attributes, ( result, value, key ) => {
if ( get( type, [ 'attributes', key, 'source' ] ) === 'meta' ) {
result[ type.attributes[ key ].meta ] = value;
}
return result;
}, {} );
if ( size( metaAttributes ) ) {
this.props.onMetaChange( {
...this.props.meta,
...metaAttributes,
} );
}
}
ここではBlockListBlock
がpropsに持っているonChange()
メソッドが重要。
https://github.com/WordPress/gutenberg/blob/master/editor/components/block-list/block.js#L465
onChange( uid, attributes ) {
dispatch( updateBlockAttributes( uid, attributes ) );
},
onChangeはStoreをdispatchする。属性の設定処理の本体はreducerにある。
https://github.com/WordPress/gutenberg/blob/master/editor/store/reducer.js#L129
case 'UPDATE_BLOCK_ATTRIBUTES':
// Ignore updates if block isn't known
if ( ! state[ action.uid ] ) {
return state;
}
// Consider as updates only changed values
const nextAttributes = reduce( action.attributes, ( result, value, key ) => {
if ( value !== result[ key ] ) {
// Avoid mutating original block by creating shallow clone
if ( result === state[ action.uid ].attributes ) {
result = { ...result };
}
result[ key ] = value;
}
return result;
}, state[ action.uid ].attributes );
// Skip update if nothing has been changed. The reference will
// match the original block if `reduce` had no changed values.
if ( nextAttributes === state[ action.uid ].attributes ) {
return state;
}
// Otherwise merge attributes into state
return {
...state,
[ action.uid ]: {
...state[ action.uid ],
attributes: nextAttributes,
},
};
Gutenbergのコードを読むなら、ある程度Flux(およびその実装であるRedux)については理解しておく必要がある。