先决条件

阅读本文需要您至少要掌握 React 、WordPress、JavaScript、PHP的相关知识,同时您如果进行实践需要您有Node相关环境。

研究对象

相信大家看过这款精美的 WordPress 主题,出自大佬:“solstice23”之手。这款主题是开源的,目前有1.6k的 Start 。作者是在今年7月份对古腾堡进行适配。

Argon主题 github 开源地址:https://github.com/solstice23/argon-theme

古腾堡模块在gutenberg目录下,拿到手后要先看他的 package.json 用了什么,而不是上去直奔 JavaScript 。

所用依赖

  "dependencies": {"@wordpress/compose": "^4.2.0","@wordpress/data": "^5.2.0","cgb-scripts": "1.23.1","font-awesome": "^4.7.0","is-whitespace-character": "^2.0.0"}
  1. @wordpress/components 它是wordpress的通用组件库,通过使用这个主题或查看的古腾堡模块目录我们知道作者做的是有折叠模块的,那折叠模块有设置,可以看到这里有个普通的 Switchbutton (WordPress中叫ToggleControl)。那这个切换按钮就是来自 @wordpress/components ,如果您用过 BootStrap 你就知道第一个说的是干嘛的了。

图中按钮来自 wordpress components

官方组件库的示例:https://wordpress.github.io/gutenberg/?path=/docs/components-togglecontrol--default

使用 ToggleControl 代码示例:

import { ToggleControl } from '@wordpress/components';
import { useState } from '@wordpress/element';const MyToggleControl = () => {const [ hasFixedBackground, setHasFixedBackground ] = useState( false );return (<ToggleControllabel="Fixed Background"help={hasFixedBackground? 'Has fixed background.': 'No fixed background.'}checked={ hasFixedBackground }onChange={ () => {setHasFixedBackground( ( state ) => ! state );} }/>);
};

2. @wordpress/data 它就是 WordPress 的数据管理模块,建立在 Redux 的基础上(因为 wordpress 后台用的有React), WordPress 用到了它,并且有自己的特性。它的作用和 Vuex 一样用来统一管理数据。

使用 @wordpress/data 代码示例 :

import apiFetch from '@wordpress/api-fetch';
import { createReduxStore, register } from '@wordpress/data';const DEFAULT_STATE = {prices: {},discountPercent: 0,
};const actions = {setPrice( item, price ) {return {type: 'SET_PRICE',item,price,};},startSale( discountPercent ) {return {type: 'START_SALE',discountPercent,};},fetchFromAPI( path ) {return {type: 'FETCH_FROM_API',path,};},
};const store = createReduxStore( 'my-shop', {reducer( state = DEFAULT_STATE, action ) {switch ( action.type ) {case 'SET_PRICE':return {...state,prices: {...state.prices,[ action.item ]: action.price,},};case 'START_SALE':return {...state,discountPercent: action.discountPercent,};}return state;},actions,selectors: {getPrice( state, item ) {const { prices, discountPercent } = state;const price = prices[ item ];return price * ( 1 - 0.01 * discountPercent );},},controls: {FETCH_FROM_API( action ) {return apiFetch( { path: action.path } );},},resolvers: {*getPrice( item ) {const path = '/wp/v2/prices/' + item;const price = yield actions.fetchFromAPI( path );return actions.setPrice( item, price );},},
} );register( store );

3. cgb-scripts 这个是古腾堡块的开发工具包,Argon 主题作者用的就是它进行块开发,当然这个工具也是开源的。使用命令行进行创建:

npx create-guten-block my-block

然后你就能看到和 Argon 主题一样的古腾堡目录结构。

cgb-scripts github 开源地址: https://github.com/ahmadawais/create-guten-block

4. font-awesome 这个大家都不陌生了,开源的图标库。

5. is-whitespace-character 他用于检查字符是否为空白字符,同时它也是开源的。

is-whitespace-character github 开源地址: https://github.com/wooorm/is-whitespace-character#readme

