从零搭建个人博客(3)-如何在webpack环境下配置jquery和富文本编辑器Simditor

无论是博主自己写文章还是读者发表评论,都需要一个方便的编辑框,html自带的textarea和editable div都过于简单,本文将记录在webpack环境中添加jquery和Simditor的过程,同时加入emoji功能。

从零搭建个人博客(1)-webpack环境配置
从零搭建个人博客(2)-博客UI搭建

安装并使用Simditor

使用npm安装,由于simditor依赖jquery,所以需要安装如下几个库:

npm install jquery simditor expose-loader --save

官方文档:http://simditor.tower.im/docs/doc-usage.html
文档中说明需要引用如下依赖:

<link rel="stylesheet" type="text/css" href="[style path]/simditor.css" />

<script type="text/javascript" src="[script path]/jquery.min.js"></script>
<script type="text/javascript" src="[script path]/module.js"></script>
<script type="text/javascript" src="[script path]/hotkeys.js"></script>
<script type="text/javascript" src="[script path]/uploader.js"></script>
<script type="text/javascript" src="[script path]/simditor.js"></script>

这里按需引入即可。首先在webpack中配置jquery,在module的loaders里加入

{
    test: require.resolve('jquery'),
    loader: 'expose-loader?$!expose-loader?jQuery', // jQuery and $
}

这样就可以全局引用jquery了,也方便以后使用jquery的ajax等功能,使用时直接import就行。

import $ from 'expose-loader?$!jquery';

同时我们要在入口文件中引入simditor的css文件

import '../node_modules/simditor/styles/simditor.scss';

simditor是对已有textarea的增强,所以使用时首先在react的render中插入一个textarea,这里使用react-bootstrap。

<FormGroup controlId="MainParentMessageBox">
    <FormControl componentClass="textarea" placeholder="留言" ref={'editor'} />
    <Button type="submit">提交</Button>
</FormGroup>

在componentDidMount中拿到这个textarea对应的dom节点并增强。

componentDidMount() {
    const textbox = ReactDOM.findDOMNode(this.refs.editor);
    this.editor = new Simditor({
        textarea: textbox,
        toolbar: ['title', 'bold', 'italic', 'underline', 'strikethrough', 'color', 'ol', 'ul', 'link', 'alignment']
    });
}

Simditor的参数可以参考官方文档http://simditor.tower.im/docs/doc-usage.html

emoji

使用npm安装

npm install simditor-emoji

在入口文件中import css文件:

import '../node_modules/simditor-emoji/styles/simditor-emoji.scss';

下面问题出现了,simditor-emoji.js无法加载进来,从node_module将simditor-emoji.js拷贝一份放到resource文件夹中,去掉文件头部的amd模块定义方式:

(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module unless amdModuleId is set
    define('simditor-emoji', ["jquery","simditor"], function (a0,b1) { return (root['EmojiButton'] = factory(a0,b1)); });
  } else if (typeof exports === 'object') {
    // Node. Does not work with strict CommonJS, but
    // only CommonJS-like environments that support module.exports,
    // like Node.
    module.exports = factory(require("jquery"),require("Simditor"));
  } else {
    root['SimditorEmoji'] = factory(jQuery,Simditor);
  }
}(this, function ($, Simditor) {

并import jquery和Simditor,取名emoji.js,变成如下代码。

import $ from 'expose-loader?$!jquery';
import Simditor from 'simditor';

const hasProp = {}.hasOwnProperty;
const slice = [].slice;
const extend = (child, parent) => { for (const key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

const EmojiButton = ((superClass) => {
    function NewEmojiButton() {
        const args = arguments.length >= 1 ? slice.call(arguments, 0) : [];
        NewEmojiButton.__super__.constructor.apply(this, args);
        $.merge(this.editor.formatter._allowedAttributes.img, ['data-emoji', 'alt']);
    }

    extend(NewEmojiButton, superClass);

    NewEmojiButton.i18n = {
        'zh-CN': {
            emoji: '表情'
        },
        'en-US': {
            emoji: 'emoji'
        }
    };

    NewEmojiButton.images = ['smile', 'smiley', 'laughing', 'blush', 'heart_eyes', 'smirk', 'flushed', 'grin', 'wink', 'kissing_closed_eyes', 'stuck_out_tongue_winking_eye', 'stuck_out_tongue', 'sleeping', 'worried', 'expressionless', 'sweat_smile', 'cold_sweat', 'joy', 'sob', 'angry', 'mask', 'scream', 'sunglasses', 'heart', 'broken_heart', 'star', 'anger', 'exclamation', 'question', 'zzz', 'thumbsup', 'thumbsdown', 'ok_hand', 'punch', 'v', 'clap', 'muscle', 'pray', 'skull', 'trollface'];

    NewEmojiButton.prototype.name = 'emoji';

    NewEmojiButton.prototype.icon = 'smile-o';

    NewEmojiButton.prototype.menu = true;

    NewEmojiButton.prototype.renderMenu = function renderMenu() {
        const tpl = '<ul class="emoji-list">\n</ul>';
        const opts = $.extend({
            imagePath: 'images/emoji/',
            images: NewEmojiButton.images
        }, this.editor.opts.emoji || {});
        let html = '';
        const dir = opts.imagePath.replace(/\/$/, '') + '/';
        const ref = opts.images;
        for (let i = 0, len = ref.length; i < len; i++) {
            const name = ref[i];
            html += "<li data-name='" + name + "'><img src='" + dir + name + ".png' width='20' height='20' alt='" + name + "' /></li>";
        }
        const $list = $(tpl);
        $list.html(html).appendTo(this.menuWrapper);
        return $list.on('mousedown', 'li', ((_this) => {
            return (e) => {
                _this.wrapper.removeClass('menu-on');
                if (!_this.editor.inputManager.focused) {
                    return;
                }
                const $img = $(e.currentTarget).find('img').clone().attr({
                    'data-emoji': true,
                    'data-non-image': true
                });
                _this.editor.selection.insertNode($img);
                _this.editor.trigger('valuechanged');
                _this.editor.trigger('selectionchanged');
            };
        })(this));
    };

    NewEmojiButton.prototype.status = () => {};

    return NewEmojiButton;
})(Simditor.Button);
Simditor.Toolbar.addButton(EmojiButton);

之后在入口文件将它require进来。

require('./resource/js/emoji');

使用时将emoji加入到Simditor中去。

componentDidMount() {
        const textbox = ReactDOM.findDOMNode(this.refs.MainParentMessageBox);
        this.editor = new Simditor({
            textarea: textbox,
            toolbar: ['title', 'bold', 'italic', 'underline', 'strikethrough', 'color', 'ol', 'ul', 'link', 'alignment', 'emoji'],
            emoji: {
                imagePath: './emoji'
            }
        });
    }

这里还有一个大坑,imagePath的路径比较麻烦,在simditor-emoji.js中用到了这个路径并使用了img的src属性来放置该路径,为打包带来了很大麻烦,这里有个解决方案,感觉不是很完美,最后还是打算直接塞进去服务器中的图片存放地址。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值