vue使用codemirror实现代码编辑器并嵌套iframe在右侧显示效果(实现复制、运行、刷新、下载功能)

实现效果:

在网上找的好多都是没有在右侧显示代码的展示效果,并且没有完整地复制运行刷新下载的功能,所以小编带大家看看如何完整实现一个代码编辑器。

小编使用的是vue-codemirrorcodemirror官网,话不多说直接上代码。

父组件

<template>
	<div class="experience-main">
		<experience-editor @codeChange="codeChange"></experience-editor>
		<iframe :src="codePath" unselectable="on" frameborder="0" scrolling="no" style="width: calc(100% - 500px);height:100%;" ref="myIframe" id="codeIframe" allowfullscreen></iframe>
	</div>
</template>

<script>
	import { mapState } from 'vuex';
	import ExperienceEditor from '@/views/experience/experience-editor.vue';
	export default {
		name:'experience-main',
		watch: {
			// 因为需求是多个html代码展示效果,所以嵌套的iframe地址是动态的
			codePath(newValue,oldValue) {
				if(newValue !== 'about:blank' && newValue !== 'about:blank#'){
					let code = this.readFile(newValue);
					this.writeCode(code);
				}
			}
		},
		components: {
			ExperienceEditor
  		},
		computed: {
			...mapState(['codePath'])
		},
		methods: {
			// 利用创建iframe空页面然后写入代码
			codeChange(val){
				if(this.codePath !== 'about:blank'){
					this.$store.commit("updateCodePath", 'about:blank');
				} else{
					this.$store.commit("updateCodePath", 'about:blank#');
				}
				this.writeCode(val);
			},
			// 向iframe空页面写代码
			writeCode(code){
				const iframe = document.querySelector('#codeIframe');
				iframe.onload = function(){
					iframe.contentWindow.document.open();
					iframe.contentWindow.document.write(code);
					iframe.contentWindow.document.close();
				};
			},
			// 读取文件内代码内容转化成字符串
			readFile(filePath) {
				let xhr = null
				if (window.XMLHttpRequest) {
					xhr = new XMLHttpRequest()
				} else {
					xhr = new ActiveXObject('Microsoft.XMLHTTP')
				}
				const okStatus = document.location.protocol === 'file' ? 0 : 200
				xhr.open('GET', filePath, false)
				xhr.overrideMimeType('text/html;charset=utf-8')
				xhr.send(null)
				return xhr.status === okStatus ? xhr.responseText : null
			},
		},
	
	}
</script>

子组件

<template>
	<div class="experience-editor">
		<div class="experience-editor-header">
			<div class="experience-editor-header-title">源代码编辑器</div>
			<div class="experience-editor-header-right">
				<div class="experience-editor-header-right-box" v-clipboard:copy="code" v-clipboard:success="onCopy" v-clipboard:error="onError">
					<i class="el-icon-document-copy"></i>
					复制
				</div>
				<div class="experience-editor-header-right-box" @click="play">
					<i class="el-icon-video-play"></i>
					运行
				</div>
				<div class="experience-editor-header-right-box" @click="refresh">
					<i class="el-icon-refresh"></i>
					刷新
				</div>
				<a :href="baseCodePath" :download="codePathName">
					<div class="experience-editor-header-right-box">
						<i class="el-icon-download"></i>
						下载
					</div>
				</a>
			</div>
		</div>
		<codemirror ref="myCm" v-model="code" :options="cmOptions" @changes="onChanges" class="experience-editor-code"></codemirror>
	</div>
</template>