那这个 Argon 主题作者在哪里用到了呢?打开他写的古腾堡警告组件 admonition 模块,看87行代码。

{!(isWhitespaceCharacter(props.attributes.fa_icon_name) || props.attributes.fa_icon_name == "") &&<span><i className={`fa fa-${props.attributes.fa_icon_name}`}></i>&nbsp;</span>
}

这段代码逻辑很简单,如果用户自定义的图标名称输入的是空格则不进行图标处理(第一个位置), 反之不成立说明用户输入的第一个位置不是空格,就取用户输入的(那如果第一位不是空格,但后面有,则不用处理)。

注意点

Argon 主题作者虽然在 package.json 引入了 font-awesome ,但它没有在古腾堡模块内使用,而是从 assets\vendor 取用。所用依赖部分除了 cgb-scripts ,其他为作者自己去手动安装的。

复刻目标

本文复刻 Argon 主题的古腾堡提示模块

准备工作

使用官方脚手架创建基础块目录,在主题目录下执行命令,一路回车就行。

npx @wordpress/create-block

安装好后自己在 npm 装下 font-awesomeis-whitespace-character

src 下我们建立一个 alert 目录,在里面分别建立:index.js 、index.css 。

JavaScript复制过来要进行修改,css则不修改,不要直接拿来用!原作者没有完全按需引用,有些没有用到。

index.js


import './index.css';
import { __ } from '@wordpress/i18n';
import {RichText,InspectorControls} from "@wordpress/block-editor";
import {ColorPalette,
TextControl,
PanelBody, PanelRow} from '@wordpress/components';
import { isWhitespaceCharacter } from 'is-whitespace-character'
import { registerBlockType } from '@wordpress/blocks';registerBlockType('argon/alert', {title: __('提示'),icon: 'warning',category: 'argon',keywords: ['argon',__('提示')],attributes: {color: {type: 'string',default: '#7889e8'},content: {type: 'string',default: ''},fa_icon_name: {type: 'string',default: 'info-circle'},},edit: (props) => {const onChangeContent = (value) => {props.setAttributes({ content: value });};const onChangeColor = (value) => {props.setAttributes({ color: (value || "#7889e8") });}const onIconChange = (value) => {props.setAttributes({ fa_icon_name: value });}return (<div><div className="alert" style={{ backgroundColor: props.attributes.color }}>{!(isWhitespaceCharacter(props.attributes.fa_icon_name) || props.attributes.fa_icon_name == "") &&<span className="alert-inner--icon"><i className={`fa fa-${props.attributes.fa_icon_name}`}></i></span>}<RichTexttagName="span"className="alert-inner--text"placeholder={__("内容")}value={props.attributes.content}onChange={onChangeContent}/></div><InspectorControls key="setting"><PanelBody title={__("区块设置")} icon={"more"} initialOpen={true}><PanelRow><div id="gutenpride-controls"><fieldset><PanelRow>{__('颜色', 'argon')}</PanelRow><ColorPaletteonChange={onChangeColor}colors={[{ name: 'argon', color: '#7889e8' },{ name: 'green', color: '#4fd69c' },{ name: 'red', color: '#f75676' },{ name: 'blue', color: '#37d5f2' },{ name: 'orange', color: '#fc7c5f' },{ name: 'pink', color: '#fa7298' },{ name: 'black', color: '#3c4d69' },]}value={props.attributes.color}/></fieldset><fieldset><PanelRow>{__('图标', 'argon')}</PanelRow><TextControlvalue={props.attributes.fa_icon_name}onChange={onIconChange}/><p className="help-text">{__('Font Awesome 中的图标名,留空则不显示', 'argon')}&nbsp;<a href="https://fontawesome.com/v4.7.0/icons/" target="_blank">{__('浏览图标', 'argon')}</a></p></fieldset></div></PanelRow></PanelBody></InspectorControls></div>);},save: (props) => {return (<div className="alert" style={{ backgroundColor: props.attributes.color }}>{!(isWhitespaceCharacter(props.attributes.fa_icon_name) || props.attributes.fa_icon_name == "") &&<span className="alert-inner--icon"><i className={`fa fa-${props.attributes.fa_icon_name}`}></i></span>}<span className="alert-inner--text" dangerouslySetInnerHTML={{ __html: props.attributes.content }}></span></div>);},
});

