亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

vue下如何利用canvas實現(xiàn)在線圖片標(biāo)注

 更新時間:2022年04月28日 11:04:32   作者:嘀嗒嗒咚呲噠噠  
這篇文章主要介紹了vue下如何利用canvas實現(xiàn)在線圖片標(biāo)注,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

web端實現(xiàn)在線圖片標(biāo)注在此做下記錄,功能類似微信截圖時的標(biāo)注,包含畫線、框、箭頭和文字輸入,思路是利用canvas畫布,先把要標(biāo)注的圖片使用drawImage方法畫在畫布上,然后定義畫線、框、箭頭和文字輸入的方法調(diào)用

組件代碼如下

<template>
? <div class="draw">
? ? <div class="drawTop" ref="drawTop" v-if="lineStep == lineNum">
? ? ? <div>
? ? ? ? <el-button type @click="resetAll">清空</el-button>
? ? ? ? <el-button type @click="repeal">撤銷</el-button>
? ? ? ? <el-button type @click="canvasRedo">恢復(fù)</el-button>
? ? ? ? <el-button type @click="downLoad">下載</el-button>
? ? ? </div>
? ? ? <div style="width:22%">
? ? ? ? 選擇繪制類型:
? ? ? ? <el-radio-group v-model="type" size="medium">
? ? ? ? ? <el-radio-button
? ? ? ? ? ? v-for="(item,index) in typeOption"
? ? ? ? ? ? :key="index"
? ? ? ? ? ? :label="item.value"
? ? ? ? ? ? @click.native="radioClick(item.value)"
? ? ? ? ? >{{item.label}}
? ? ? ? ? </el-radio-button>
? ? ? ? </el-radio-group>
? ? ? </div>
? ? ? <div style="width:15%">
? ? ? ? 邊框粗細(xì):
? ? ? ? <el-slider v-model="lineWidth" :min="0" :max="10" :step="1" style="width:70%"></el-slider>
? ? ? </div>
? ? ? <div>
? ? ? ? 線條顏色:
? ? ? ? <el-color-picker v-model="strokeStyle"></el-color-picker>
? ? ? </div>
? ? ? <div>
? ? ? ? 文字顏色:
? ? ? ? <el-color-picker v-model="fontColor"></el-color-picker>
? ? ? </div>
? ? ? <div style="width:15%">
? ? ? ? 文字大小:
? ? ? ? <el-slider v-model="fontSize" :min="14" :max="36" :step="2" style="width:70%"></el-slider>
? ? ? </div>
? ? </div>
? ? <div style="height: 100%;width: 100%;position:relative;">
? ? ? <div class="content"></div>
? ? ? <input v-show="isShow" type="text" @blur="txtBlue" ref="txt" id="txt"
? ? ? ? ? ? ?style="z-index: 9999;position: absolute;border: 0;background:none;outline: none;"/>
? ? </div>
? </div>
</template>
<script>
? export default {
? ? name: "callout",
? ? props: {
? ? ? imgPath: undefined,
?
? ? },
? ? data() {
? ? ? return {
? ? ? ? isShow: false,
? ? ? ? canvas: "",
? ? ? ? ctx: "",
? ? ? ? ctxX: 0,
? ? ? ? ctxY: 0,
? ? ? ? lineWidth: 1,
? ? ? ? type: "L",
? ? ? ? typeOption: [
? ? ? ? ? {label: "線", value: "L"},
? ? ? ? ? {label: "矩形", value: "R"},
? ? ? ? ? {label: "箭頭", value: "A"},
? ? ? ? ? {label: "文字", value: "T"},
? ? ? ? ],
? ? ? ? canvasHistory: [],
? ? ? ? step: 0,
? ? ? ? loading: false,
? ? ? ? fillStyle: "#CB0707",
? ? ? ? strokeStyle: "#CB0707",
? ? ? ? lineNum: 2,
? ? ? ? linePeak: [],
? ? ? ? lineStep: 2,
? ? ? ? ellipseR: 0.5,
? ? ? ? dialogVisible: false,
? ? ? ? isUnfold: true,
? ? ? ? fontSize: 24,
? ? ? ? fontColor: "#CB0707",
? ? ? ? fontFamily: '微軟雅黑',
? ? ? ? img: new Image(),
? ? ? };
? ? },
? ? mounted() {
? ? ? let _this = this;
? ? ? let image = new Image();
? ? ? image.setAttribute('crossOrigin', 'anonymous');
? ? ? image.src = this.imgPath;
? ? ? image.onload = function () {//圖片加載完,再draw 和 toDataURL
? ? ? ? if (image.complete) {
? ? ? ? ? _this.img = image
? ? ? ? ? let content = document.getElementsByClassName("content")[0];
? ? ? ? ? _this.canvas = document.createElement("canvas");
? ? ? ? ? _this.canvas.height = _this.img.height
? ? ? ? ? _this.canvas.width = _this.img.width
? ? ? ? ? _this.ctx = _this.canvas.getContext("2d");
? ? ? ? ? _this.ctx.globalAlpha = 1;
? ? ? ? ? _this.ctx.drawImage(_this.img, 0, 0)
? ? ? ? ? _this.canvasHistory.push(_this.canvas.toDataURL());
? ? ? ? ? _this.ctx.globalCompositeOperation = _this.type;
? ? ? ? ? content.appendChild(_this.canvas);
? ? ? ? ? _this.bindEventLisner();
? ? ? ? }
? ? ? }
? ? },
? ? methods: {
? ? ? radioClick(item) {
? ? ? ? if (item != "T") {
? ? ? ? ? this.txtBlue()
? ? ? ? ? this.resetTxt()
? ? ? ? }
? ? ? },
? ? ? // 下載畫布
? ? ? downLoad() {
? ? ? ? let _this = this;
? ? ? ? let url = _this.canvas.toDataURL("image/png");
? ? ? ? let fileName = "canvas.png";
? ? ? ? if ("download" in document.createElement("a")) {
? ? ? ? ? // 非IE下載
? ? ? ? ? const elink = document.createElement("a");
? ? ? ? ? elink.download = fileName;
? ? ? ? ? elink.style.display = "none";
? ? ? ? ? elink.href = url;
? ? ? ? ? document.body.appendChild(elink);
? ? ? ? ? elink.click();
? ? ? ? ? document.body.removeChild(elink);
? ? ? ? } else {
? ? ? ? ? // IE10+下載
? ? ? ? ? navigator.msSaveBlob(url, fileName);
? ? ? ? }
? ? ? },
? ? ? // 清空畫布及歷史記錄
? ? ? resetAll() {
? ? ? ? this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
? ? ? ? this.canvasHistory = [];
? ? ? ? this.ctx.drawImage(this.img, 0, 0);
? ? ? ? this.canvasHistory.push(this.canvas.toDataURL());
? ? ? ? this.step = 0;
? ? ? ? this.resetTxt();
? ? ? },
? ? ? // 清空當(dāng)前畫布
? ? ? reset() {
? ? ? ? this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
? ? ? ? this.ctx.drawImage(this.img, 0, 0);
? ? ? ? this.resetTxt();
? ? ? },
? ? ? // 撤銷方法
? ? ? repeal() {
? ? ? ? let _this = this;
? ? ? ? if (this.isShow) {
? ? ? ? ? _this.resetTxt();
? ? ? ? ? _this._repeal();
? ? ? ? } else {
? ? ? ? ? _this._repeal();
? ? ? ? }
?
? ? ? },
? ? ? _repeal() {
? ? ? ? if (this.step >= 1) {
? ? ? ? ? this.step = this.step - 1;
? ? ? ? ? let canvasPic = new Image();
? ? ? ? ? canvasPic.src = this.canvasHistory[this.step];
? ? ? ? ? canvasPic.addEventListener("load", () => {
? ? ? ? ? ? this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
? ? ? ? ? ? this.ctx.drawImage(canvasPic, 0, 0);
? ? ? ? ? ? this.loading = true;
? ? ? ? ? });
? ? ? ? } else {
? ? ? ? ? this.$message.warning("不能再繼續(xù)撤銷了");
? ? ? ? }
? ? ? },
? ? ? // 恢復(fù)方法
? ? ? canvasRedo() {
? ? ? ? if (this.step < this.canvasHistory.length - 1) {
? ? ? ? ? if (this.step == 0) {
? ? ? ? ? ? this.step = 1;
? ? ? ? ? } else {
? ? ? ? ? ? this.step++;
? ? ? ? ? }
? ? ? ? ? let canvasPic = new Image();
? ? ? ? ? canvasPic.src = this.canvasHistory[this.step];
? ? ? ? ? canvasPic.addEventListener("load", () => {
? ? ? ? ? ? this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
? ? ? ? ? ? this.ctx.drawImage(canvasPic, 0, 0);
? ? ? ? ? });
? ? ? ? } else {
? ? ? ? ? this.$message.warning("已經(jīng)是最新的記錄了");
? ? ? ? }
? ? ? },
? ? ? // 繪制歷史數(shù)組中的最后一個
? ? ? rebroadcast() {
? ? ? ? let canvasPic = new Image();
? ? ? ? canvasPic.src = this.canvasHistory[this.step];
? ? ? ? canvasPic.addEventListener("load", () => {
? ? ? ? ? this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
? ? ? ? ? this.ctx.drawImage(canvasPic, 0, 0);
? ? ? ? ? this.loading = true;
? ? ? ? });
? ? ? },
? ? ? // 綁定事件,判斷分支
? ? ? bindEventLisner() {
? ? ? ? let _this = this;
? ? ? ? let r1, r2; // 繪制圓形,矩形需要
? ? ? ? this.canvas.onmousedown = function (e) {
? ? ? ? ? console.log("onmousedown");
? ? ? ? ? if (_this.type == "L") {
? ? ? ? ? ? _this.createL(e, "begin");
? ? ? ? ? } else if (_this.type == "R") {
? ? ? ? ? ? r1 = e.layerX;
? ? ? ? ? ? r2 = e.layerY;
? ? ? ? ? ? _this.createR(e, "begin", r1, r2);
? ? ? ? ? } else if (_this.type == "A") {
? ? ? ? ? ? _this.drawArrow(e, "begin")
? ? ? ? ? } else if (_this.type == "T") {
? ? ? ? ? ? _this.createT(e, "begin")
? ? ? ? ? }
? ? ? ? };
? ? ? ? this.canvas.onmouseup = function (e) {
? ? ? ? ? console.log("onmouseup");
? ? ? ? ? if (_this.type == "L") {
? ? ? ? ? ? _this.createL(e, "end");
? ? ? ? ? } else if (_this.type == "R") {
? ? ? ? ? ? _this.createR(e, "end", r1, r2);
? ? ? ? ? ? r1 = null;
? ? ? ? ? ? r2 = null;
? ? ? ? ? } else if (_this.type == "A") {
? ? ? ? ? ? _this.drawArrow(e, "end")
? ? ? ? ? } else if (_this.type == "T") {
? ? ? ? ? ? _this.createT(e, "end")
? ? ? ? ? }
? ? ? ? };
?
? ? ? },
? ? ? // 繪制線條
? ? ? createL(e, status) {
? ? ? ? let _this = this;
? ? ? ? if (status == "begin") {
? ? ? ? ? _this.ctx.beginPath();
? ? ? ? ? _this.ctx.moveTo(e.layerX, e.layerY);
? ? ? ? ? _this.canvas.onmousemove = function (e) {
? ? ? ? ? ? console.log("onmousemove");
? ? ? ? ? ? _this.ctx.lineTo(e.layerX, e.layerY);
? ? ? ? ? ? _this.ctx.strokeStyle = _this.strokeStyle;
? ? ? ? ? ? _this.ctx.lineWidth = _this.lineWidth;
? ? ? ? ? ? _this.ctx.stroke();
? ? ? ? ? };
? ? ? ? } else if (status == "end") {
? ? ? ? ? _this.ctx.closePath();
? ? ? ? ? _this.step = _this.step + 1;
? ? ? ? ? if (_this.step < _this.canvasHistory.length - 1) {
? ? ? ? ? ? _this.canvasHistory.length = _this.step; // 截斷數(shù)組
? ? ? ? ? }
? ? ? ? ? _this.canvasHistory.push(_this.canvas.toDataURL());
? ? ? ? ? _this.canvas.onmousemove = null;
? ? ? ? }
? ? ? },
? ? ? // 繪制矩形
? ? ? createR(e, status, r1, r2) {
? ? ? ? let _this = this;
? ? ? ? let r;
? ? ? ? if (status == "begin") {
? ? ? ? ? console.log("onmousemove");
? ? ? ? ? _this.canvas.onmousemove = function (e) {
? ? ? ? ? ? _this.reset();
? ? ? ? ? ? let rx = e.layerX - r1;
? ? ? ? ? ? let ry = e.layerY - r2;
?
? ? ? ? ? ? //保留之前繪畫的圖形
? ? ? ? ? ? if (_this.step !== 0) {
? ? ? ? ? ? ? let canvasPic = new Image();
? ? ? ? ? ? ? canvasPic.src = _this.canvasHistory[_this.step];
? ? ? ? ? ? ? _this.ctx.drawImage(canvasPic, 0, 0);
? ? ? ? ? ? }
?
? ? ? ? ? ? _this.ctx.beginPath();
? ? ? ? ? ? _this.ctx.strokeRect(r1, r2, rx, ry);
? ? ? ? ? ? _this.ctx.strokeStyle = _this.strokeStyle;
? ? ? ? ? ? _this.ctx.lineWidth = _this.lineWidth;
? ? ? ? ? ? _this.ctx.closePath();
? ? ? ? ? ? _this.ctx.stroke();
? ? ? ? ? };
? ? ? ? } else if (status == "end") {
? ? ? ? ? _this.rebroadcast();
? ? ? ? ? let interval = setInterval(() => {
? ? ? ? ? ? if (_this.loading) {
? ? ? ? ? ? ? clearInterval(interval);
? ? ? ? ? ? ? _this.loading = false;
? ? ? ? ? ? } else {
? ? ? ? ? ? ? return;
? ? ? ? ? ? }
? ? ? ? ? ? let rx = e.layerX - r1;
? ? ? ? ? ? let ry = e.layerY - r2;
? ? ? ? ? ? _this.ctx.beginPath();
? ? ? ? ? ? _this.ctx.rect(r1, r2, rx, ry);
? ? ? ? ? ? _this.ctx.strokeStyle = _this.strokeStyle;
? ? ? ? ? ? _this.ctx.lineWidth = _this.lineWidth;
? ? ? ? ? ? _this.ctx.closePath();
? ? ? ? ? ? _this.ctx.stroke();
? ? ? ? ? ? _this.step = _this.step + 1;
? ? ? ? ? ? if (_this.step < _this.canvasHistory.length - 1) {
? ? ? ? ? ? ? _this.canvasHistory.length = _this.step; // 截斷數(shù)組
? ? ? ? ? ? }
? ? ? ? ? ? _this.canvasHistory.push(_this.canvas.toDataURL());
? ? ? ? ? ? _this.canvas.onmousemove = null;
? ? ? ? ? }, 1);
? ? ? ? }
? ? ? },
?
? ? ? //繪制箭頭
? ? ? drawArrow(e, status) {
? ? ? ? let _this = this;
? ? ? ? if (status == "begin") {
? ? ? ? ? //獲取起始位置
? ? ? ? ? _this.arrowFromX = e.layerX;
? ? ? ? ? _this.arrowFromY = e.layerY;
? ? ? ? ? _this.ctx.beginPath();
? ? ? ? ? _this.ctx.moveTo(e.layerX, e.layerY);
? ? ? ? } else if (status == "end") {
? ? ? ? ? //計算箭頭及畫線
? ? ? ? ? let toX = e.layerX;
? ? ? ? ? let toY = e.layerY;
? ? ? ? ? let theta = 30;
? ? ? ? ? let headlen = 10;
? ? ? ? ? let _this = this;
? ? ? ? ? let fromX = this.arrowFromX;
? ? ? ? ? let fromY = this.arrowFromY;
? ? ? ? ? // 計算各角度和對應(yīng)的P2,P3坐標(biāo)
? ? ? ? ? let angle = Math.atan2(fromY - toY, fromX - toX) * 180 / Math.PI,
? ? ? ? ? angle1 = (angle + theta) * Math.PI / 180,
? ? ? ? ? angle2 = (angle - theta) * Math.PI / 180,
? ? ? ? ? topX = headlen * Math.cos(angle1),
? ? ? ? ? topY = headlen * Math.sin(angle1),
? ? ? ? ? botX = headlen * Math.cos(angle2),
? ? ? ? ? botY = headlen * Math.sin(angle2);
? ? ? ? ? let arrowX = fromX - topX,
? ? ? ? ? arrowY = fromY - topY;
? ? ? ? ? _this.ctx.moveTo(arrowX, arrowY);
? ? ? ? ? _this.ctx.moveTo(fromX, fromY);
? ? ? ? ? _this.ctx.lineTo(toX, toY);
? ? ? ? ? arrowX = toX + topX;
? ? ? ? ? arrowY = toY + topY;
? ? ? ? ? _this.ctx.moveTo(arrowX, arrowY);
? ? ? ? ? _this.ctx.lineTo(toX, toY);
? ? ? ? ? arrowX = toX + botX;
? ? ? ? ? arrowY = toY + botY;
? ? ? ? ? _this.ctx.lineTo(arrowX, arrowY);
? ? ? ? ? _this.ctx.strokeStyle = _this.strokeStyle;
? ? ? ? ? _this.ctx.lineWidth = _this.lineWidth;
? ? ? ? ? _this.ctx.stroke();
?
? ? ? ? ? _this.ctx.closePath();
? ? ? ? ? _this.step = _this.step + 1;
? ? ? ? ? if (_this.step < _this.canvasHistory.length - 1) {
? ? ? ? ? ? _this.canvasHistory.length = _this.step; // 截斷數(shù)組
? ? ? ? ? }
? ? ? ? ? _this.canvasHistory.push(_this.canvas.toDataURL());
? ? ? ? ? _this.canvas.onmousemove = null;
? ? ? ? }
? ? ? },
?
? ? ? //文字輸入
? ? ? createT(e, status) {
? ? ? ? let _this = this;
? ? ? ? if (status == "begin") {
?
? ? ? ? } else if (status == "end") {
? ? ? ? ? let offset = 0;
? ? ? ? ? if (_this.fontSize >= 28) {
? ? ? ? ? ? offset = (_this.fontSize / 2) - 3
? ? ? ? ? } else {
? ? ? ? ? ? offset = (_this.fontSize / 2) - 2
? ? ? ? ? }
?
? ? ? ? ? _this.ctxX = e.layerX + 2;
? ? ? ? ? _this.ctxY = e.layerY + offset;
?
? ? ? ? ? let index = this.getPointOnCanvas(e);
? ? ? ? ? _this.$refs.txt.style.left = index.x + 'px';
? ? ? ? ? _this.$refs.txt.style.top = index.y - (_this.fontSize / 2) + 'px';
? ? ? ? ? _this.$refs.txt.value = '';
? ? ? ? ? _this.$refs.txt.style.height = _this.fontSize + "px";
? ? ? ? ? _this.$refs.txt.style.width = _this.canvas.width - e.layerX - 1 + "px",
? ? ? ? ? ? _this.$refs.txt.style.fontSize = _this.fontSize + "px";
? ? ? ? ? _this.$refs.txt.style.fontFamily = _this.fontFamily;
? ? ? ? ? _this.$refs.txt.style.color = _this.fontColor;
? ? ? ? ? _this.$refs.txt.style.maxlength = Math.floor((_this.canvas.width - e.layerX) / _this.fontSize);
? ? ? ? ? _this.isShow = true;
? ? ? ? ? setTimeout(() => {
? ? ? ? ? ? _this.$refs.txt.focus();
? ? ? ? ? })
? ? ? ? }
? ? ? },
? ? ? //文字輸入框失去光標(biāo)時在畫布上生成文字
? ? ? txtBlue() {
? ? ? ? let _this = this;
? ? ? ? let txt = _this.$refs.txt.value;
? ? ? ? if (txt) {
? ? ? ? ? _this.ctx.font = _this.$refs.txt.style.fontSize + ' ' + _this.$refs.txt.style.fontFamily;
? ? ? ? ? _this.ctx.fillStyle = _this.$refs.txt.style.color;
? ? ? ? ? _this.ctx.fillText(txt, _this.ctxX, _this.ctxY);
? ? ? ? ? _this.step = _this.step + 1;
? ? ? ? ? if (_this.step < _this.canvasHistory.length - 1) {
? ? ? ? ? ? _this.canvasHistory.length = _this.step; // 截斷數(shù)組
? ? ? ? ? }
? ? ? ? ? _this.canvasHistory.push(_this.canvas.toDataURL());
? ? ? ? ? _this.canvas.onmousemove = null;
? ? ? ? }
? ? ? },
? ? ? //計算文字框定位位置
? ? ? getPointOnCanvas(e) {
? ? ? ? let cs = this.canvas;
? ? ? ? let content = document.getElementsByClassName("content")[0];
? ? ? ? return {
? ? ? ? ? x: e.layerX + (content.clientWidth - cs.width) / 2,
? ? ? ? ? y: e.layerY
? ? ? ? };
? ? ? },
? ? ? //清空文字
? ? ? resetTxt() {
? ? ? ? let _this = this;
? ? ? ? _this.$refs.txt.value = '';
? ? ? ? _this.isShow = false;
? ? ? }
? ? }
? };
</script>
<style scope>
? * {
? ? box-sizing: border-box;
? }
?
? body,
? html,
? #app {
? ? overflow: hidden;
? }
?
? .draw {
? ? height: 100%;
? ? min-width: 420px;
? ? display: flex;
? ? flex-direction: column;
? }
?
? .content {
? ? flex-grow: 1;
? ? height: 100%;
? ? width: 100%;
? }
?
? .drawTop {
? ? display: flex;
? ? justify-content: flex-start;
? ? align-items: center;
? ? padding: 5px;
? ? height: 52px;
? }
?
? .drawTop > div {
? ? display: flex;
? ? align-items: center;
? ? padding: 5px 5px;
? }
?
? div.drawTopContrllor {
? ? display: none;
? }
?
? @media screen and (max-width: 1200px) {
? ? .drawTop {
? ? ? position: absolute;
? ? ? background-color: white;
? ? ? width: 100%;
? ? ? flex-direction: column;
? ? ? align-items: flex-start;
? ? ? height: 30px;
? ? ? overflow: hidden;
? ? }
?
? ? .drawTopContrllor {
? ? ? display: flex !important;
? ? ? height: 30px;
? ? ? width: 100%;
? ? ? justify-content: center;
? ? ? align-items: center;
? ? ? padding: 0 !important;
? ? }
? }
</style>

