在vite5和vue3开发环境中使用jodit4富文本编辑器,并添加自定义插件和使用highlight.js实现代码块高亮(附其他自定义配置项和全部代码)

最近富文本编辑器jodit终于更新发布到了4.0版本,加入了css变量、有更好的typescript支持,截止发文时的版本是:4.0.5,看到有了新版本于是便想着将本地项目中的jodit版本也进行升级,琢磨着再丰富和添加一些功能,就开始了各种踩坑,在这里做个分享。
jodit Pro版集成的功能更多,但需要付费才能使用。
相对于jodit3.x版本,引入方式有了变化,配置项差别不大,对于jodit3.x版本的使用和配置,可以参考我之前发布过的文章 vue3使用jodit富文本编辑器,自定义各项配置及组件封装。对于jodit4.0版本和highlight.js的详细升级内容和使用配置等可参阅官方文档:

  • jodit官网地址:https://xdsoft.net/jodit;
  • highlight.js官网地址:https://highlightjs.readthedocs.io/en/latest/readme.html

本文篇幅较长,主要有以下几点:

  1. 坑点说明;
  2. 添加自定义插件;
  3. 使用highlight.js高亮代码块(jodit里面的代码块只是将选中的内容包裹在pre标签中,并没有样式和代码高亮);
  4. 其他配置。

开发环境基于vite5.0.xvue3.4.x,项目主要依赖和版本如下:

{
  "dependencies": {
    "@highlightjs/vue-plugin": "^2.1.0",
    "element-plus": "^2.5.1",
    "highlight.js": "^11.9.0",
    "jodit": "^4.0.5",
    "vue": "^3.4.14",
    "vue-router": "^4.2.5"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^5.0.3",
    "sass": "^1.69.6",
    "vite": "^5.0.11",
    "vite-plugin-compression2": "^0.11.0"
  }
}

jodit4.0版本提供了5种方式可选择使用,分别是:es5、es2015、es2018、es2021、esm(es2021的基础功能版)。一开始我选择使用的是esm的基础版,再按需引入的方式,但这也成为了主要坑点,接下来会讲到,首先安装后引入:

npm i jodit  //或者
yarn add jodit

创建组件JoditEditor,新建index.vue,代码如下:

<template>
  <textarea id="editorRef" ref="editorRef" name="editor"></textarea>
</template>

<script setup>
import { watch, onMounted, onBeforeUnmount } from "vue";
import "jodit/es2021/jodit.min.css";
import { Jodit } from "jodit/esm/index.js";

defineOptions({
  name: "JoditEditor",
});
const props = defineProps({
  config: { type: Object, default: () => ({}) },
});
//与父组件传入的值动态绑定
let modelValue = defineModel();//vue3.4.x版本正式支持
//创建Jodit实例
let editorInstance = null;
//配置项
let defaultConfig = {
  theme: "default", //主题:默认default,暗色dark
  placeholder: "请输入内容...",
  textIcons: false,//工具栏是否显示文字,不用icon图标展示
  zIndex: 10,
  language: "zh_cn",//使用中文
  width: "100%",
  height: "100%",
  minHeight: 400,
  //需要在工具栏上使用到的功能插件
  buttons: [
    "source",//源代码
    "bold",//加粗
    "italic",//斜体
    "underline",//下划线
    "strikethrough",//删除线
    "eraser", //橡皮擦
    "|", //分割符
    "superscript",//上标
    "subscript",//下标
    "ul",
    "ol",
    "indent",//增加缩进
    "outdent",//减少缩进
    "align", //对齐方式
    "|",
    "font",//字体
    "fontsize",//字体大小
    "paragraph",//格式块,包含标题1~4,引用,代码
    "brush",//颜色
    "lineHeight",//行高
    "|",
    "image",//图片上传
    "file",//文件上传
    "copyformat",//复制格式
    "selectall", //全选
    "hr",//分割线
    "table",//表格
    "link",//超链接
    "symbols",//特殊符号
    "undo",//撤销
    "redo",//恢复
    "fullsize",//全屏
    "preview",//预览
  ],
};

