----------项目目录---------
dist
node_modules
package-lock.json
package.json
quickstart_tinymce.html[单页js应用]
src -->内容详细见下
themes
webpack.config.js
------- src ----
app.vue [入口]
assets
editor.vue [tinymce的官网组件封装,需要api key]
index.js
static [静态资源]
subc.vue [练习子组件]
tmm.vue [tinymce的封装,不需要key]
参考
https://www.cnblogs.com/wisewrong/p/8985471.html
npm install tinymce -S
安装之后,在 node_modules 中找到 tinymce/skins 目录,然后将 skins 目录拷贝到 static/tinymce (这个是在src下面自己建的目录) 目录下
代码清单:
------app.vue--------
//组件不能直接挂载到html里
<template>
<div>
<div id="test">{{text}}</div>
<div>
<!--
<editor api-key="x" :init="{plugins: 'wordcount'}"></editor>
-->
<editor2 ></editor2>
</div>
</div>
</template>
<script>
//import subc from "./subc.vue";
//import Editor from '@tinymce/tinymce-vue';
import tmm from "./tmm.vue";
export default {
data() {
return{
text:'这是测试',
description:'我是富文本编辑器的内容',
//tinymce的配置信息 参考官方文档 https://www.tinymce.com/docs/configure/integration-and-setup/
editorSetting:{
height:400,
}
}
},
components:{
// subc,
//'editor': Editor
'editor2': tmm
}
}
</script>
<style scoped>
#test{color:red;}
</style>
------tmm.vue--------
<template>
<div class='tinymce'>
<h1>tinymce</h1>
<editor id='tinymce' v-model='tinymceHtml' :init='init'></editor>
<div v-html='tinymceHtml'></div>
<div v-text='tinymceHtml'></div>
</div>
</template>
<script>
import tinymce from 'tinymce/tinymce'
import 'tinymce/themes/silver/theme'
import Editor from '@tinymce/tinymce-vue'
import 'tinymce/plugins/image'
import 'tinymce/plugins/link'
import 'tinymce/plugins/code'
import 'tinymce/plugins/table'
import 'tinymce/plugins/lists'
import 'tinymce/plugins/contextmenu'
import 'tinymce/plugins/wordcount'
import 'tinymce/plugins/colorpicker'
import 'tinymce/plugins/textcolor'
export default {
name: 'tinymce',
data () {
return {
tinymceHtml: '请输入内容',
init: {
//language_url: '/static/tinymce/zh_CN.js',
// language: 'zh_CN',
skin_url: '/src/static/tinymce/skins/ui/oxide-dark',
height: 300,
plugins: 'link lists image code table colorpicker textcolor wordcount contextmenu',
toolbar:
'bold italic underline strikethrough | fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist | outdent indent blockquote | undo redo | link unlink image code | removeformat',
branding: false
}
}
},
mounted () {
tinymce.init({})
},
components: {Editor}
}
</script>
----------editor.vue---------
<template>
<textarea :id="id" :value="value"></textarea>
</template>
<script>
// Import TinyMCE
//import tinymce from 'tinymce/tinymce';
// import 'tinymce/themes/modern/theme';
import 'tinymce/plugins/paste';
import 'tinymce/plugins/link';
//import tinymce from 'tinymce/tinymce'
//import 'tinymce/themes/modern/theme'
import Editor from '@tinymce/tinymce-vue'
const INIT = 0;
const CHANGED = 2;
var EDITOR = null;
export default {
props: {
value: {
type: String,
required: true
},
setting: {}
},
watch: {
value: function (val) {
console.log('init ' + val)
if (this.status == INIT || tinymce.activeEditor.getContent() != val){
tinymce.activeEditor.setContent(val);
}
this.status = CHANGED
}
},
data: function () {
return {
status: INIT,
id: 'editor-'+new Date().getMilliseconds(),
}
},
methods: {
},
mounted: function () {
const _this = this;
const setting =
{
selector:'#'+_this.id,
language:"zh_CN",
init_instance_callback:function(editor) {
EDITOR = editor;
console.log("Editor: " + editor.id + " is now initialized.");
editor.on('input change undo redo', () => {
var content = editor.getContent()
_this.$emit('input', content);
});
},
plugins:[]
};
Object.assign(setting,_this.setting)
tinymce.init(setting);
},
beforeDestroy: function () {
tinymce.get(this.id).destroy();
}
}
</script>
----------subc.vue------
**练习**
//组件不能直接挂载到html里
<template>
<div>
<div id="subc">{{subctext}}</div>
<button id="subc_btn_inc" @click="inc">subc inc</button>
<button id="subc_btn_dec" @click="dec">subc dec</button>
</div>
</template>
<script>
export default {
data() {
return{
subctext:0
}
},
methods:{
inc:function(){
//alert(this.subctext)
this.subctext++
},
dec:function(){
alert(this.subctext)
this.subctext--
},
}
}
</script>
<style scoped>
#subc{color:darkorange;}
</style>
---------index.js------------
//入口文件
import Vue from 'vue' //映入vue类库
import App from './app.vue' //app来自vue文件
import './assets/styles/test.css'
import './assets/images/Figure_1.jpg'
const root = document.createElement('div')
document.body.appendChild(root) //创建节点
new Vue({
render:(h) => h(App) //把app挂载到html里
}).$mount(root) //调用api,$mount到html的节点里
---------webpack.config.js------------
//打包出来在浏览器可以直接运行的js代码
const path = require('path') //path是node.js里的基本包
const HTMLPlugin = require('html-webpack-plugin')
const webpack = require('webpack')
const VueLoaderPlugin = require('vue-loader/lib/plugin') //webpack4配置需要包含VueLoaderPlugin
const isDev = process.env.NODE_ENV === 'development' //判断是不是true
const config = {
target: "web",
entry: path.join(__dirname,'src/index.js'), //入口entry要使用绝对路径 _dirname是根目录 拼接路径形成绝对路径,保证绝对可以访问到我们的文件
output: {
filename: "bundle.js",//输出的文件名
path: path.join(__dirname,'dist'), //输出路径
publicPath: '/'
}, //出口,输出文件
module: {
rules: [
{
test: /\.vue$/,
loader: "vue-loader"
},
{
test:/\.css$/,
//loader:['style-loader','css-loader']
use:['style-loader','css-loader'] //css会以js代码出现
},
{
test:/\.(gif|jpg|jpeg|png|svg)$/,
use:[
{
loader:'url-loader',
options:{
limit:1024,
name:'[name].[ext]'
}// 图片
}
]
}
]
},
plugins: [
new VueLoaderPlugin(),
new webpack.DefinePlugin({
'process.env':{
NODE_ENV: isDev ? '"development"' : '"production"'
}
}),
new HTMLPlugin()
]//webpack4配置需要包含VueLoaderPlugin,在输出里面配置plugins:
}
if (isDev){
config.devServer = {
port:8000,
host:'localhost',
overlay:{
errors:true,
},
// open:true //自动打开浏览器
}
}
module.exports = config
-------------package.json------
{
"name": "webpacktest",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "cross-env NODE_ENV=PRODUCTION webpack --config webpack.config.js",
"dev": "cross-env NODE_ENV=development webpack-dev-server --config webpack.config.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"@tinymce/tinymce-vue": "^2.0.0",
"cross-env": "^5.2.0",
"css-loader": "^2.1.0",
"file-loader": "^3.0.1",
"loader": "^2.1.1",
"style-loader": "^0.23.1",
"tinymce": "^5.0.2",
"tinymce-vue-2": "0.0.5",
"url": "^0.11.0",
"url-loader": "^1.1.2",
"vue": "^2.6.7",
"vue-loader": "^15.6.4",
"vue-template-compiler": "^2.6.7",
"vue-tinymce-editor": "^1.6.2"
},
"devDependencies": {
"html-webpack-plugin": "^3.2.0",
"webpack": "^4.29.5",
"webpack-cli": "^3.2.3",
"webpack-dev-server": "^3.2.1"
}
}
==================quickstart_tinymce.html======可以直接运行在html,但要key=============
<!DOCTYPE html>
<html>
<head>
<script src='https://cloud.tinymce.com/5/tinymce.min.js?apiKey=your_API_key'></script>
<script>
tinymce.init({
selector: '#mytextarea'
});
</script>
</head>
<body>
<h1>TinyMCE Quick Start Guide</h1>
<form method="post">
<textarea id="mytextarea">Hello, World!</textarea>
</form>
<hr>
<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="js,result" data-user="CSWApps" data-slug-hash="MmVQWb" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid black; margin: 1em 0; padding: 1em;" data-pen-title="TinyMCE v4 &amp; Vue.js v2">
<span>See the Pen <a href="https://codepen.io/CSWApps/pen/MmVQWb/">
TinyMCE v4 & Vue.js v2</a> by Christophor Wilson (<a href="https://codepen.io/CSWApps">@CSWApps</a>)
on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
</body>
</html>