index.css

.alert {font-size: 0.875rem;padding: 1rem 1.5rem;border: 0;border-radius: 0.25rem;
}.alert .alert-inner--icon {font-size: 1.25rem;display: inline-block;margin-right: 1.25rem;vertical-align: middle;
}.alert .alert-inner--icon i.ni {position: relative;top: 1px;
}.alert .alert-inner--text {display: inline-block;vertical-align: middle;
}.alert:not(.alert-secondary) {color: #fff;
}[class*="alert-"] .alert-link {color: #fff;border-bottom: 1px dotted rgba(255, 255, 255, 0.5);
}.alert-heading {font-size: 1.5rem;font-weight: 600;margin-top: 0.15rem;
}.alert-dismissible .close {top: 50%;right: 1.5rem;padding: 0;transform: translateY(-50%);opacity: 1;color: rgba(255, 255, 255, 0.6);
}.alert-dismissible .close:focus,
.alert-dismissible .close:hover {opacity: 1 !important;color: rgba(255, 255, 255, 0.9);
}@media (max-width: 575.98px) {.alert-dismissible .close {top: 1rem;right: 0.5rem;}
}.alert-dismissible .close > span:not(.sr-only) {font-size: 1.5rem;color: rgba(255, 255, 255, 0.6);background-color: transparent;
}.alert-dismissible .close:focus > span:not(.sr-only),
.alert-dismissible .close:hover > span:not(.sr-only) {color: rgba(255, 255, 255, 0.9);background-color: transparent;
}.alert {position: relative;margin-bottom: 1rem;padding: 1rem 1.5rem;border: 0.0625rem solid transparent;border-radius: 0.25rem;
}.alert-heading {color: inherit;
}.alert-link {font-weight: 600;
}.alert-dismissible {padding-right: 4.5rem;
}.alert-dismissible .close {position: absolute;top: 0;right: 0;padding: 1rem 1.5rem;color: inherit;
}.alert-primary {color: #fff;border-color: #7889e8;background-color: #7889e8;
}.alert-primary hr {border-top-color: #6276e4;
}.alert-primary .alert-link {color: #324cdd;
}.alert-secondary {color: #212529;border-color: #f6f7f8;background-color: #f6f7f8;
}.alert-secondary hr {border-top-color: #e8eaed;
}.alert-secondary .alert-link {color: #d6dae2;
}.alert-success {color: #fff;border-color: #4fd69c;background-color: #4fd69c;
}.alert-success hr {border-top-color: #3ad190;
}.alert-success .alert-link {color: #24a46d;
}.alert-info {color: #fff;border-color: #37d5f2;background-color: #37d5f2;
}.alert-info hr {border-top-color: #1fd0f0;
}.alert-info .alert-link {color: #0da5c0;
}.alert-warning {color: #fff;border-color: #fc7c5f;background-color: #fc7c5f;
}.alert-warning hr {border-top-color: #fc6846;
}.alert-warning .alert-link {color: #fa3a0e;
}.alert-danger {color: #fff;border-color: #f75676;background-color: #f75676;
}.alert-danger hr {border-top-color: #f63e62;
}.alert-danger .alert-link {color: #ec0c38;
}.alert-light {color: #fff;border-color: #bac1c8;background-color: #bac1c8;
}.alert-light hr {border-top-color: #acb4bd;
}.alert-light .alert-link {color: #919ca6;
}.alert-dark {color: #fff;border-color: #45484b;background-color: #45484b;
}.alert-dark hr {border-top-color: #393b3e;
}.alert-dark .alert-link {color: #0a0c0d;
}.alert-default {color: #fff;border-color: #3c4d69;background-color: #3c4d69;
}.alert-default hr {border-top-color: #334159;
}.alert-default .alert-link {color: #0b1526;
}.alert-white {color: #212529;border-color: #fff;background-color: #fff;
}.alert-white hr {border-top-color: #f2f2f2;
}.alert-white .alert-link {color: #e6e6e6;
}.alert-neutral {color: #212529;border-color: #fff;background-color: #fff;
}.alert-neutral hr {border-top-color: #f2f2f2;
}.alert-neutral .alert-link {color: #e6e6e6;
}.alert-darker {color: #fff;border-color: #292929;background-color: #292929;
}.alert-darker hr {border-top-color: #1c1c1c;
}.alert-darker .alert-link {color: #000;
}.help-text{margin-top: -8px !important;font-size: 12px;font-style: normal;color: rgb(117, 117, 117);
}