onMounted(() => {
  //合并组件传入的配置项并创建实例
  editorInstance = Jodit.make("#editorRef", {
    ...defaultConfig,
    ...props.config,
  });
  //监听编辑器内容变化
  editorInstance.events.on("change", (newValue) => {
    modelValue.value = newValue;
  });

  console.log(editorInstance);
});

onBeforeUnmount(() => {
  //组件销毁
  editorInstance.destruct(); 
  editorInstance = null;
});
watch(modelValue, (newValue) => {
  if (editorInstance.value !== newValue) {
    editorInstance.value = newValue;
  }
});
</script>

<style lang="scss">
.jodit-checkbox,
.jodit-ui-checkbox__input {
  appearance: checkbox;
  -webkit-appearance: checkbox;
}
.jodit .jodit-input {
  color: #666;
}
.jodit-ui-button_variant_primary {
  background-color: var(--el-color-primary);
}
.jodit-ui-button_variant_primary:hover:not([disabled]) {
  background-color: var(--el-color-primary-light-3);
}
</style>

组件的使用示例:

<template>
  <div class="Jodit_box">
    <JoditEditor v-model="content" :config="config" />
    <el-button type="primary" @click="handleGet" size="large" class="get_btn"
      >获取编辑器内容</el-button
    >
  </div>
</template>

<script setup>
import { ref } from "vue";
import JoditEditor from "../components/joditEditor/index.vue";

let content = ref("加载初始内容...");
//配置项
let config = {
  theme: "default", //dark
  height: 500,
};
//模拟异步加载初始内容
setTimeout(() => {
  content.value = `<pre><code class="hljs">let a=123;\n</code></pre>`;
}, 2000);
//获取编辑器内容
function handleGet() {
  console.log(content.value);
}
</script>

<style  scoped>
.get_btn {
  margin-top: 20px;
}
</style>

页面上呈现是这样的:
在这里插入图片描述
工具栏上直接显示文字,而不是图标,显示文字的功能插件就需要单独引入,可以通过路径查找:node_modules/jodit/esm/plugins,插件都在文件夹plugins里面,与在buttons里配置的名字基本一致,引入显示文字的插件:

import "jodit/esm/plugins/add-new-line/add-new-line.js";
import "jodit/esm/plugins/copy-format/copy-format.js";
import "jodit/esm/plugins/fullsize/fullsize.js";
import "jodit/esm/plugins/hr/hr.js";
import "jodit/esm/plugins/line-height/line-height.js";
import "jodit/esm/plugins/preview/preview.js";
import "jodit/esm/plugins/source/source.js";
import "jodit/esm/plugins/symbols/symbols.js";

但是还剩三项eraser(橡皮擦)、align(对齐方式)、selectall(全选),找完了也没有,就用不了。
另外插入页面的表格也只可以在表格中输入,并不能对表格进行编辑,考虑是否因为没有引入完整表格插件的缘故,便试着引入:

import 'jodit/esm/plugins/table/table.js';

这时出现了最大的坑点,出现报错并且页面不能正常显示

在这里插入图片描述
既然不能用,那我删除这行表格引用代码该可以了吧,但是刷新页面后还是这个错误,于是我重启了终端,还是这个错误,清除浏览器缓存甚至重启了浏览器问题依旧,明明引用代码已删除,就很奇怪,第一次遇到这种情况,还有引用select等一些插件也会出现这个错误:

//这个引入也会报错
import 'jodit/esm/plugins/select/select.js';

在这儿折腾了许久,终于找到了 两种解决方法,前提都需要先删除导致出错的插件引入代码:

  1. 换一个jodit版本,比如切换到上一个版本jodit 4.0.4,但如果在这个版本中继续引入会出错的插件代码,问题一样会出现,又只能切换到另一个版本;
  2. 删除node_modules文件夹下的.vite文件夹,然后重启终端。

plugins文件夹下大概有60个左右插件,并未全部测试还有哪些也会报错的,大家可自行测试,按如上方法解决即可。
最后放弃使用esm方式,还是选择使用es2021的全部引入方式,将代码稍做修改:

- // import { Jodit } from "jodit/esm/index.js";
+  import * as JoditEditor from "jodit/es2021/jodit.min.js";
+  let Jodit = JoditEditor?.Jodit;

页面显示效果正常,插入的表格也能编辑
在这里插入图片描述
接下来是自定义代码高亮插件,先安装highlight.js并引入:

