IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> ElementUI中使用富文本编辑器(quill-editor)实现图片视频上传,图片拖拽和缩放,以及菜单悬停显示中文和表情包 -> 正文阅读

[JavaScript知识库]ElementUI中使用富文本编辑器(quill-editor)实现图片视频上传,图片拖拽和缩放,以及菜单悬停显示中文和表情包

ElementUI中使用富文本编辑器(quill-editor)


本文相当于是承上启下的一篇文章,之前的博客讲了如何文件上传,富文本编辑器需要利用到 文件上传,而楼主的下一个项目,需要对文章进行管理,所以今天来封装一个富文本编辑器(在之前的博客里用到了UEditor,当时出于官网太久没有更新),换了一个富文本编辑器使用。

一、引入quill-editor

安装依赖,需要先安装vue-quill-editor插件

npm install vue-quill-editor --save
npm install quill

image-20220728123037342

安装图片插件(图片拖拽和修改图片大小),如果你有这个方面的需求的话,可以引入,否则忽略

npm install quill-image-drop-module --save     
npm install quill-image-resize-module --save

image-20220728123609153

二、使用quill-editor

全局引入

我们安装完成之后,可以在main.js中全局引入quill-editor

 //引入quill-editor编辑器
 import VueQuillEditor from 'vue-quill-editor'
 import 'quill/dist/quill.core.css'
 import 'quill/dist/quill.snow.css'
 import 'quill/dist/quill.bubble.css'
 Vue.use(VueQuillEditor)
 
 //实现quill-editor编辑器拖拽上传图片
 import * as Quill from 'quill'
 import { ImageDrop } from 'quill-image-drop-module'
 Quill.register('modules/imageDrop', ImageDrop)
 
 //实现quill-editor编辑器调整图片尺寸
 import ImageResize from 'quill-image-resize-module'
 Quill.register('modules/imageResize', ImageResize)

image-20220728123908350

按需引入

用到的时候,再引入

//引入quill-editor编辑器
import VueQuillEditor from 'vue-quill-editor'
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
//实现quill-editor编辑器拖拽上传图片
import * as Quill from 'quill'
import { ImageDrop } from 'quill-image-drop-module'
//实现quill-editor编辑器调整图片尺寸
import ImageDrop from 'quill-image-resize-module' 
export default {
  components: {
    VueQuillEditor,
     ImageDrop, 
      ImageDrop
  }
}

配置修改

使用图片与视频的上传功能,请在此之前完成上传组件,为其 class 赋值,并隐藏该组件

<el-upload
          class="avatar-uploader"
          :action="uploadImgUrl"
          :accept="'image/*,video/*'"
          :show-file-list="false"
          :on-success="uploadEditorSuccess"
          :on-error="uploadEditorError"
          :before-upload="beforeEditorUpload"
          :headers="headers">
</el-upload>
视频修改

如果需要用到视频上传,且希望视频可以正常回显,需要修改quill源码中视频 标签为

写一个quillVideo.js

import  { Quill }  from 'vue-quill-editor'
// 源码中是import直接倒入,这里要用Quill.import引入
const BlockEmbed = Quill.import('blots/block/embed')
// const Link = Quill.import('formats/link')

const ATTRIBUTES = ['height', 'width']

class Video extends BlockEmbed {
    static create (value) {
        const node = super.create(value)
        // console.log("js文件"+ window.jsValue)
        // 添加video标签所需的属性
        node.setAttribute('controls', 'controls') // 控制播放器
        //删除原生video的控制条的下载或者全屏按钮的方法
        //<video controls controlsList='nofullscreen nodownload noremote footbar' ></video>
        //不用哪个在下面加上哪个
        node.setAttribute('controlsList', 'nofullscreen') // 控制删除
        node.setAttribute('type', 'video/mp4')
        node.setAttribute('style', 'object-fit:fill;width: 100%;')
        node.setAttribute('preload', 'auto')    // auto - 当页面加载后载入整个视频  meta - 当页面加载后只载入元数据  none - 当页面加载后不载入视频
        node.setAttribute('playsinline', 'true')
        node.setAttribute('x-webkit-airplay', 'allow')
        // node.setAttribute('x5-video-player-type', 'h5') // 启用H5播放器,是wechat安卓版特性
        node.setAttribute('x5-video-orientation', 'portraint') // 竖屏播放 声明了h5才能使用  播放器支付的方向,landscape横屏,portraint竖屏,默认值为竖屏
        node.setAttribute('x5-playsinline', 'true') // 兼容安卓 不全屏播放
        node.setAttribute('x5-video-player-fullscreen', 'true')    // 全屏设置,设置为 true 是防止横屏
        node.setAttribute('src', window.jsValue)
        return node
    }