functions.php

<?php
function init_gutenberg_blocks() {wp_register_script('demo-gutenberg-block-js',get_template_directory_uri().'/esnext-example/build/index.js',array( 'wp-blocks', 'wp-i18n', 'wp-element', 'wp-editor'),null,true);wp_register_style('demo-gutenberg-block-backend-css',get_template_directory_uri().'/esnext-example/build/index.css',array('wp-edit-blocks'),get_template_directory() . '/esnext-example/build/style-index.css');register_block_type('esnext-example/demo-gutenberg-block', array('editor_script' => 'demo-gutenberg-block-js','editor_style'  => 'demo-gutenberg-block-backend-css',));
}
add_action('init', 'init_gutenberg_blocks');

这里引入都是打包后的模块,不要急,后面我就说打包。

我这种做法是手动建立,跳过了官方说的插件激活那种步骤。最后使用 register_block_type 注册块,也就是说我的资源只在后台加载,前端只需要放有对应块样式就能进行显示。

准备工作好了后,我们找到 src 下的 index 引入我们写的警告模块。


import 'font-awesome/css/font-awesome.min.css'
import './alert'/*** Registers a new block provided a unique name and an object defining its behavior.** @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/*/
import { registerBlockType } from '@wordpress/blocks';/*** Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.* All files containing `style` keyword are bundled together. The code used* gets applied both to the front of your site and to the editor.** @see https://www.npmjs.com/package/@wordpress/scripts#using-css*/
import './style.scss';/*** Internal dependencies*/
import Edit from './edit';
import save from './save';/*** Every block starts by registering a new block type definition.** @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/*/
registerBlockType( 'create-block/esnext-example', {title: '测试一下',testValue: null,/*** @see ./edit.js*/edit: Edit,/*** @see ./save.js*/save,
} );

在脚手架生成的文件下执行打包(我生成的目录名叫esnext-example就在这个目录下执行)。

打包开发环境:

npm run build

打包生产环境

npm run format

其他命令您可以参照这个即可:https://www.npmjs.com/package/@wordpress/create-block

如果您是IDEA、PHPStorm即 Jetbrains 系列编辑器直接点击这个也能打包。

这里就是打包后输出的目录

图为打包后目录

最终效果

图为最终效果