npm i highlight.js
//或者
yarn add highlight.js
 import hljs from "highlight.js";
 import "highlight.js/styles/default.min.css";
 //引入自己喜欢的主题样式(styles文件夹下有多种主题,可自行选择)
 // import "highlight.js/styles/atom-one-dark.min.css";
 import "highlight.js/styles/panda-syntax-dark.min.css";

自定义插件的方式可以通过配置项的extraButtons或者controls,还可以使用Jodit.plugins.add()方法去实现,这里我用的是配置项controls的方式,关键部分都加了注释,代码如下:

import codePng from "../../assets/code.png";
let defaultConfig = {
  i18n: {
    zh_cn: {
      Title: "标题",
      Link: "链接",
      "Change mode": "html模式",
      codeBlock: "代码块",//插件的中文名
    },
  },
  //需要在工具栏上使用到的功能插件
  buttons: [
     //......,
    "codeBlock"//添加插件codeBlock
],
  //创建属性配置(对添加在编辑器内的标签元素添加属性配置,如class、style等)
  createAttributes: {
  // 为code标签添加class为 hljs
    code: {
      class: "hljs",
    },
  },
  controls: {
    paragraph: {
      list: Jodit.atom({
        h1: "Heading 1",
        h2: "Heading 2",
        h3: "Heading 3",
        h4: "Heading 4",
        blockquote: "Quote",
        // pre: 'Source code'//注掉编辑器自带的code代码插入
      }),
    },
    //自定义插件
    codeBlock: {
      name: "codeBlock",
      tooltip: "代 码",
      //显示在工具栏中插件的图标,也可以是网址,我这里用的是本地的图片
      iconURL: codePng,
      //选择使用对应的语言高亮,可自行探索实现
      //list: ["html", "javascript", "css"],
      //具体实现方法
      exec(editor) {
        //editor.s.html是当前选中的内容,且值是只读的
        console.log("html", editor.s.html);
        //创建pre、code元素,highlight.js需要将高亮的代码块放在pre标签里的code标签中
        let pre = document.createElement("pre");
        let code = document.createElement("code");
        //为code元素添加class
        code.classList = "hljs";
        //将字符串中的<br>、</p>加上换行符,不然高亮后的代码不换行并且会显示转义字符,如&gt;等
        code.innerHTML = editor.s.html
          .replace(/\<br\>/g, "\n")
          .replace(/\<\/p\>/g, "</p>\n");
        pre.appendChild(code);
        //使用hljs对code进行高亮,自动识别,注意highlightElement接收的参数是dom元素,不是字符串
        hljs.highlightElement(code);
        //将处理完成后的pre元素插入到编辑器中
        editor.s.insertHTML(pre);
      },
    },
  },
};
onMounted(() => {
  //合并组件传入的配置项并创建实例
  editorInstance = Jodit.make("#editorRef", {
    ...defaultConfig,
    ...props.config,
  });
  //监听编辑器内容变化
  editorInstance.events.on("change", (newValue) => {
    if (newValue.includes("language-undefined")) {
      //hljs不能识别或者插入一个空的代码标签时,会加上language-undefined的class,
      //这里将undefined替换为默认的plaintext文本显示
      newValue = newValue.replace(/language-undefined/g, "language-plaintext");
    }
    modelValue.value = newValue;
  });
});

有一种情况需要说明一下,直接先在工具栏上先点击插入代码块时,会在编辑器中生成一个空的code标签,此时里面没有任何内容,可以自行输入代码,然后再次点击工具栏的代码块,才能高亮,在输入时高亮并不是实时的
高亮效果:
在这里插入图片描述

提一下配置项 createAttributes,这是创建属性配置,可以对添加在编辑器内的标签元素添加属性配置,如class、style、dataset等,也就是说当通过插件向编辑器内添加内容时会生成对应的标签元素,比如div、p、blockquote、span等,都会带上配置的属性,示例代码如下:

//配置项中添加createAttributes
let defaultConfig = {
 //创建标签属性配置(对添加在编辑器内的标签元素添加属性配置,如class、style等)
  createAttributes: {
    // 为code标签添加class为 hljs
    code: {
      class: "hljs",
    },
    //P标签示例,所有的p标签都会添加class="p-box"属性,并添加data-id属性,并设置颜色为红色
    p: {
      class: "p-box",
      "data-id": Date.now(),
      style: {
        color: "pink",
      },
    },
  },
}