    static formats (domNode) {
        return ATTRIBUTES.reduce((formats, attribute) => {
            if (domNode.hasAttribute(attribute)) {
                formats[attribute] = domNode.getAttribute(attribute)
            }
            return formats
        }, {})
    }

    // static sanitize (url) {
    //
    //      // eslint-disable-line import/no-named-as-default-member
    // }

    static value (domNode) {
        return domNode.getAttribute('src')
    }

    format (name, value) {
        if (ATTRIBUTES.indexOf(name) > -1) {
            if (value) {
                this.domNode.setAttribute(name, value)
            } else {
                this.domNode.removeAttribute(name)
            }
        } else {
            super.format(name, value)
        }
    }

    html () {
        const { video } = this.value()
        return `<a href="${video}">${video}</a>`
    }
}
Video.blotName = 'video' // 这里不用改,楼主不用iframe,直接替换掉原来,如果需要也可以保留原来的,这里用个新的blot
Video.className = 'ql-video'
Video.tagName = 'video' // 用video标签替换iframe

export default Video

在quillEditor界面写

window.jsValue=imgUrl;

image-20220728144646295

滚动效果

富文本里面的下拉框默认是不滚动的,想要滚动效果,加上下面的css

/*加上height和滚动属性就可以,滚动条样式是系统默认样式,可能不同*/
.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-options {
  border-color: #ccc;
  height: 125px;
  overflow: auto;
}
添加表情包

添加插件

npm i node-emoji

或者

npm install node-emoji

image-20220728212532081

image-20220728212545643

在main.js将它挂载到vue原型上

import emoji from 'node-emoji'
Vue.prototype.emoji = emoji. //这里,emoji里的表情还是很多的好像有上千个,这里可以截取其中的一部分

添加插件

npm isntall quill-emoji

在main.js中加入(全局注册)

import 'quill/dist/quill.bubble.css'
import quillEmoji from 'quill-emoji'

注册

Quill.register('modules/quillEmoji', quillEmoji)//将emoji插件注册进富文本

image-20220728222310064

在main.js中添加(注意导入的位置,否则可能会报错,前端界面启动不起来)

import quillEmoji from 'quill-emoji'
import 'quill-emoji/dist/quill-emoji.css'、
Quill.register('modules/quillEmoji', quillEmoji)

image-20220728223436600

悬停加上中文释义

image-20220728142859276

先定义一个数组,把所有的工具放在里面

