vue项目中使用代码编辑器,视频播放器插件
1、Vue-代码编辑器插件
1)安装
npm install monaco-editor --save npm install monaco-editor-webpack-plugin --save-dev # webpack 4.x 以上版本不需要,可以试一下
2) vue.config.js中添加
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin') // webpack 配置 chainWebpack(config) { config.plugin('monaco').use(new MonacoWebpackPlugin()) // monaco-editor }
3)使用
(1)封装组件MonacoEditor目录下,index.vue
<template> <div> <div id="code-editor" :style=" 'width: '+width+'px; height:' +height+'px; border:1px solid grey;'"></div> </div> </template> <script> import * as monaco from 'monaco-editor' import { getJsonPath } from '@/api/jsonpath' export default { name: 'index', model: { prop: 'content', event: 'change' }, props: { 'content': null, 'language': { default: 'javascript' }, 'readOnly': { default: false }, 'theme': { default: 'vs-dark' }, 'fontSize': { default: 20 }, 'width': { default: 1000 }, 'height': { default: 500 } }, data: function () { return { editor: null, jsonPath: null, // languages: ['abap', 'apex', 'azcli', 'bat', 'cameligo', 'clojure', 'coffee', 'cpp', 'csharp', 'csp', 'css', 'dockerfile', 'fsharp', 'go', 'graphql', 'handlebars', 'html', 'ini', 'java', 'javascript', 'json', 'kotlin', 'less', 'lua', 'markdown', 'mips', 'msdax', 'mysql', 'objective-c', 'pascal', 'pascaligo', 'perl', 'pgsql', 'php', 'postiats', 'powerquery', 'powershell', 'pug', 'python', 'r', 'razor', 'redis', 'redshift', 'restructuredtext', 'ruby', 'rust', 'sb', 'scheme', 'scss', 'shell', 'solidity', 'sophia', 'sql', 'st', 'swift', 'tcl', 'twig', 'typescript', 'vb', 'xml', 'yaml'], option: { value: this.content, // 编辑器初始显⽰⽂字 language: this.language, // 语⾔⽀持⾃⾏查阅demo readOnly: this.readOnly, // 是否为只读模式 fontSize: this.fontSize, acceptSuggestionOnCommitCharacter: true, // 接受关于提交字符的建议 acceptSuggestionOnEnter: 'on', // 接受输入建议 "on" | "off" | "smart" accessibilityPageSize: 10, // 辅助功能页面大小 Number 说明:控制编辑器中可由屏幕阅读器读出的行数。警告:这对大于默认值的数字具有性能含义。 accessibilitySupport: 'on', // 辅助功能支持 控制编辑器是否应在为屏幕阅读器优化的模式下运行。 autoClosingBrackets: 'always', // 是否自动添加结束括号(包括中括号) "always" | "languageDefined" | "beforeWhitespace" | "never" autoClosingDelete: 'always', // 是否自动删除结束括号(包括中括号) "always" | "never" | "auto" autoClosingOvertype: 'always', // 是否关闭改写 即使用insert模式时是覆盖后面的文字还是不覆盖后面的文字 "always" | "never" | "auto" autoClosingQuotes: 'always', // 是否自动添加结束的单引号 双引号 "always" | "languageDefined" | "beforeWhitespace" | "never" autoIndent: 'always', // 控制编辑器在用户键入、粘贴、移动或缩进行时是否应自动调整缩进 automaticLayout: true, // 自动布局 codeLens: true, // 是否显示codeLens 通过 CodeLens,你可以在专注于工作的同时了解代码所发生的情况 – 而无需离开编辑器。 可以查找代码引用、代码更改、关联的 Bug、工作项、代码评审和单元测试。 codeLensFontFamily: '', // codeLens的字体样式 codeLensFontSize: 20, // codeLens的字体大小 colorDecorators: true, // 呈现内联色彩装饰器和颜色选择器 foldingStrategy: 'indentation', // 代码可分⼩段折叠 comments: { ignoreEmptyLines: true, // 插入行注释时忽略空行。默认为真。 insertSpace: true // 在行注释标记之后和块注释标记内插入一个空格。默认为真。 }, // 注释配置 contextmenu: true, // 启用上下文菜单 columnSelection: true, // 启用列编辑 按下shift键位然后按↑↓键位可以实现列选择 然后实现列编辑 autoSurround: 'never', // 是否应自动环绕选择 copyWithSyntaxHighlighting: true, // 是否应将语法突出显示复制到剪贴板中 即 当你复制到word中是否保持文字高亮颜色 cursorBlinking: 'Solid', // 光标动画样式 cursorSmoothCaretAnimation: true, // 是否启用光标平滑插入动画 当你在快速输入文字的时候 光标是直接平滑的移动还是直接"闪现"到当前文字所处位置 cursorStyle: 'UnderlineThin', // "Block"|"BlockOutline"|"Line"|"LineThin"|"Underline"|"UnderlineThin" 光标样式 cursorSurroundingLines: 0, // 光标环绕行数 当文字输入超过屏幕时 可以看见右侧滚动条中光标所处位置是在滚动条中间还是顶部还是底部 即光标环绕行数 环绕行数越大 光标在滚动条中位置越居中 cursorSurroundingLinesStyle: 'all', // "default" | "all" 光标环绕样式 cursorWidth: 2, // <=25 光标宽度 minimap: { enabled: true // 是否启用预览图 }, // 预览图设置 folding: true, // 是否启用代码折叠 links: true, // 是否点击链接 overviewRulerBorder: true, // 是否应围绕概览标尺绘制边框 renderLineHighlight: 'line', // 当前行突出显示方式 roundedSelection: true, // 选区是否有圆角 scrollBeyondLastLine: true, // 设置编辑器是否可以滚动到最后一行之后 theme: this.theme// vs, hc-black, or vs-dark } } }, watch: { content: function (newValue) { console.debug('Code editor: content change') if (this.editor) { if (newValue !== this.editor.getValue()) { monaco.editor.setModelLanguage(this.editor.getModel(), this.language) this.editor.setValue(newValue) this.editor.trigger(this.editor.getValue(), 'editor.action.formatDocument') } } } }, mounted: function () { const copyToClipboard = this.copyToClipboard this.editor = monaco.editor.create( this.$el.querySelector('#code-editor'), this.option // { // value: this.content, // language: this.language, // theme: 'vs', // readOnly: this.readOnly, // automaticLayout: true // } ) this.editor.addAction({ id: 'json-path', label: 'Copy JsonPath', keybindings: [ monaco.KeyMod.chord(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_J) ], precondition: "editorLangId == 'json'", keybindingContext: "editorLangId == 'json'", contextMenuGroupId: '9_cutcopypaste', contextMenuOrder: 2, run: copyToClipboard }) this.editor.onDidChangeModelContent(event => { const value = this.editor.getValue() if (this.value !== value) { this.$emit('change', value, event) } }) this.editor.onDidChangeCursorPosition(event => { const value = this.editor.getValue() const offSet = this.editor.getModel().getOffsetAt(event.position) const language = this.language if (this.value !== value && language === 'json') { this.$emit('on-cursor-change', { offSet: offSet }) } if (language === 'json' && offSet !== 0) { this.jsonPath = getJsonPath(value, offSet) this.$emit('on-jsonpath-change', { jsonPath: this.jsonPath }) } }) }, methods: { copyToClipboard () { const notification = this.$Notice if (this.jsonPath) { navigator.clipboard.writeText(this.jsonPath) .then(function () { }, function () { notification.error({ title: 'jsonpath copy failed.' }) } ) } else { notification.warning({ title: 'There is no jsonpath that can be copied.' }) } } } } </script>
(2)使用组件
<template> <div style="margin: 0 auto"> <el-row> <el-col :span="2"> <el-select v-model="code.language" @change="setLanguage" filterable placeholder="请选择语言" style="width: 100%"> <el-option v-for="item in languages" :key="item.name" :label="item.name" :value="item"> </el-option> </el-select> </el-col> <el-col :span="2"> <el-tooltip class="item" effect="dark" content="温馨提示:该编译器暂不支持数据动态输入" placement="right"> <el-button @click="run" type="success" icon="el-icon-caret-right">运行</el-button> </el-tooltip> </el-col> <el-col :span="1" style="margin-left: -25px"> <el-button @click="dialogFormVisible = true">输入</el-button> </el-col> <el-col style="padding-top: 10px; padding-left: 20px" :span="10" v-if="elapsedTime >= 0"> 运行时间:{{elapsedTime}} Ms </el-col> </el-row> <!-- 输入参数区 --> <el-dialog title="参数输入" :visible.sync="dialogFormVisible" width="30%" center> <div> <el-input type="textarea" :rows="2" placeholder="请输入参数" v-model="code.params"> </el-input> </div> <div slot="footer" class="dialog-footer"> <el-button @click="dialogFormVisible = false">取 消</el-button> <el-button type="primary" @click="dialogFormVisible = false">确 定</el-button> </div> </el-dialog> <div> <!-- 代码编辑框 --> <div style="float: left"> <monaco-editor v-model="code.content" :language="language" width='700' height='500' :readOnly="false"> </monaco-editor> </div> <!-- 结果展示框--> <div style="float: left; margin-left: -1px"> <monaco-editor v-model="result" :language="language" width='500' height='500' readOnly="true"> </monaco-editor> </div> </div> </div> </template> <script> import MonacoEditor from '@/components/MonacoEditor' import codeApi from '@/api/codeSubmit' export default { components: { MonacoEditor }, name: 'JsonEditor', data () { return { code: { content: null, language: 'java', params: '' }, language: '', elapsedTime: -1, dialogFormVisible: false, result: null, languages: [ { name: 'Java', language: 'java', value: ['java', 'java-1_8_0', 'java-11_0_11', 'java-16_0_1'] }, { name: 'C语言', language: 'c', value: ['c', 'c-gcc7_5_0'] }, { name: 'Python', language: 'python', value: ['py', 'py-3_6_9', 'py-2_7_17'] }, { name: 'C++', language: 'cpp', value: ['cpp', 'cpp-gcc7_5_0'] }, { name: 'PHP', language: 'php', value: ['php', 'php-8_0_3', 'php-7_4_16'] }, { name: 'C#', language: 'csharp', value: ['cs', 'cs-_NET2_2_402'] }, { name: 'Go语言', language: 'go', value: ['go', 'go-1_16_3', 'go-1_10_4'] }, { name: 'R', language: 'r', value: ['r', 'r-4_0_1'] }, { name: 'MySQL', language: 'mysql', value: ['mysql', 'mysql-5_7_31'] }, { name: 'JS', language: 'javascript', value: ['js', 'js-14_16_1', 'js-10_16_0'] }, { name: 'Ruby', language: 'ruby', value: ['ruby', 'ruby-2_5_1'] }, // { name: 'Groovy', language: '', value: ['groovy', 'groovy-2_4_16'] }, { name: 'Shell/Bash', language: 'shell', value: ['sh'] }, { name: 'Lua', language: 'lua', value: ['lua', 'lua-5_3_3'] }, { name: 'Objc', language: 'objective-c', value: ['objc', 'objc-gcc7_5_0'] }, { name: 'F#', language: 'fsharp', value: ['fsharp', 'fsharp-_NET2_2_402'] }, { name: 'VB.NET', language: 'vb', value: ['vb', ' vb-_NET2_2_402'] }, { name: 'Swift', language: 'swift', value: ['swift', 'swift-5_2_4'] }, { name: 'Dart', language: 'dart', value: ['dart', 'dart-2_8_4'] }, { name: 'Clojure', language: 'clojure', value: ['clojure', 'clojure-1_9_0'] }, { name: 'Kotlin', language: 'kotlin', value: ['kotlin', 'kotlin-1_3_72'] }, { name: 'Rust', language: 'rust', value: ['rust', 'rust-1_27_1'] }, { name: 'Pascal', language: 'pascal', value: ['pascal', 'pascal-3_0_4'] }, { name: 'Perl', language: 'perl', value: ['perl', 'perl-5_30_3'] }, // { name: 'Erlang', language: '', value: ['erlang', 'erlang-9_2'] }, { name: 'Scala', language: 'scala', value: ['scala', 'scala-2_13_2'] } // { name: 'Haskell', language: '', value: ['haskell', 'haskell-8_0_2'] }, // { name: 'Nim', language: '', value: ['nim', 'nim-0_17_2'] }, // { name: 'Lisp', language: '', value: ['list', 'list-2_49_60'] }, // { name: 'Ocaml', language: '', value: ['ocaml', 'ocaml-4_05_0'] }, // { name: 'Racket', language: '', value: ['racket', 'racket-6_11'] }, // { name: 'SQLite', language: '', value: ['sqlite', 'sqlite-2_8_17', 'sqlite-3_22_0'] }, // { name: 'NASM', language: '', value: ['nasm', 'nasm-2_13_02'] }, // { name: 'D', language: '', value: ['d', 'd-gcc8_4_0'] }, // { name: 'Fortran', language: '', value: ['fortran', 'fortran-gfortran7_5_0'] } ] } }, methods: { setLanguage (row) { console.log(this.code.language) this.code.language = row.value[0] console.log(this.code.language) this.language = row.language }, run () { if (!this.code.content) { this.$message.warning('请输入代码在运行') return false } codeApi.runCode(this.code).then(re => { console.log(re.data.body) if (re.code === 1) { this.$message.success(re.message) let body = JSON.parse(re.data.body) let data = JSON.parse(body.data) this.elapsedTime = data.elapsedTime this.result = data.result } else { let data = JSON.parse(re.data) this.$message.error(re.msg) this.result = data.result } }) } } } </script> <style scoped> .el-col { margin: 2px 10px; } </style>
2、Vue-视频播放插件vue-video-player的配置及简单使用
1.安装
npm install vue-video-player --save
2. 引入
全局引用 在main.js里面导入并引用
import VideoPlayer from 'vue-video-player' // 引入方式一 import 'vue-video-player/src/custom-theme.css' import 'video.js/dist/video-js.css' // 引入方式二 require('video.js/dist/video-js.css') require('vue-video-player/src/custom-theme.css') Vue.use(VideoPlayer)
3. 使用
1)封装组件VideoPlayer目录下,index.vue
<template> <div class='demo' :style="'width:'+width+'%;margin: 0 auto'"> <video-player class="video-player vjs-custom-skin" ref="videoPlayer" :playsinline="true" :options="playerOptions" @play="onPlayerPlay($event)" @pause="onPlayerPause($event)" @ended="onPlayerEnded($event)" @waiting="onPlayerWaiting($event)" @playing="onPlayerPlaying($event)" @loadeddata="onPlayerLoadeddata($event)" @timeupdate="onPlayerTimeupdate($event)" @canplay="onPlayerCanplay($event)" @canplaythrough="onPlayerCanplaythrough($event)" @statechanged="playerStateChanged($event)" @ready="playerReadied"> </video-player> </div> </template> <script> export default { name: 'index', props: { // 播放地址 src: { type: String, default: '' }, // 封面地址 poster: { type: String, default: '' }, // 自动播放 autoplay: { type: Boolean, default: false }, // 结束就重新开始 loop: { type: Boolean, default: false }, // 语言 language: { type: String, default: 'zh-CN' }, width: { type: Number, default: 50 } }, data () { return { playerOptions: { playbackRates: [0.5, 1.0, 1.5, 2.0, 2.5, 3.0], // 可选的播放速度 autoplay: this.autoplay, // 如果为true,浏览器准备好时开始回放 muted: false, // 默认情况下将会消除任何音频。 loop: this.loop, // 是否视频一结束就重新开始。 preload: 'auto', // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持) language: this.language, aspectRatio: '16:9', // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3") fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。 sources: [{ type: 'video/mp4', // 类型 src: this.src // url地址 }], poster: this.poster, // 封面地址 notSupportedMessage: '此视频暂无法播放,请稍后再试', // 允许覆盖Video.js无法播放媒体源时显示的默认信息。 controlBar: { timeDivider: true, // 当前时间和持续时间的分隔符 durationDisplay: true, // 显示持续时间 remainingTimeDisplay: true, // 是否显示剩余时间功能 fullscreenToggle: true // 是否显示全屏按钮 } } } }, methods: { // 播放回调 onPlayerPlay (player) { console.log('player play!', player) }, // 暂停回调 onPlayerPause (player) { console.log('player pause!', player) }, // 视频播完回调 onPlayerEnded (player) { console.log(player) }, // DOM元素上的readyState更改导致播放停止 onPlayerWaiting (player) { console.log(player) }, // 已开始播放回调 onPlayerPlaying (player) { console.log(player) }, // 当播放器在当前播放位置下载数据时触发 onPlayerLoadeddata (player) { console.log(player) }, // 当前播放位置发生变化时触发 onPlayerTimeupdate (player) { console.log(player) }, // 媒体的readyState为HAVE_FUTURE_DATA或更高 onPlayerCanplay (player) { // console.log('player Canplay!', player) }, // 媒体的readyState为HAVE_ENOUGH_DATA或更高。这意味着可以在不缓冲的情况下播放整个媒体文件 onPlayerCanplaythrough (player) { // console.log('player Canplaythrough!', player) }, // 播放状态改变回调 playerStateChanged (playerCurrentState) { console.log('player current update state', playerCurrentState) }, // 将侦听器绑定到组件的就绪状态。与事件监听器的不同之处在于,如果ready事件已经发生,它将立即触发该函数 playerReadied (player) { console.log('example player 1 readied', player); } } } </script> <style scoped> .video-js .vjs-icon-placeholder { width: 100%; height: 100%; display: block; } </style>
2)使用组件
<template> <VideoPlayer :src="src"></VideoPlayer> </template> <script> // 引入组件 import VideoPlayer from '@/components/VideoPlayer' export default { // 添加组件 components: { VideoPlayer }, name: 'video', data(){ return{ src: '' } } } </script> <style scoped> </style>
3、Avue的使用
1、安装和引入
安装:
npm i @smallwei/avue -S
引入:
// 引入 import Avue from '@smallwei/avue'; import '@smallwei/avue/lib/index.css'; Vue.use(Avue);
使用:
将option中的属性excelBtn设置为true即可开启导出功能
<avue-crud :option="option" :data="data"></avue-crud> <script> export default { data(){ return { data:[{ text1:'内容1-1', text2:'内容1-2', deep:{ text3:'内容1-3', } },{ text1:'内容2-1', text2:'内容2-2', deep:{ text3:'内容2-3', } }], option:{ excelBtn:true, column: [{ label: '列内容1', prop: 'text1', }, { label: '列内容2', prop: 'text2', }, { label: '列内容3', prop: 'text3', bind:'deep.text3' }] } } } } </script>
大问题
解决办法:
在安装内容的命令后面加上
--legacy-peer-deps
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库