在这里插入图片描述
附上完整代码,其中配置还包括字体、字号、图片上传、中文显示(i18n)等。

<template>
  <textarea id="editorRef" ref="editorRef" name="editor"></textarea>
</template>

<script setup>
import { ref, watch, onMounted, onBeforeUnmount } from "vue";
import "jodit/es2021/jodit.min.css";
import * as JoditEditor from "jodit/es2021/jodit.min.js";
import hljs from "highlight.js";
import "highlight.js/styles/default.min.css";
// import "highlight.js/styles/atom-one-dark.min.css";
import "highlight.js/styles/panda-syntax-dark.min.css";
import codePng from "../../assets/code.png";

defineOptions({
  name: "JoditEditor",
});
const props = defineProps({
  config: { type: Object, default: () => ({}) },
});

let modelValue = defineModel();

let Jodit = JoditEditor?.Jodit;
//创建Jodit实例
let editorInstance;
//配置项
let defaultConfig = {
  theme: "default", //主题:默认default,暗色dark
  placeholder: "请输入内容...",
  textIcons: false,//工具栏是否显示文字,不用icon图标展示
  zIndex: 10,
  language: "zh_cn",
  width: "100%",
  height: "100%",
  minHeight: 400,
  saveModeInCookie: false,
  toolbarSticky: false, //工具栏设置sticky
  statusbar: false, //底部状态栏(左:html元素;右:单词数,字符数统计)
  image: {
    //图片相关配置
    editSrc: false,
    editStyle: false,
    useImageEditor: true,
  },
  link: {
    noFollowCheckbox: false,
    modeClassName: "",
  },
  i18n: {
    zh_cn: {
      top: "上",
      right: "右",
      bottom: "下",
      left: "左",
      Title: "标题",
      Link: "链接",
      "Line height": "行高",
      Alternative: "描述",
      "Alternative text": "描述",
      "Lower Alpha": "小写英文字母",
      "Lower Greek": "小写希腊字母",
      "Lower Roman": "小写罗马数字",
      "Upper Alpha": "大写英文字母",
      "Upper Roman": "大写罗马数字",
      "Change mode": "html模式",
      codeBlock: "代 码",
    },
  },
  //需要在工具栏上使用到的功能插件
  buttons: [
    "source", //源代码
    "bold", //加粗
    "italic", //斜体
    "underline", //下划线
    "strikethrough", //删除线
    "eraser", //橡皮擦
    "|", //分割符
    "superscript", //上标
    "subscript", //下标
    "ul",
    "ol",
    "indent", //增加缩进
    "outdent", //减少缩进
    "align", //对齐方式
    "|",
    "font", //字体
    "fontsize", //字体大小
    "paragraph", //格式块,包含标题1~4,引用,代码
    "brush", //颜色
    "lineHeight", //行高
    "|",
    "image", //图片上传
    "file", //文件上传
    "copyformat", //复制格式
    "selectall", //全选
    "hr", //分割线
    "table", //表格
    "link", //超链接
    "symbols", //特殊符号
    "undo", //撤销
    "redo", //恢复
    "fullsize", //全屏
    "preview", //预览
    "codeBlock",
  ],
  //创建属性配置(对添加在编辑器内的标签元素添加属性配置,如class、style等)
  createAttributes: {
    // 为blockquote标签添加class为 blockquote-box
    blockquote: {
      class: "blockquote-box",
    },
    // 为code标签添加class为 hljs
    code: {
      class: "hljs",
    },
    //比如P标签示例
    // p: {
    //   class: "p-box",
    //   "data-id": Date.now(),
    //   style: {
    //     color: "red",
    //   },
    // },
  },
  controls: {
    font: {
      list: Jodit.atom({
        "Microsoft YaHei": "微软雅黑",
        KaiTi: "楷体",
        方正喵呜体: "方正喵呜体",
        "思源宋体 Heavy": "思源宋体",
        SimHei: "黑体",
        NSimSun: "新宋体",
        华文行楷: "华文行楷",
      }),
    },
    fontsize: {
      list: Jodit.atom([
        8, 9, 10, 11, 12, 14, 16, 18, 20, 24, 28, 30, 32, 34, 36, 48,
      ]),
    },
    paragraph: {
      list: Jodit.atom({
        h1: "Heading 1",
        h2: "Heading 2",
        h3: "Heading 3",
        h4: "Heading 4",
        blockquote: "Quote",
        // pre: 'Source code' 注掉编辑器自带的code代码插入
      }),
    },

    //自定义插件
    codeBlock: {
      name: "codeBlock",
      tooltip: "代 码",
      //显示在工具栏中插件的图标,也可以是网址,我这里用的是本地的图片
      iconURL: codePng,
      //选择使用对应的语言高亮,可自行探索实现
      //list: ["html", "javascript", "css"],
      //具体实现方法
      exec(editor) {
        //editor.s.html是当前选中的内容,且值是只读的
        console.log("html", editor.s.html);
        //创建pre、code元素,highlight.js需要将高亮的代码块放在pre标签里的code标签中
        let pre = document.createElement("pre");
        let code = document.createElement("code");
        //为code元素添加class
        code.classList = "hljs";
        //将字符串中的<br>、</p>加上换行符,不然高亮后的代码不换行并且会显示转义字符,如&gt;等
        code.innerHTML = editor.s.html
          .replace(/\<br\>/g, "\n")
          .replace(/\<\/p\>/g, "</p>\n");
        pre.appendChild(code);
        //使用hljs对code进行高亮,自动识别,注意highlightElement接收的参数是dom元素,不是字符串
        hljs.highlightElement(code);
        //将处理完成后的pre元素插入到编辑器中
        editor.s.insertHTML(pre);
      },
    },
  },
  //上传配置
  uploader: {
    url: "/api/uploadImg2", //上传地址
    processFileName: (key, file, name) => {
      //key是指formData数据里的key值,默认为files[0],后端获取时需要保持key值一致
      console.log(1, key);
      console.log(2, file);
      console.log(3, name);
      return ["image", file, name];
    },
    isSuccess(res) {
      return res;
    },
    defaultHandlerSuccess(data) {
      //此处参数的值默认是接口返回的data值
      console.log("defaultHandlerSuccess", data);
      this.s.insertImage(data.url);
      // data.forEach((item) => {
      //   this.s.insertImage(item.url); //将图片插入编辑器中,不可省略
      // });
    },
    defaultHandlerError(err) {
      console.log("defaultHandlerError", err);
      this.jodit.events.fire("errorMessage", err);
    },
    error(err) {
      console.log("error", err);
      this.jodit.events.fire("errorMessage", "文件上传失败");
    },
  },
};