// toolbar标题
const titleConfig = [
  { Choice: '.ql-insertMetric', title: '跳转配置' },
  { Choice: '.ql-bold', title: '加粗' },
  { Choice: '.ql-italic', title: '斜体' },
  { Choice: '.ql-underline', title: '下划线' },
  { Choice: '.ql-header', title: '段落格式' },
  { Choice: '.ql-strike', title: '删除线' },
  { Choice: '.ql-blockquote', title: '块引用' },
  { Choice: '.ql-code', title: '插入代码' },
  { Choice: '.ql-code-block', title: '插入代码段' },
  { Choice: '.ql-font', title: '字体' },
  { Choice: '.ql-size', title: '字体大小' },
  { Choice: '.ql-list[value="ordered"]', title: '编号列表' },
  { Choice: '.ql-list[value="bullet"]', title: '项目列表' },
  { Choice: '.ql-direction', title: '文本方向' },
  { Choice: '.ql-header[value="1"]', title: 'h1' },
  { Choice: '.ql-header[value="2"]', title: 'h2' },
  { Choice: '.ql-align', title: '对齐方式' },
  { Choice: '.ql-color', title: '字体颜色' },
  { Choice: '.ql-background', title: '背景颜色' },
  { Choice: '.ql-image', title: '图像' },
  { Choice: '.ql-video', title: '视频' },
  { Choice: '.ql-link', title: '添加链接' },
  { Choice: '.ql-formula', title: '插入公式' },
  { Choice: '.ql-clean', title: '清除字体格式' },
  { Choice: '.ql-emoji', title: '表情包' },
  { Choice: '.ql-script[value="sub"]', title: '下标' },
  { Choice: '.ql-script[value="super"]', title: '上标' },
  { Choice: '.ql-indent[value="-1"]', title: '向左缩进' },
  { Choice: '.ql-indent[value="+1"]', title: '向右缩进' },
  { Choice: '.ql-header .ql-picker-label', title: '标题大小' },
  { Choice: '.ql-header .ql-picker-item[data-value="1"]', title: '标题一' },
  { Choice: '.ql-header .ql-picker-item[data-value="2"]', title: '标题二' },
  { Choice: '.ql-header .ql-picker-item[data-value="3"]', title: '标题三' },
  { Choice: '.ql-header .ql-picker-item[data-value="4"]', title: '标题四' },
  { Choice: '.ql-header .ql-picker-item[data-value="5"]', title: '标题五' },
  { Choice: '.ql-header .ql-picker-item[data-value="6"]', title: '标题六' },
  { Choice: '.ql-header .ql-picker-item:last-child', title: '标准' },
  { Choice: '.ql-size .ql-picker-item[data-value="small"]', title: '小号' },
  { Choice: '.ql-size .ql-picker-item[data-value="large"]', title: '大号' },
  { Choice: '.ql-size .ql-picker-item[data-value="huge"]', title: '超大号' },
  { Choice: '.ql-size .ql-picker-item:nth-child(2)', title: '标准' },
  { Choice: '.ql-align .ql-picker-item:first-child', title: '居左对齐' },
  { Choice: '.ql-align .ql-picker-item[data-value="center"]', title: '居中对齐' },
  { Choice: '.ql-align .ql-picker-item[data-value="right"]', title: '居右对齐' },
  { Choice: '.ql-align .ql-picker-item[data-value="justify"]', title: '两端对齐' }
]

在页面上已经渲染好元素之后,执行下面函数,放在onEditorReady函数内

for (let item of titleConfig) {
	let tip = document.querySelector('.quill-editor ' + item.Choice)
	if (!tip) continue
	tip.setAttribute('title', item.title)
}

具体使用

写一个quillEditor.vue

<template>
  <div>
    <div id='quillEditorQiniu'>
      <!-- 基于elementUi的上传组件 el-upload begin-->
      <el-upload
          class="avatar-uploader"
          :action="uploadImgUrl"
          :accept="'image/*,video/*'"
          :show-file-list="false"
          :on-success="uploadEditorSuccess"
          :on-error="uploadEditorError"
          :before-upload="beforeEditorUpload"
          :headers="headers">
      </el-upload>
      <!-- 基于elementUi的上传组件 el-upload end-->
      <quill-editor  class="editor"  v-model="content" ref="customQuillEditor" :options="editorOption" @ready="onEditorReady($event)" >
      </quill-editor>
    </div>

  </div>
</template>

<script>
import * as Quill from 'quill'
// 这里引入修改过的video模块并注册
import Video from "@/components/quillEditor/quillVideo";
Quill.register(Video, true)