然后在頁面中引入組件,傳入圖片鏈接。

在開發(fā)過程中遇到的問題

文字輸入功能在用戶輸入文字后,如果不再點擊別的地方直接點擊別的功能按鈕的話,最后輸入的文字將不會再畫布上生成,通過監(jiān)控輸入框的blur事件來在畫布上生成文字,避免這個問題。

文字輸入時字體的大小會影響生成文字的位置,這里發(fā)現(xiàn)文字的大小和位置有一個偏移量:

let offset = 0;
if (_this.fontSize >= 28) {
? offset = (_this.fontSize / 2) - 3
} else {
? offset = (_this.fontSize / 2) - 2
}

在畫布上生成文字的時候需要加上這個偏移量,這里字體范圍是14~36,別的字體大小沒有校驗,不一定適用這個計算方式。

繪制矩形的時候需要先清空畫布,在清空之前先保存一次畫布然后再清空再重新畫一下畫布,負(fù)責(zé)矩形框會不停的出現(xiàn)軌跡,并且之前畫的元素會消失。

撤銷的時候需要考慮文字輸入,判斷input得v-show是否為true,如果是true需要先清空文字,再撤銷,否則畫布上會一直存在一個輸入框。

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 基于vue-cli、elementUI的Vue超簡單入門小例子(推薦)

    基于vue-cli、elementUI的Vue超簡單入門小例子(推薦)

    這篇文章主要介紹了基于vue-cli、elementUI的Vue超簡單入門小例子,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • vue之監(jiān)聽器的使用案例詳解

    vue之監(jiān)聽器的使用案例詳解

    這篇文章主要介紹了vue之監(jiān)聽器的使用案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • 淺談Vue頁面級緩存解決方案feb-alive (下)

    淺談Vue頁面級緩存解決方案feb-alive (下)

    這篇文章主要介紹了淺談Vue頁面級緩存解決方案feb-alive(下),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • vue打包的時候自動將px轉(zhuǎn)成rem的操作方法

    vue打包的時候自動將px轉(zhuǎn)成rem的操作方法

    這篇文章主要介紹了vue打包的時候自動將px轉(zhuǎn)成rem的操作方法,需要的朋友可以參考下
    2018-06-06
  • vue內(nèi)置組件transition簡單原理圖文詳解(小結(jié))

    vue內(nèi)置組件transition簡單原理圖文詳解(小結(jié))

    這篇文章主要介紹了vue內(nèi)置組件transition簡單原理圖文詳解(小結(jié)),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-07-07
  • vue-element-admin項目導(dǎo)入和導(dǎo)出的實現(xiàn)

    vue-element-admin項目導(dǎo)入和導(dǎo)出的實現(xiàn)

    組件是Vue.js最強(qiáng)大的功能,這篇文章主要介紹了vue-element-admin項目導(dǎo)入和導(dǎo)出的實現(xiàn),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • Vue2?中的數(shù)據(jù)劫持簡寫示例

    Vue2?中的數(shù)據(jù)劫持簡寫示例

    這篇文章主要為大家介紹了Vue2?中的數(shù)據(jù)劫持簡寫示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • vue實現(xiàn)固定位置顯示功能

    vue實現(xiàn)固定位置顯示功能

    這篇文章主要介紹了vue實現(xiàn)固定位置顯示功能,本文通過實例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-05-05
  • vue實現(xiàn)簡單圖片上傳功能

    vue實現(xiàn)簡單圖片上傳功能

    這篇文章主要為大家詳細(xì)介紹了vue實現(xiàn)簡單圖片上傳功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • Vite打包性能優(yōu)化之開啟Gzip壓縮實踐過程

    Vite打包性能優(yōu)化之開啟Gzip壓縮實踐過程

    vue前端項目發(fā)布的時候,打包可實現(xiàn)gzip格式的壓縮,下面這篇文章主要給大家介紹了關(guān)于Vite打包性能優(yōu)化之開啟Gzip壓縮的相關(guān)資料,需要的朋友可以參考下
    2022-12-12

最新評論