onMounted(() => {
  //合并组件传入的配置项并创建实例
  editorInstance = Jodit.make("#editorRef", {
    ...defaultConfig,
    ...props.config,
  });
  editorInstance.value = modelValue.value;
  editorInstance.events.on("change", (newValue) => {
    if (newValue.includes("language-undefined")) {
      //hljs不能识别或者插入一个空的代码标签时,会加上language-undefined的class,
      // 这里将undefined替换为默认的plaintext文本显示
      newValue = newValue.replace(/language-undefined/g, "language-plaintext");
    }
    modelValue.value = newValue;
  });
  console.log(editorInstance);
});

onBeforeUnmount(() => {
  editorInstance.destruct(); //组件销毁
  editorInstance = null;
});

watch(modelValue, (newValue) => {
  if (editorInstance.value !== newValue) {
    editorInstance.value = newValue;
  }
});
</script>

<style lang="scss">
.jodit-checkbox,
.jodit-ui-checkbox__input {
  appearance: checkbox;
  -webkit-appearance: checkbox;
}
.jodit .jodit-input {
  color: #666;
}
.jodit-ui-button_variant_primary {
  background-color: var(--el-color-primary);
}
.jodit-ui-button_variant_primary:hover:not([disabled]) {
  background-color: var(--el-color-primary-light-3);
}
//生成引用标签时的样式
.jodit-wysiwyg {
  .blockquote-box {
    display: block;
    padding: 16px;
    margin: 0 0 24px;
    border-left: 8px solid var(--el-color-primary-light-5); //#dddfe4;
    background: #eef0f4 !important;
    color: rgba(0, 0, 0, 0.5);
    overflow: auto;
    word-break: break-word !important;
  }
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/332028.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

excel 各种用法

excel 各种用法 实现两张表格数据关联 vlookup 实现两张表格数据关联 vlookup 实现两个 sheet 间的关联需要用 vlookup 函数实现 函数第一个参数设置成 sheet1 中的 A 列&#xff08;如果数据很多&#xff0c;可以直接选中 A 列&#xff09; 函数的第二个参数选中 sheet2 中…

android 和 opencv 开发环境搭建

本文详细说明给android项目添加opencv库的详细步骤&#xff0c;并通过实现图片灰度化来查看配置是否成功。 下载OPENCV ANDROID SDK 到官网下载 打开 https://opencv.org/releases/ 选择android&#xff0c;下载完成后解压出下面的文件&#xff1a; 安装android sdk 和 ndk …

YOLOv8全网首发:DCNv4更快收敛、更高速度、更高性能,效果秒杀DCNv3、DCNv2等 ,助力检测

💡💡💡本文独家改进:DCNv4更快收敛、更高速度、更高性能,完美和YOLOv8结合,助力涨点 DCNv4优势:(1) 去除空间聚合中的softmax归一化,以增强其动态性和表达能力;(2) 优化存储器访问以最小化冗余操作以加速。这些改进显著加快了收敛速度,并大幅提高了处理速度,DCN…

【CSS】解决height = line-height 文字不垂直居中(偏上、偏下)的问题

解决办法1&#xff1a; 查看 font-family 属性&#xff0c;确认是否是因为字体而导致的不垂直居中问题。 其他小知识&#xff1a; 基线就是小写x字母的下边缘(线) 就是我们常说的 基线。line-height 属性设置的行高也就是定义的两行文字基线之间的距离! 参考文章&#xff1a;…

2017年认证杯SPSSPRO杯数学建模B题(第一阶段)岁月的印记全过程文档及程序

2017年认证杯SPSSPRO杯数学建模 跨年龄人脸识别模型的建立与分析 B题 岁月的印记 原题再现&#xff1a; 对同一个人来说&#xff0c;如果没有过改变面容的疾病、面部外伤或外科手术等经历&#xff0c;年轻和年老时的面容总有很大的相似性。人们在生活中也往往能够分辨出来两…

Java 方法中参数类型后写了三个点?什么意思?

1、...代表什么意思&#xff1f; 2、如何使用 3、注意事项 4、两个list&#xff0c;一个新的&#xff0c;一个旧的&#xff0c;旧列表中可能有新列表中存在的数据&#xff0c;也可能存在新列表中不存在的数据&#xff08;注&#xff1a;新旧列表中都不存在重复元素&#xff09;…

7.6 MySQL基本函数的使用(❤❤❤)

7.6 MySQL基本函数的使用 1. 提要2. 数字函数3. 字符函数3.1 替换字符3.2 左填充字符及截取字符串 4. 日期函数4.1 日期函数4.2 表达式占位符4.3 日期偏移计算4.4 日期间隔 5. 条件函数5.1 IF语句5.2 case...when语句 1. 提要 2. 数字函数 3. 字符函数 3.1 替换字符 -- INSERT…

水电站智能监测泄洪预警系统介绍

一、背景 近年来由于危险河道管理措施不到位&#xff0c;调峰电站泄水风险长期存在&#xff0c;信息通报制度缺失以及民众安全警觉性不高等因素导致的水电站在泄洪时冲走下游河道游客以及人民财产的事故频发。 二、系统介绍 水电站智能监测泄洪预警系统是一种集成了物联网、云…

C/C++ BM5 合并K个已排序的链表

文章目录 前言题目1 解决方案一1.1 思路阐述1.2 源码 2 解决方案二2.1 思路阐述2.2 源码 总结 前言 在接触了BM4的两个链表合并的情况&#xff0c;对于k个已排序列表&#xff0c;其实可以用合并的方法来看待问题。 这里第一种方法就是借用BM4的操作&#xff0c;只不过是多个合…

腾讯云服务器的介绍_云主机概览——腾讯云

腾讯云服务器CVM提供安全可靠的弹性计算服务&#xff0c;腾讯云明星级云服务器&#xff0c;弹性计算实时扩展或缩减计算资源&#xff0c;支持包年包月、按量计费和竞价实例计费模式&#xff0c;CVM提供多种CPU、内存、硬盘和带宽可以灵活调整的实例规格&#xff0c;提供9个9的数…

workflow源码解析:GoTask

关于go task 提供了另一种更简单的使用计算任务的方法&#xff0c;模仿go语言实现的go task。 使用go task来实计算任务无需定义输入与输出&#xff0c;所有数据通过函数参数传递。 与ThreadTask 区别 ThreadTask 是有模板&#xff0c;IN 和 OUT&#xff0c; ThreadTask 依赖…

分布式Erlang/OTP(学习笔记)(一)

Erlang分布式基础 假设你在机器A和机器B上各跑着一个Simple Cache应用的实例。要是在机器A的缓存上插人一个键/值对之后&#xff0c;从机器B上也可以访问&#xff0c;那可就好了。显然&#xff0c;要达到这个目的&#xff0c;机器A必须以某种方式将相关信息告知给机器B。传递该…

力扣309. 买卖股票的最佳时机含冷冻期(动态规划,Java C++解法)

Problem: 309. 买卖股票的最佳时机含冷冻期 文章目录 题目描述思路解题方法复杂度Code 题目描述 思路 Problem: 714. 买卖股票的最佳时机含手续费 该题目可以看作是上述题目的改编&#xff0c;该题目添加了一个冷冻期使得动态转移方程更加复杂&#xff0c;具体思路如下&#xf…

【MyBatis-Plus】逻辑删除

对于一些比较重要的数据&#xff0c;我们通常采用逻辑删除。&#xff08;即用一个字段表示是否删除&#xff0c;实际上始终在数据库没有被删除&#xff09; 当逻辑删除字段为 true&#xff0c;业务处理的时候会自动把该数据当做一个“不存在”的数据处理。&#xff08;即不处理…

uniapp让图片缩小

image{width: 500rpx;height:500rpx;} 在图片属性设置为image{}宽高改变但是大小不改变&#xff0c;解决办法是改成下面的代码 & > img {width: 50px; height: auto; } 如图&#xff1a;

最优解:阿里云服务器地域如何选择?

阿里云服务器地域和可用区怎么选择&#xff1f;地域是指云服务器所在物理数据中心的位置&#xff0c;地域选择就近选择&#xff0c;访客距离地域所在城市越近网络延迟越低&#xff0c;速度就越快&#xff1b;可用区是指同一个地域下&#xff0c;网络和电力相互独立的区域&#…

【计算机网络】(1)OSI七层模型、协议、交换技术、路由器技术

文章目录 计算机网络功能与分类计算机网络的定义计算机网络的功能计算机网络的指标计算机网络的性能指标计算机网络的非性能指标 计算机网络的分布范围以及拓扑结构划分图计算机网络分类总线型拓扑星型拓扑环形图拓扑树型拓扑分布式拓扑 通信技术信道物理信道逻辑信道 发信机OS…

vue3-事件处理

事件监听 DOM 事件监听指令 v-on 简写 v-on:click"handler" 或者 click"handler"事件处理器 (handler) 的值可以是&#xff1a; 内联事件处理器&#xff1a;比如 click 方法事件处理器&#xff1a;一个指向组件上定义的方法的属性名或是路径。 在内联…

搭建属于自己的内容付费平台:开发知识付费APP教学

近期知识付费的热度非常高&#xff0c;本篇文章小编将为你提供一份关于如何搭建属于自己的内容付费平台的简要教程&#xff0c;让你能够逐步实现一个功能完备的知识付费APP。 1.明确目标和功能需求 在开始开发之前&#xff0c;首先需要确定你的APP是面向哪个领域的用户&#x…

JSONObject - 用最通俗的讲解,教你玩转 JSON 数据的解析和修改

目录 一、JSONObject 1.1、为什么要使用他&#xff1f; 1.2、应用 1.2.1、依赖 1.2.2、JSON 数据示例 1.2.3、JSON 数据的构建 1.2.4、JSON 数据的解析 一、JSONObject 1.1、为什么要使用他&#xff1f; 在还没有接触过这个东西的时候&#xff0c;一直是通过 ObjectMap…