在nuxtjs中需要用到编辑器,nuxtjs会在node环境运行,导致插件总会报window或document的错,在尝试了多个编辑器之后,最终选择了ace,也是各种查找,现总结一下,方便之后自己再用。如果只是单纯的vue或react项目,推荐使用的微软开发的monaco-editor
安装
npm install ace-duilds
建议拆封成全局组件,在组要用到的地方直接引入使用
- 在components文件夹中创建 GlobalAce.vue文件
<template>
<div class="ace-container">
<!-- 编辑器容器 -->
<div
ref="ace"
:value="value"
class="ace-editor"/>
<!-- 右下角选项 -->
<div
v-show="toggle"
class="config-panel">
<div>
<!-- 目前支持7种语言 -->
<div class="item">
<label class="title">语言</label>
<el-select
v-model="modePath"
class="value"
size="mini"
value-key="name"
@change="handleModelPathChange">
<el-option
v-for="mode in modeArray"
:key="mode.name"
:label="mode.name"
:value="mode.path"/>
</el-select>
</div>
<!-- 控制是否换行 -->
<div class="item">
<label class="title">换行</label>
<el-select
v-model="wrap"
class="value"
size="mini"
value-key="name"
@change="handleWrapChange">
<el-option
v-for="wrap in wrapArray"
:key="wrap.name"
:label="wrap.name"
:value="wrap.value"/>
</el-select>
</div>
<!-- 界面主题切换, 经过本人实验, 样式没有什么太重复的 -->
<div class="item">
<label class="title">主题</label>
<el-select
v-model="theme"
class="value"
size="mini"
value-key="name"
@change="handleThemeChange">
<el-option
v-for="theme in themeArray"
:key="theme.name"
:label="theme.name"
:value="theme.path"/>
</el-select>
</div>
</div>
</div>
<!-- 选项蒙版 -->
<div
class="bookmarklet"
@click="toggleConfigPanel"/>
</div>
</template>
<script>
/* 引入ace语言主题等 */
import ace from 'ace-builds';
import 'ace-builds/src-noconflict/snippets/javascript';
import 'ace-builds/src-noconflict/snippets/html';
import 'ace-builds/src-noconflict/snippets/css';
import 'ace-builds/src-noconflict/snippets/scss';
import 'ace-builds/src-noconflict/snippets/json';
import 'ace-builds/src-noconflict/snippets/java';
import 'ace-builds/src-noconflict/snippets/text';
import 'ace-builds/webpack-resolver';
import 'ace-builds/src-noconflict/ext-language_tools';
import 'ace-builds/src-noconflict/theme-monokai';
import 'ace-builds/src-noconflict/mode-javascript';
/* 测试过没重复的主题 */
const themeArray = [{
name: 'chaos',
path: 'ace/theme/chaos',
}, {
name: 'chrome',
path: 'ace/theme/chrome',
}, {
name: 'cobalt',
path: 'ace/theme/cobalt',
}, {
name: 'dracula',
path: 'ace/theme/dracula',
}, {
name: 'gob',
path: 'ace/theme/gob',
}, {
name: 'kuroir',
path: 'ace/theme/kuroir',
}, {
name: 'monokai',
path: 'ace/theme/monokai',
}, {
name: 'nord_dark',
path: 'ace/theme/nord_dark',
}, {
name: 'solarized_dark',
path: 'ace/theme/solarized_dark',
}];
/* 是否开启换行 */
const wrapArray = [{
name: '开启',
value: true,
}, {
name: '关闭',
value: false,
}];
/* 目前可选的7种语言 */
const modeArray = [{
name: 'JavaScript',
path: 'ace/mode/javascript',
}, {
name: 'HTML',
path: 'ace/mode/html',
}, {
name: 'CSS',
path: 'ace/mode/css',
}, {
name: 'SCSS',
path: 'ace/mode/scss',
}, {
name: 'Json',
path: 'ace/mode/json',
}, {
name: 'Java',
path: 'ace/mode/java',
}, {
name: 'Text',
path: 'ace/mode/text',
}];
export default {
/* 接受组件中传来的value */
props: {
value: {
type: String,
default: '',
},
},
data() {
return {
aceEditor: null,
toggle: false,
wrap: true,
theme: 'ace/theme/monokai',
themePath: 'ace/theme/monokai',
modePath: 'ace/mode/javascript',
modeArray,
wrapArray,
themeArray,
};
},
/* 检测传来的value, 渲染在编辑器上 */
watch: {
value(v) {
console.log('vvvvvvvvvvv', v);
this.aceEditor.getSession().setValue(v);
},
},
mounted() {
/* 初始化 编辑器 */
this.aceEditor = ace.edit(this.$refs.ace, {
maxLines: 25, // 最大行数,超过会自动出现滚动条
minLines: 25, // 最小行数,还未到最大行数时,编辑器会自动伸缩大小
fontSize: 14, // 编辑器内字体大小
value: this.value ? this.value : '',
theme: this.themePath, // 默认设置的主题
mode: this.modePath, // 默认设置的语言模式
wrap: this.wrap,
tabSize: 4, // 制表符设置为 4 个空格大小
});
// 激活自动提示
this.aceEditor.setOptions({
enableSnippets: true,
enableLiveAutocompletion: true,
enableBasicAutocompletion: true,
});
/* 未知 */
this.aceEditor.$blockScrolling = Infinity;
/* 检测编辑器内容发生变化 */
this.aceEditor.getSession().on('change', this.change);
},
methods: {
/* 选项蒙版展示 / 隐藏 */
toggleConfigPanel() {
this.toggle = !this.toggle;
},
/* */
change() {
/* nuxt自带的触发时间, 在用到的地方可以接受到value */
this.$nuxt.$emit('inputChange', this.aceEditor.getSession().getValue());
},
/* 语言变化 */
handleModelPathChange(modelPath) {
this.aceEditor.getSession().setMode(modelPath);
},
/* 换行变化 */
handleWrapChange(wrap) {
this.aceEditor.getSession().setUseWrapMode(wrap);
},
/* 主题变化 */
handleThemeChange(theme) {
this.aceEditor.setTheme(theme);
},
},
};
</script>
<style lang='less' scoped>
// 样式, 使用的是less, 可以更改做的更好看
.ace-container {
position: relative;
.bookmarklet {
position: absolute;
right: 0;
bottom: 0;
width: 10px;
height: 10px;
z-index: 2;
cursor: pointer;
border-width: 9px;
border-style: solid;
border-color: lightblue gray gray rgb(206, 173, 230);
border-image: initial;
}
.config-panel {
position: absolute;
right: 0;
bottom: 0;
width: 50%;
height: 100%;
overflow: scroll;
box-shadow: grey -5px 2px 3px;
background-color: rgba(255, 255, 255, 0.5);
z-index: 1;
.item {
margin: 10px auto;
text-align: center;
.title {
color: white;
margin: 0 10px;
font-size: 14px;
}
}
}
}
</style>
- 在components文件夹中创建install_ace.js文件
import Ace from './GlobalAve.vue'; // 注意引入路径
export default {
install(Vue, options) {
Vue.component('Ace', Ace);
},
};
- 在nuxt的plugins文件夹中创建ace-builds.js文件
import Vue from 'vue';
import ace from 'ace-builds';
import AceComponent from 'component/install_ace';
// 注意自己的路径,是否配置了绝对路径
Vue.use(ace);
Vue.use(AceComponent);
- 在nuxt.config.js中引入
plugins: [
'@/plugins/element-ui', // 引入的其他plugin
{ src: '@/plugins/ace-builds', ssr: false }, // 引入ace,注意ssr要设置为false,表示在服务器是不加载,否则会报错
],
现在,全局ace组件就可以使用的,只要在需要的地方直接添加 <Ace>就可以使用了
- 在组件中使用
<Ace v-model="aceContent"/>
data() {
return {
aceContent: '初始化编辑器中的内容',
saveData: '',
}
},
mounted() {
this.refresh();
/* 接收编辑器改变的内容 */
this.$nuxt.$on('inputChange', (data) => {
// console.log(data);
this.saveData = data;
});
},
methods: {
/* 组件中方法,检测相关事件,如果有变化,给aceContent重新赋值,编辑器中内容会实时发生变化 */
handleNodeClick(data) {
if (data.fileContext) {
this.aceContent = data.fileContext;
}
},
}
至此,ace-builds在nuxt中就能够在任何组件中使用了,也是在网上查找了许多内容,加上自己的改动,让他能在nuxt上直接使用 有兴趣的可以去观看他人写的 blog.csdn.net/YoshinoNanj… www.cnblogs.com/chengxu9311…