构建自定义模块

Quill作为编辑器的核心优势在于其丰富的API和强大的自定义功能。当你在Quill API的基础上实现功能时,把它作为一个模块进行组织是很方便的。本指南的目的在于,我们通过一种方式来构建文字计数器模块,这是许多文字处理器中常见的功能。

注意:好多Quill的内部模块的功能都是有组织的。你可以通过实现自己的方法来覆盖这些默认模块,并使用相同的名称进行注册。

字数

字数计数器的核心就是统计编辑器中的字数,并在某个用户界面中显示该值。因此我们需要:

  1. 监听Quill的文本变化
  2. 计算字符的总数
  3. 显示这个值

让我们直接跳到一个真实的例子!

html代码

  1. <div id="editor"></div>
  2. <div id="counter">0</div>

css代码

  1. body {
  2. padding: 25px;
  3. }
  4. #editor {
  5. border: 1px solid #ccc;
  6. }
  7. #counter {
  8. border: 1px solid #ccc;
  9. border-width: 0px 1px 1px 1px;
  10. color: #aaa;
  11. padding: 5px 15px;
  12. text-align: right;
  13. }

js代码

  1. // Implement and register module
  2. Quill.register('modules/counter', function(quill, options) {
  3. var container = document.querySelector('#counter');
  4. quill.on('text-change', function() {
  5. var text = quill.getText();
  6. // There are a couple issues with counting words
  7. // this way but we'll fix these later
  8. container.innerText = text.split(/\s+/).length;
  9. });
  10. });
  11. // We can now initialize Quill with something like this:
  12. var quill = new Quill('#editor', {
  13. modules: {
  14. counter: true
  15. }
  16. });

结果

计数例子

这就是为Quill添加一个自定义模块所需的一切!一个函数可以被注册为一个模块,它将被传递到相应的Quill编辑器对象通过配置项。

使用配置项

模可以通过传递一个配置对象,来调整所需的行为。我们可以使用它来接收计数器容器的选择器,而不是硬编码的字符串。让我们定制计数器来计算单词或者字符。

html代码

  1. <div id="editor"></div>
  2. <div id="counter">0 words</div>

css代码

  1. body {
  2. padding: 25px;
  3. }
  4. #editor {
  5. border: 1px solid #ccc;
  6. }
  7. #counter {
  8. border: 1px solid #ccc;
  9. border-width: 0px 1px 1px 1px;
  10. color: #aaa;
  11. padding: 5px 15px;
  12. text-align: right;
  13. }

js代码

  1. Quill.register('modules/counter', function(quill, options) {
  2. var container = document.querySelector(options.container);
  3. quill.on('text-change', function() {
  4. var text = quill.getText();
  5. if (options.unit === 'word') {
  6. container.innerText = text.split(/\s+/).length + ' words';
  7. } else {
  8. container.innerText = text.length + ' characters';
  9. }
  10. });
  11. });
  12. var quill = new Quill('#editor', {
  13. modules: {
  14. counter: {
  15. container: '#counter',
  16. unit: 'word'
  17. }
  18. }
  19. });

结果

计算单词数

构造函数

由于任何函数都可以注册为一个Quill模块,所以我们可以实现我们的计数器作为ES5构造函数或者ES6类。这使我们可以直接访问和使用模块。

html代码

  1. <div id="editor"></div>
  2. <div id="counter">0 words</div>

css代码

  1. body {
  2. padding: 25px;
  3. }
  4. #editor {
  5. border: 1px solid #ccc;
  6. }
  7. #counter {
  8. border: 1px solid #ccc;
  9. border-width: 0px 1px 1px 1px;
  10. color: #aaa;
  11. padding: 5px 15px;
  12. text-align: right;
  13. }

js代码

  1. var Counter = function(quill, options) {
  2. this.quill = quill;
  3. this.options = options;
  4. var container = document.querySelector(options.container);
  5. var _this = this;
  6. quill.on('text-change', function() {
  7. var length = _this.calculate();
  8. container.innerText = length + ' ' + options.unit + 's';
  9. });
  10. };
  11. Counter.prototype.calculate = function() {
  12. var text = this.quill.getText();
  13. if (this.options.unit === 'word') {
  14. return text.split(/\s+/).length;
  15. } else {
  16. return text.length;
  17. }
  18. };
  19. Quill.register('modules/counter', Counter);
  20. var quill = new Quill('#editor', {
  21. modules: {
  22. counter: {
  23. container: '#counter',
  24. unit: 'word'
  25. }
  26. }
  27. });
  28. var counter = quill.getModule('counter');
  29. // We can now access calculate() directly
  30. console.log(counter.calculate(), 'words');

结果

构造函数例子

包装起来

现在让我们整理我们的ES6模块并且修改一些bug。下面就是所有代码了!

html代码

  1. <div id="editor"></div>
  2. <div id="counter"></div>

css代码

  1. body {
  2. font-family: Helvetica, Arial, sans-serif;
  3. font-size: 13px;
  4. padding: 25px;
  5. }
  6. #editor {
  7. border: 1px solid #ccc;
  8. }
  9. #counter {
  10. border: 1px solid #ccc;
  11. border-width: 0px 1px 1px 1px;
  12. color: #aaa;
  13. padding: 5px 15px;
  14. text-align: right;
  15. }

js代码(Babel)

  1. class Counter {
  2. constructor(quill, options) {
  3. this.quill = quill;
  4. this.options = options;
  5. this.container = document.querySelector(options.container);
  6. quill.on('text-change', this.update.bind(this));
  7. this.update(); // Account for initial contents
  8. }
  9. calculate() {
  10. let text = this.quill.getText();
  11. if (this.options.unit === 'word') {
  12. text = text.trim();
  13. // Splitting empty text returns a non-empty array
  14. return text.length > 0 ? text.split(/\s+/).length : 0;
  15. } else {
  16. return text.length;
  17. }
  18. }
  19. update() {
  20. var length = this.calculate();
  21. var label = this.options.unit;
  22. if (length !== 1) {
  23. label += 's';
  24. }
  25. this.container.innerText = length + ' ' + label;
  26. }
  27. }
  28. Quill.register('modules/counter', Counter);
  29. var quill = new Quill('#editor', {
  30. modules: {
  31. counter: {
  32. container: '#counter',
  33. unit: 'word'
  34. }
  35. }
  36. });

结果

最后结果