研究下开源主题Argon的古腾堡实现相关推荐

  1. WordPress 5.0禁用古滕堡编辑器的方法

    WordPress 5.0正式版使用了古滕堡编辑器,非常不习惯,没以前的经典编辑器好用.那么怎么回到以前的编辑器呢?我们可以使用Classic Editor经典编辑器做为插件方式,安装Classic ...

  2. Maplab:一个用于视觉惯性建图和定位研究的开源框架

    摘要 鲁棒且精确的视觉惯性估计是当今机器人领域的重要挑战.能够用先验地图(prior map)进行定位(localize)并获得准确且无漂移的姿态估计,可以推动该系统的适应性.然而,目前大多数可用的解 ...

  3. 适合个人博客搭建的WordPress免费开源主题汇总

    WordPress最重要的就是找一个适合自己的主题了.好一点的WordPress主题基本上都是要收费的,而且价格还不便宜,这导致了不少的新手朋友们很为难.而有时我们仅仅根据个人的爱好来搭建一个博客,所 ...

  4. BciPy: 一款基于Python用于BCI研究的开源软件

    ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ 进行脑机接口(BCI)研究对技术和软件有很高的要求.为了加速BCIs的开发和可访问性,研究人员开发了BciPy,一个基于Python的用于BCI研究的开源软件 ...

  5. 关于.NET下开源及商业图像处理(PSD)组件

    1 前言 这篇博客的背景是:为了完成吉日嘎拉的"PSD文件损坏检测和图层检测"任务,查找了目前.NET各种开源的及商业的图像处理资料,在完成任务之后,进行总结.此次任务主要是用C# ...

  6. MOOCCube:基于MOOC相关研究的开源大规模数据仓库 ACL2020

    论文链接:http://keg.cs.tsinghua.edu.cn/jietang/publications/ACL20-Yu-Luo-et-al-MOOCCube.pdf 数据链接:http:// ...

  7. Linux下开源邮件系统Postfix+Extmail+Extman环境部署

    SMTP.POP3.IPMAP三者说明 简单来说:SMTP是邮件发送协议:POP3和IMAP是邮件接收协议.其中: 1)SMTP 全称是"Simple Mail Transfer Proto ...

  8. pe里的计算机桌面,PE下桌面主题使用技巧解读

    PE下桌面主题使用技巧解读 发布时间:2014-04-01 14:59:23   作者:佚名   我要评论 windows下更换主题相信大家都会,但在PE下使用桌面主题对大家来说,或许就有点难度了,下 ...

  9. J2EE学习中一些值得研究的开源项目(转载天极网)

    J2EE学习中一些值得研究的开源项目 这篇文章写在我研究J2SE.J2EE近三年后.前3年我研究了J2SE的Swing.Applet.Net.RMI.Collections.IO.JNI--研究了J2 ...

最新文章

  1. python pandas DataFrame 排序
  2. Tungsten Fabric SDN — 基于 Tags 的安全访问控制策略
  3. 企业千人千面管理模式_一汽解放青岛汽车有限公司荣获“2020(第十六届)中国企业教育先进单位百强”...
  4. STM32工作笔记0098---Windows下的Linux环境_Cygwin_MinGW_MSYS_MSYS2_之间的关系
  5. 点击复制,兼容ios-safari
  6. 一题多解(四)—— 数组中唯一出现 2 次的数
  7. raw socket 使用 BPF 过滤报文
  8. 【数据治理】数据元、元数据、主数据、参考数据概述
  9. 基于ssm的酒店管理系统
  10. pytorch实现textCNN
  11. 计算机设计大赛报道,我院在中国大学生计算机设计大赛中再创佳绩
  12. PostgreSQL汉字转拼音
  13. pt、px、rpx、em、rem到底是什么
  14. Java视频教程(浙江大学翁恺)
  15. 考夫曼自适应均线_采访:查理·考夫曼
  16. python entry如何清空_Python tkinter,从类中清除Entry小部件
  17. 飞机3D轨迹绘制(经度-纬度-高度)
  18. [实操]ITunes打开时报错.“如果您在 iTunes 中看到 -45054 或 -42110 错误“
  19. 正则表达式教程: 开始
  20. 来自西弗吉利亚大学li xin整理的CV代码合集

热门文章

  1. leetcode5923.从房屋收集雨水需要的最少水桶数(中等,周赛)
  2. 第九十九节,JavaScript数据类型
  3. 特强的的拖动分页(JS+CSS
  4. [AGC003D]Anticube
  5. 五连珠matlab,智慧珠游戏拼盘终于有了自己比较满意的解法
  6. 3D打印机,固件编程环境
  7. windbg入门教程之获取异常报告
  8. 24式太极拳文字讲解
  9. MySQL库迁移到达梦的过程中,出现列长度超出定义的问题导致中断
  10. 选题的背景与意义计算机网络在继续教育中的应用,计算机网络在继续教育中应用...