Vue JSを使ってcomponent内にsummernoteを挿入するときの注意事項

表示:vueライフサイクル上のmounted()を使う

<template>
    <div class="vue-message-composer">
        <div class="mail-text h-200">
            <div class="summernote" ></div>

        </div>

    </div>

</template>

<script>

    import summernote.min.js;

    export defalut {

        mounted() {
            $('.summernote').summernote();

        }

    }

</script>

 

ここでsummernoteの表示、非表示をv-ifで実装しようとすると...

summernote()で追加されるelementにv-ifが適用出来ないため表示エラーが出る。

従って非表示は.summernoteの親クラスごとcssのdisplay: noneで処理

 

summernote.min.jsの配置場所も重要

URLから直接リロードしてsummernoteを含むコンポーネントを表示した場合、component内に配置したsummernote.min.jsが読み込まれ正常動作するが、router-linkを通じて当該componentを表示した場合、component内に配置したsummernote.min.jsが読み込まれない(もしくは読み込む順番がおかしい?)ため表示エラーになる。

従って、起点となるページ(laravel内にvueを配置しているため今回はapp.blade.php)にも

<script src="{{ asset('js/plugins/summernote/summernote.min.js') }}"></script>

を配置。 

 

dependencyエラー

jqueryとbootstrapが必要

ただし最新版jquery-3.2.1だとフォントの切り替え等、一部ツールバーのボタンが機能しない。

jquery-2.2.4だと

jQuery Tooltip script error TypeError: JQuery(...).tooltip is not a function

ツールバーは機能しても表示エラー

上記エラーを回避するために最新版(現時点でjQuery UI 1.12.1)のjQuery UIを読み込む。

dependencyまとめ

{ jquery-3-2-1, summernote}

-> ツールバーが一部動作しない

{ jquery-2-2-4, summernote}

->vue-routerでルーティングして表示した時表示がおかしくなる 

{ jquery-2-2-4, jquery UI 1.12.1, summernote}

->vue-routerでルーティングして表示した時、ツールバーのポップアップ表示がおかしくなる。

下記のスクリプトを追加で解決

/* ========================================================================
* Bootstrap: popover.js v3.3.7
* http://getbootstrap.com/javascript/#popovers
* ========================================================================
* Copyright 2011-2016 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */


+function ($) {
'use strict';

// POPOVER PUBLIC CLASS DEFINITION
// ===============================

var Popover = function (element, options) {
this.init('popover', element, options)
}

if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')

Popover.VERSION = '3.3.7'

Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
placement: 'right',
trigger: 'click',
content: '',
template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
})


// NOTE: POPOVER EXTENDS tooltip.js
// ================================

Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)

Popover.prototype.constructor = Popover

Popover.prototype.getDefaults = function () {
return Popover.DEFAULTS
}

Popover.prototype.setContent = function () {
var $tip = this.tip()
var title = this.getTitle()
var content = this.getContent()

$tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
$tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
](content)

$tip.removeClass('fade top bottom left right in')

// IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
// this manually by checking the contents.
if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
}

Popover.prototype.hasContent = function () {
return this.getTitle() || this.getContent()
}

Popover.prototype.getContent = function () {
var $e = this.$element
var o = this.options

return $e.attr('data-content')
|| (typeof o.content == 'function' ?
o.content.call($e[0]) :
o.content)
}

Popover.prototype.arrow = function () {
return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
}


// POPOVER PLUGIN DEFINITION
// =========================

function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.popover')
var options = typeof option == 'object' && option

if (!data && /destroy|hide/.test(option)) return
if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
if (typeof option == 'string') data[option]()
})
}

var old = $.fn.popover

$.fn.popover = Plugin
$.fn.popover.Constructor = Popover


// POPOVER NO CONFLICT
// ===================

$.fn.popover.noConflict = function () {
$.fn.popover = old
return this
}

}(jQuery);

laravelで起点ページを作り、vue-routerでsummernoteを表示するページを作った場合、当該ページをリロードした時とvue-router経由で表示した時、イベント実行時に使用されるスクリプトがなぜか違う。理由は不明。

ページをリロード→app.js

vue-router経由→jquery-ui.js(app.jsは無視される??)→エラー

mounted()でsummernote()を実行した時と、別途methodを作ってsummernote()を実行した時でイベント実行時に使用されるスクリプトがなぜか違う。理由は不明。

 

mounted()→app.js

method→jquery-ui.js(app.jsは無視される??)→エラー

 

結論:

summernoteとvue-routerは同時に使えない。(summernote以外をroutingすることは可能か???)

起点ページapp.blade.phpに配置したscriptの順番の問題。

app.js→jqueryの順番で配置したため、一部上書きされエラーが発生。

jquery→app.jsの順で配置する。ページをリロードした時app.jsがjqueryで上書きされなかった理由は不明。