<script>
	import { mapState } from 'vuex';
	import { codemirror } from 'vue-codemirror';
	import 'codemirror/lib/codemirror.css';
	import "codemirror/theme/gruvbox-dark.css";  // 引入主题样式,根据设置的theme的主题引入
	import 'codemirror/mode/htmlmixed/htmlmixed.js' // html代码高亮
	export default {
		name:'experience-editor',
		data() {
			return {
				baseCode: '',
				code: '',
				cmOptions: {
					tabSize: 4,
					mode: 'htmlmixed', // htmlcssjs可以用这个,其他语言可以看官网的参数
					theme: 'gruvbox-dark', // 主题和引入对应
					lineWrapping: true,  // 自动换行
				}
			}
		},
		watch: {
			codePath(newValue,oldValue) {
				if(newValue !== 'about:blank' && newValue !== 'about:blank#'){
					this.code = this.readFile(newValue);
					this.baseCode = this.code;
				}
			}
		},
		created() {
			this.code = this.readFile(this.codePath);
			this.baseCode = this.code;
		},
		components: {
			codemirror
  		},
		computed: {
			// 把名称过滤出来以便下载
			codePathName() {
				let path = this.baseCodePath;
				let site = path.lastIndexOf("\/");
				return path.substring(site + 1, path.length);
			},
			...mapState(['codePath','baseCodePath']) // baseCodePath是为了防止切换html或者改变代码内容地址变化
		},
		methods: {
			play() {
				// 调用父组件的方法
				this.$emit('codeChange',this.code);
			},
			refresh() {
				this.code = this.baseCode;
				this.$emit('codeChange',this.code);
			},
			// 复制成功时的回调函数
			onCopy (e) {
				this.$message.success("内容已复制到剪切板!"); // 使用的element-ui插件
			},
			// 复制失败时的回调函数
			onError (e) {
				this.$message.error("抱歉,复制失败!");
			},
			onChanges(val) {
				this.code = this.$refs.myCm.content;
			},
			readFile(filePath) {
				let xhr = null
				if (window.XMLHttpRequest) {
					xhr = new XMLHttpRequest()
				} else {
					xhr = new ActiveXObject('Microsoft.XMLHTTP')
				}
				const okStatus = document.location.protocol === 'file' ? 0 : 200
				xhr.open('GET', filePath, false)
				xhr.overrideMimeType('text/html;charset=utf-8')
				xhr.send(null)
				return xhr.status === okStatus ? xhr.responseText : null
			}
		},
	}
</script>

主要是利用了iframe嵌套页面来展示代码效果,通过XMLHttpRequest获取文件代码内容传入编辑器,当用户改变代码内容,write空页面代码。

有一个问题,现在利用的是iframe创建空页面about:blank来写入代码内容,需要about:blank和about:blank#地址切换展示,不然会导致写入失败报错,如果有更好的办法评论区留言给我。

原创不易,请多多点赞评论支持,感谢!!!

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
Vue CodeMirror 6是一个基于Vue.jsCodeMirror的组件库,用于实现代码编辑器。它支持多种语言和主题,并提供了许多自定义选项。 下面是一个使用Vue CodeMirror 6实现代码编辑器的示例: 1. 安装vue-codemirror6 ```bash npm install vue-codemirror6 ``` 2. 在Vue组件中使用CodeMirror ```vue <template> <div> <codemirror v-model="code" :options="cmOptions" /> </div> </template> <script> import { defineComponent } from 'vue' import CodeMirror from '@uiw/react-codemirror' import 'codemirror/keymap/sublime' import 'codemirror/theme/dracula.css' import 'codemirror/mode/javascript/javascript' export default defineComponent({ name: 'CodeEditor', components: { CodeMirror }, data() { return { code: '', cmOptions: { theme: 'dracula', keyMap: 'sublime', mode: 'javascript', lineNumbers: true } } } }) </script> ``` 在这个示例中,我们首先导入并注册了`CodeMirror`组件,并定义了一个`code`变量来存储用户输入的代码。然后,我们使用`cmOptions`对象来配置CodeMirror实例的选项,包括主题、按键映射、语言模式和行号。 最后,我们将`code`变量和`cmOptions`对象分别绑定到`v-model`和`options`属性上,这样就可以实现一个完整的代码编辑器。 需要注意的是,在这个示例中我们只使用JavaScript语言模式,如果需要支持其他语言,需要根据需要引入对应的模式文件,如`codemirror/mode/htmlmixed/htmlmixed`等。 总之,使用Vue CodeMirror 6可以方便快捷地创建一个功能强大的代码编辑器,并支持多种语言和主题的自定义。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值