如何在 Nuxt 中使用 TinyMCE?
How to use TinyMCE in Nuxt?
我想将此脚本添加到我的 Nuxt 代码中:
<script>
tinymce.init({
selector: "#mytextarea",
plugins: "emoticons",
toolbar: "emoticons",
toolbar_location: "bottom",
menubar: false
});
</script>
我可以将它放入我的组件的模板主体中(这个脚本必须在 <body>
而不是 <head>
中) 像这样:
有趣的是它有效,但这里有两个问题:
- 长得丑
- 它不是动态的。例如,我无法将
selector
动态绑定到道具或数据 属性!它必须被硬编码。
所以我想知道是否有人知道如何将这些脚本正确地集成到我的 Nuxt 项目中?
- 我真的很怀疑这行得通。 Vue 总是忽略模板中的任何
<script>
标签并显示错误消息:
Templates should only be responsible for mapping the state to the UI. Avoid placing tags with side-effects in your templates, such as <script>
, as they will not be parsed.
- 没有理由将其放入模板中。它只是您可以作为组件生命周期的一部分执行的常规 JS 代码。下面是 非常 将 TinyMCE 集成到 Vue 应用程序中的简单组件包装器。
但是我不建议自己这样做而是使用official Vue wrapper (docs) - use v3 for Vue 2. Official integration handles all the edge cases like component activation/deactivation (when used together with <keep-alive>
) and proper cleanup when the component is destroyed which is required in order to avoid nasty memory leaks
const ed = Vue.component("MyEditor", {
props: ["id", "value"],
template: `
<div>
<textarea :id="id" :value="value"></textarea>
</div>
`,
mounted() {
const me = this;
window.tinymce.init({
selector: "#" + this.id,
plugins: "emoticons",
toolbar: "emoticons",
toolbar_location: "bottom",
menubar: false,
setup: function (editor) {
editor.on("change input undo redo", function () {
me.$emit('input', editor.getContent({format: 'text'}))
});
}
});
}
});
Nuxt
由于TinyMCE完全是JS渲染的,在服务器端渲染时执行它是没有意义的。事实上,上面的代码在服务器上根本不起作用,因为没有 window
变量。使用 Nuxt 的 <client-only>
component 强制 Nuxt 只在客户端渲染编辑器...
更新:另一方面,在 SSR 期间根本不会调用 mounted
生命周期挂钩,因此即使没有 <client-only>
也可能会正常工作
如已接受的答案中所述,官方 vue 包是必经之路。即使是官方包,我把它拉到 Nuxt 后也有很多问题。
这是一组。通过我如何让它工作的步骤。以下是所有相关内容的版本:
"tinymce": "^5.10.3",
"@tinymce/tinymce-vue": "^3.2.8",
"vue": "^2.6.11",
"nuxt": "2.15.8",
tinymce-vue 包需要一个 tinymce 可用。您可以像上面那样通过 npm 安装它,或者使用 cloud-hosted 版本(参见 Prerequisites here)。
Nuxt-specific 问题
您需要确保组件包裹在 <client-only>
标记中以避免 SSR 错误。
此外,如果 self-hosting tinymce 包,您将只想在 client-side 上导入它。否则你会看到如下错误:
[Vue warn]: Failed to resolve async component: ... Reason: ReferenceError: navigator is not defined
您可以通过在它们周围使用 require
和 if (process.client) {
来做到这一点。
例如:
if (process.client) {
require('tinymce/tinymce')
require('tinymce/themes/silver')
require('tinymce/icons/default')
require('tinymce/plugins/lists') // do this for any plugins you use on the editor
}
import Editor from '@tinymce/tinymce-vue'
此时编辑器应该正在您的页面上加载,但样式可能尚未加载。
您可以通过在其他 require
下方添加 require('tinymce/skins/ui/oxide/skin.min.css')
来解决此问题。
现在样式将得到修复,但 tinymce 主题仍会寻找其他 CSS 文件,例如 mobile,它自己的最小版本,并导致网络错误。
例如:
404 http://localhost:3000/_nuxt/skins/ui/oxide/content.min.css
404 http://localhost:3000/_nuxt/skins/ui/oxide/skin.min.css
内容:
您可以将该文件复制到具有相同路径的静态文件夹,或者使用 content_css setting(在 Vue 组件 init
选项中)覆盖它们。
适合皮肤:
由于您已经将其作为模块提供,因此在 Vue 组件 init
选项中设置 skin: false
。
我想将此脚本添加到我的 Nuxt 代码中:
<script>
tinymce.init({
selector: "#mytextarea",
plugins: "emoticons",
toolbar: "emoticons",
toolbar_location: "bottom",
menubar: false
});
</script>
我可以将它放入我的组件的模板主体中(这个脚本必须在 <body>
而不是 <head>
中) 像这样:
有趣的是它有效,但这里有两个问题:
- 长得丑
- 它不是动态的。例如,我无法将
selector
动态绑定到道具或数据 属性!它必须被硬编码。
所以我想知道是否有人知道如何将这些脚本正确地集成到我的 Nuxt 项目中?
- 我真的很怀疑这行得通。 Vue 总是忽略模板中的任何
<script>
标签并显示错误消息:
Templates should only be responsible for mapping the state to the UI. Avoid placing tags with side-effects in your templates, such as
<script>
, as they will not be parsed.
- 没有理由将其放入模板中。它只是您可以作为组件生命周期的一部分执行的常规 JS 代码。下面是 非常 将 TinyMCE 集成到 Vue 应用程序中的简单组件包装器。
但是我不建议自己这样做而是使用official Vue wrapper (docs) - use v3 for Vue 2. Official integration handles all the edge cases like component activation/deactivation (when used together with <keep-alive>
) and proper cleanup when the component is destroyed which is required in order to avoid nasty memory leaks
const ed = Vue.component("MyEditor", {
props: ["id", "value"],
template: `
<div>
<textarea :id="id" :value="value"></textarea>
</div>
`,
mounted() {
const me = this;
window.tinymce.init({
selector: "#" + this.id,
plugins: "emoticons",
toolbar: "emoticons",
toolbar_location: "bottom",
menubar: false,
setup: function (editor) {
editor.on("change input undo redo", function () {
me.$emit('input', editor.getContent({format: 'text'}))
});
}
});
}
});
Nuxt
由于TinyMCE完全是JS渲染的,在服务器端渲染时执行它是没有意义的。事实上,上面的代码在服务器上根本不起作用,因为没有 window
变量。使用 Nuxt 的 <client-only>
component 强制 Nuxt 只在客户端渲染编辑器...
更新:另一方面,在 SSR 期间根本不会调用 mounted
生命周期挂钩,因此即使没有 <client-only>
如已接受的答案中所述,官方 vue 包是必经之路。即使是官方包,我把它拉到 Nuxt 后也有很多问题。
这是一组。通过我如何让它工作的步骤。以下是所有相关内容的版本:
"tinymce": "^5.10.3",
"@tinymce/tinymce-vue": "^3.2.8",
"vue": "^2.6.11",
"nuxt": "2.15.8",
tinymce-vue 包需要一个 tinymce 可用。您可以像上面那样通过 npm 安装它,或者使用 cloud-hosted 版本(参见 Prerequisites here)。
Nuxt-specific 问题
您需要确保组件包裹在 <client-only>
标记中以避免 SSR 错误。
此外,如果 self-hosting tinymce 包,您将只想在 client-side 上导入它。否则你会看到如下错误:
[Vue warn]: Failed to resolve async component: ... Reason: ReferenceError: navigator is not defined
您可以通过在它们周围使用 require
和 if (process.client) {
来做到这一点。
例如:
if (process.client) {
require('tinymce/tinymce')
require('tinymce/themes/silver')
require('tinymce/icons/default')
require('tinymce/plugins/lists') // do this for any plugins you use on the editor
}
import Editor from '@tinymce/tinymce-vue'
此时编辑器应该正在您的页面上加载,但样式可能尚未加载。
您可以通过在其他 require
下方添加 require('tinymce/skins/ui/oxide/skin.min.css')
来解决此问题。
现在样式将得到修复,但 tinymce 主题仍会寻找其他 CSS 文件,例如 mobile,它自己的最小版本,并导致网络错误。
例如:
404 http://localhost:3000/_nuxt/skins/ui/oxide/content.min.css
404 http://localhost:3000/_nuxt/skins/ui/oxide/skin.min.css
内容:
您可以将该文件复制到具有相同路径的静态文件夹,或者使用 content_css setting(在 Vue 组件 init
选项中)覆盖它们。
适合皮肤:
由于您已经将其作为模块提供,因此在 Vue 组件 init
选项中设置 skin: false
。