//自定义编辑器的工作条
import {getToken} from "@/utils/auth";
// toolbar标题
const titleConfig = [
  { Choice: '.ql-insertMetric', title: '跳转配置' },
  { Choice: '.ql-bold', title: '加粗' },
  { Choice: '.ql-italic', title: '斜体' },
  { Choice: '.ql-underline', title: '下划线' },
  { Choice: '.ql-header', title: '段落格式' },
  { Choice: '.ql-strike', title: '删除线' },
  { Choice: '.ql-blockquote', title: '块引用' },
  { Choice: '.ql-code', title: '插入代码' },
  { Choice: '.ql-code-block', title: '插入代码段' },
  { Choice: '.ql-font', title: '字体' },
  { Choice: '.ql-size', title: '字体大小' },
  { Choice: '.ql-list[value="ordered"]', title: '有序列表' },
  { Choice: '.ql-list[value="bullet"]', title: '无序列表' },
  { Choice: '.ql-direction', title: '文本方向' },
  { Choice: '.ql-header[value="1"]', title: 'h1' },
  { Choice: '.ql-header[value="2"]', title: 'h2' },
  { Choice: '.ql-align', title: '对齐方式' },
  { Choice: '.ql-color', title: '字体颜色' },
  { Choice: '.ql-background', title: '背景颜色' },
  { Choice: '.ql-image', title: '图像' },
  { Choice: '.ql-video', title: '视频' },
  { Choice: '.ql-link', title: '添加链接' },
  { Choice: '.ql-formula', title: '插入公式' },
  { Choice: '.ql-clean', title: '清除字体格式' },
  { Choice: '.ql-emoji', title: '表情包' },
  { Choice: '.ql-script[value="sub"]', title: '下标' },
  { Choice: '.ql-script[value="super"]', title: '上标' },
  { Choice: '.ql-indent[value="-1"]', title: '向左缩进' },
  { Choice: '.ql-indent[value="+1"]', title: '向右缩进' },
  { Choice: '.ql-header .ql-picker-label', title: '标题大小' },
  { Choice: '.ql-header .ql-picker-item[data-value="1"]', title: '标题一' },
  { Choice: '.ql-header .ql-picker-item[data-value="2"]', title: '标题二' },
  { Choice: '.ql-header .ql-picker-item[data-value="3"]', title: '标题三' },
  { Choice: '.ql-header .ql-picker-item[data-value="4"]', title: '标题四' },
  { Choice: '.ql-header .ql-picker-item[data-value="5"]', title: '标题五' },
  { Choice: '.ql-header .ql-picker-item[data-value="6"]', title: '标题六' },
  { Choice: '.ql-header .ql-picker-item:last-child', title: '标准' },
  { Choice: '.ql-size .ql-picker-item[data-value="small"]', title: '小号' },
  { Choice: '.ql-size .ql-picker-item[data-value="large"]', title: '大号' },
  { Choice: '.ql-size .ql-picker-item[data-value="huge"]', title: '超大号' },
  { Choice: '.ql-size .ql-picker-item:nth-child(2)', title: '标准' },
  { Choice: '.ql-align .ql-picker-item:first-child', title: '居左对齐' },
  { Choice: '.ql-align .ql-picker-item[data-value="center"]', title: '居中对齐' },
  { Choice: '.ql-align .ql-picker-item[data-value="justify"]', title: '两端对齐' },
  // { Choice: '.ql-table', title: '插入表格' },
  // { Choice: '.ql-table-insert-row', title: '插入行' },
  // { Choice: '.ql-table-insert-column', title: '插入列' },
  // { Choice: '.ql-table-delete-row', title: '删除行' },
  // { Choice: '.ql-table-delete-column', title: '删除列' },
]
const toolbarOptions = [
  ['bold', 'italic', 'underline', 'strike'], // 加粗 斜体 下划线 删除线
  ['blockquote', 'code-block'], // 引用  代码块
  [{ header: 1 }, { header: 2 }], // 1、2 级标题
  [{ list: 'ordered' }, { list: 'bullet' }], // 有序、无序列表
  [{ script: 'sub' }, { script: 'super' }], // 上标/下标
  [{ indent: '-1' }, { indent: '+1' }], // 缩进
  [{ direction: 'rtl' }], // 文本方向
  [{ size: ['small', false, 'large', 'huge'] }], // 字体大小
  [{ header: [1, 2, 3, 4, 5, 6] }], // 标题
  [{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
  [{ font: ['songti'] }], // 字体种类
  [{ align: [] }], // 对齐方式
  // [
    // {'table': 'TD'},
    // {'table-insert-row': 'TIR'},
    // {'table-insert-column': 'TIC'},
    // {'table-delete-row': 'TDR'},
    // {'table-delete-column': 'TDC'}
  // ],
  ['image', 'video'], // 链接、图片、视频
  ['emoji'],//表情包
  ['clean'], // 清除文本格式
];
export default {

  data(){
    return {
      headers: {
        Authorization: "Bearer " + getToken(),
      },
      uploadImgUrl:"/v1/admin/common/upload",
      uploadUrlPath:"没有文件上传",
      quillUpdateImg:false,
      content:'',    //最终保存的内容
      editorOption:{
        placeholder:'请输入内容',
        modules: {
          'emoji-toolbar': true,
          "emoji-textarea": true,
          'emoji-shortname': true,
          imageResize: {
            displayStyles: {
              backgroundColor: 'black',
              border: 'none',
              color: 'white'
            },
            modules: [ 'Resize', 'DisplaySize', 'Toolbar' ]
          },
          toolbar: {
            container: toolbarOptions,  // 工具栏
            table: true, // 设为true
            handlers: {

              'image': function (value) {
                if (value) {
                  document.querySelector('#quillEditorQiniu .avatar-uploader input').click()
                } else {
                  this.quill.format('image', false);
                }
              },
              'video': function (value) {
                if (value) {
                  document.querySelector('#quillEditorQiniu .avatar-uploader input').click()
                } else {
                  this.quill.format('video', false);
                }
              },

            }
          },

        }
      },
    }
  },
  methods:{

    // 准备富文本编辑器
    onEditorReady(quill) {
      console.log('editor ready!', quill);
      for (let item of titleConfig) {
        let tip = document.querySelector('.quill-editor ' + item.Choice)
        if (!tip) continue
        tip.setAttribute('title', item.title)
      }
    },
    //上传图片之前async
    beforeEditorUpload(res, file){
      //显示上传动画
      this.quillUpdateImg = true;
      //  const res1 = await uploadImage()
      // console.log(res1,'=====');
      // this.$emit('before',res, file)
      console.log(res);
      console.log(file);
    },
    // 上传图片成功
    uploadEditorSuccess(res, file) {
      console.log("上传成功")
      // this.$emit('upload',res, file)
      console.log(res, file);
      //拼接出上传的图片在服务器的完整地址
      let imgUrl=res.data.url;
      let type=imgUrl.substring(imgUrl.lastIndexOf(".")+1);
      console.log(type);
      // 获取富文本组件实例
      let quill = this.$refs.customQuillEditor.quill;
      // 获取光标所在位置
      let length = quill.getSelection().index;
      // 插入图片||视频  res.info为服务器返回的图片地址
      if(type=='mp4' || type=='MP4'){
        window.jsValue=imgUrl;
        quill.insertEmbed(length, 'video', imgUrl)
      }else{
        quill.insertEmbed(length, 'image', imgUrl)
      }
      // 调整光标到最后
      quill.setSelection(length + 1)
      //取消上传动画
      this.quillUpdateImg = false;
    },
    // 上传(文件)图片失败
    uploadEditorError(res, file) {
      console.log(res);
      console.log(file);
      //页面提示
      this.$message.error('上传图片失败')
      //取消上传动画
      this.quillUpdateImg = false;
    },
    //上传组件返回的结果
    uploadResult:function (res){
      this.uploadUrlPath=res;
    },
    openContent:function (){
      console.log(this.content)
    },

  },
  created () {

  },
  //只执行一次,加载执行
  mounted () {
    console.log("开始加载");


  },
  watch:{
    content(newVal, oldVal) {
      //this.$emit('input', newVal);
      console.log(newVal)
      console.log(oldVal)
    }
  },


}
</script>

<style>
.editor {
  line-height: normal !important;
  height: 400px;
  margin-bottom: 50px;
}
.ql-snow .ql-tooltip[data-mode="link"]::before {
  content: "请输入链接地址:";
}
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
  border-right: 0px;
  content: "保存";
  padding-right: 0px;
}

.ql-snow .ql-tooltip[data-mode="video"]::before {
  content: "请输入视频地址:";
}
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
  content: "14px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
  content: "10px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
  content: "18px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
  content: "32px";
}

.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
  content: "文本";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
  content: "标题1";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
  content: "标题2";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
  content: "标题3";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
  content: "标题4";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
  content: "标题5";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
  content: "标题6";
}

.ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
  content: "标准字体";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
  content: "衬线字体";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
  content: "等宽字体";
}


/*加上height和滚动属性就可以,滚动条样式是系统默认样式,可能不同*/
.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-options {
  border-color: #ccc;
  height: 125px;
  overflow: auto;
}
</style>

结构如下

image-20220728125714560

把该界面写入到路由router.js,测试效果

如果控制台出现如下错误,导致前端界面启动失败

Cannot read property 'imports' of undefined"
Failed to mount component: template or render function not defined.
Cannot read property 'registerof undefined’

image-20220728131032409

解决方法:

在vue.config.js加上下面代码(重启即可)

const webpack = require("webpack")
module.exports = {
    configureWebpack: {
        plugins: [
            new webpack.ProvidePlugin({
                'window.Quill': 'quill/dist/quill.js',
                'Quill': 'quill/dist/quill.js',
            })
        ]
    },
}

效果演示

image-20220728145442537

image-20220729000150180

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-08-06 10:34:49  更:2022-08-06 10:36:49 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/11 12:32:33-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码