欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用Vue實(shí)現(xiàn)防篡改的水印

 更新時(shí)間:2023年08月27日 08:53:02   作者:子辰Web草廬  
我們?cè)谄綍r(shí)上網(wǎng)的時(shí)候會(huì)看到有些圖片是加水印的,一般水印往往是后端來(lái)做的,不過(guò)有些站點(diǎn)要保護(hù)的知識(shí)產(chǎn)權(quán)類型比較多,不光是圖片,可能還有視頻或者文字,所以我們水印的作用,就是給他做一個(gè)適當(dāng)?shù)南拗?本文就給大家介紹一下如何使用Vue實(shí)現(xiàn)防篡改的水印

我們?cè)谄綍r(shí)上網(wǎng)的時(shí)候會(huì)看到有些圖片是加水印的:

像這種加水印的操作往往是后端來(lái)做的,不過(guò)有些站點(diǎn)要保護(hù)的知識(shí)產(chǎn)權(quán)類型比較多,不光是圖片,可能還有視頻或者文字。

對(duì)不同類型的東西去加這個(gè)水印,后端操作起來(lái)就可能比較麻煩,因?yàn)樗∵@個(gè)東西防君子不防小人,他要搞你的話始終能搞你。

所以我們水印的作用,就是給他做一個(gè)適當(dāng)?shù)南拗?,讓他沒(méi)有那么輕易的能搞到。

因此現(xiàn)在有些站點(diǎn)開(kāi)始逐步的讓前端來(lái)制作這個(gè)水印了。

如果你是用的是 React 來(lái)開(kāi)發(fā)的話就比較簡(jiǎn)單了:

這個(gè) Ant Design 這個(gè)庫(kù),它本身就有一個(gè)組件叫做 Watermark 水印組件,通過(guò)這個(gè)組件就可以給一個(gè)區(qū)域加上一個(gè)水印,非常的 so easy 開(kāi)發(fā)成本極低,無(wú)論這個(gè)區(qū)域是圖片還是文字或者視頻,都無(wú)所謂。

但是如果你使用的是 Vue 來(lái)開(kāi)發(fā)的話很遺憾,無(wú)論是 Element UI 還是 Ant Design Vue,都沒(méi)有這個(gè) Watermark 組件。

那么就需要我們自己手動(dòng)的去編寫,其實(shí)編寫這個(gè)組件也并不復(fù)雜,主要是要考慮兩個(gè)問(wèn)題:

  1. 如何來(lái)生成水印
  2. 如何來(lái)防止篡改

如何生成水印

我們先來(lái)看第一步如何生成水印。

基本思路與準(zhǔn)備

我們可以有這么一個(gè)思路:

比如我們要在上圖的區(qū)域做水印,那么就在區(qū)域里加上一個(gè) div,div 填充滿整個(gè)區(qū)域,然后給這個(gè) div 一張水印的背景圖,然后讓背景圖重復(fù)就可以了。

這個(gè)背景圖我們可以使用 canvas 來(lái)畫。

所以基于這么一個(gè)思路,我們就可以寫出這么一個(gè)代碼結(jié)構(gòu):

我們引入封裝的 Watermark 組件,里邊傳入任何內(nèi)容,可以是文字也可以是視頻,然后就給這個(gè)區(qū)域加上水印。

通過(guò) text 傳入水印的文本。

那么我們看看組件里咋寫的:

<template>
  <div class="watermark-container">
    <slot></slot>
    <!-- 我們要做的就是在這里添加一個(gè) div,填充滿整個(gè)區(qū)域,設(shè)置水印背景并且重復(fù) -->
  </div>
</template>
<script setup>
import useWatermarkBg from './useWatermarkBg';
// 定義一些基本的屬性( 如果說(shuō)你想開(kāi)發(fā)的更加完善,可以加入更多的屬性來(lái)適應(yīng)你的要求 )
const props = defineProps({
  text: { // 傳入水印的文本
    type: String,
    required: true,
    default: 'watermark',
  },
  fontSize: { // 字體的大小
    type: Number,
    default: 40,
  },
  gap: { // 水印重復(fù)的間隔
    type: Number,
    default: 20,
  },
});
// useWatermarkBg 函數(shù)用來(lái)創(chuàng)建一個(gè) canvas 圖片
// 將屬性傳遞進(jìn)去就返回個(gè)創(chuàng)建好的對(duì)象
const bg = useWatermarkBg(props);
console.log('bg.value >>> ', bg.value)
</script>

目前組件的代碼還是比較簡(jiǎn)單,我們看一下 useWatermarkBg 返回的數(shù)據(jù)是什么:

這里打印了兩個(gè)對(duì)象,是因?yàn)槲覀冇袃蓚€(gè)水印區(qū)域,這個(gè)對(duì)象里有三個(gè)屬性:

base64:表示 canvas 生成圖片的 dataurl,到時(shí)候就可以用它來(lái)做背景 size:表示 canvas 的寬高 styleSize:表示 canvas 的 DPR,如果想要用非常清晰的尺寸的話就用這個(gè),這個(gè)值和 window 的devicePixelRatio 有關(guān),如果你不知道的話可以關(guān)注子辰,后期會(huì)更新相關(guān)的文章 。

那么我們看看 useWatermarkBg 函數(shù)是怎么寫的,代碼也很簡(jiǎn)單:

import { computed } from 'vue';
export default function useWatermarkBg (props) {
  return computed(() => {
    // 創(chuàng)建一個(gè) canvas
    const canvas = document.createElement('canvas');
    const devicePixelRatio = window.devicePixelRatio || 1;
    // 設(shè)置字體大小
    const fontSize = props.fontSize * devicePixelRatio;
    const font = fontSize + 'px serif';
    const ctx = canvas.getContext('2d');
    // 獲取文字寬度
    ctx.font = font;
    const { width } = ctx.measureText(props.text);
    const canvasSize = Math.max(100, width) + props.gap * devicePixelRatio;
    canvas.width = canvasSize;
    canvas.height = canvasSize;
    ctx.translate(canvas.width / 2, canvas.height / 2);
    // 旋轉(zhuǎn) 45 度讓文字變傾斜
    ctx.rotate((Math.PI / 180) * -45);
    ctx.fillStyle = 'rgba(0, 0, 0, 0.3)';
    ctx.font = font;
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    // 將文字畫出來(lái)
    ctx.fillText(props.text, 0, 0);
    return {
      base64: canvas.toDataURL(),
      size: canvasSize,
      styleSize: canvasSize / devicePixelRatio,
    };
  });
}

現(xiàn)在基本的數(shù)據(jù)有了,我們就要生成一個(gè)水印的背景的 div,填充在合適的位置。

生成水印填充背景

<template>
  <div class="watermark-container">
    <slot></slot>
    <!-- 我們要做的就是在這里添加一個(gè) div,填充滿整個(gè)區(qū)域,設(shè)置水印背景并且重復(fù) -->
  </div>
</template>
<script setup>
import useWatermarkBg from './useWatermarkBg';
const props = defineProps({
	// ...
});
const bg = useWatermarkBg(props);
// 創(chuàng)建一個(gè) div
const div = document.createElement('div');
</script>

我們這里使用 document.createElement 生成一個(gè) div,有同學(xué)可能會(huì)問(wèn),為什么不直接在填充的位置寫一個(gè) div 呢?因?yàn)椴恍校劣跒槭裁床恍锌吹胶筮吘椭懒?,在最后進(jìn)行解釋,現(xiàn)在就使用 dom 來(lái)創(chuàng)建這個(gè) div。

現(xiàn)在呢我們給這個(gè) div 設(shè)置一些樣式:

<script setup>
import useWatermarkBg from './useWatermarkBg';
const props = defineProps({
	// ...
});
const bg = useWatermarkBg(props);
const div = document.createElement('div');
// 獲取到解構(gòu)的值
const { base64, styleSize } = bg;
// 背景設(shè)置為 base64 的圖片
div.style.backgroundImage = `url(${base64})`;
// 背景的大小設(shè)置為 styleSize
div.style.backgroundSize = `${styleSize}px ${styleSize}px`;
// 重復(fù)方式設(shè)置為 repeat
div.style.backgroundRepeat = 'repeat';
// 設(shè)置子元素與父元素四個(gè)方向的間隔(這里設(shè)置為 0 的效果同寬高設(shè)置 100%)
div.style.inset = 0;
// z-index 設(shè)置為 9999 覆蓋上去
div.style.zIndex = 9999;
</script>

樣式我們也只能通過(guò)上面的方式來(lái)添加,而不能直接寫成 class,具體原因后邊會(huì)解釋。

接下來(lái)我們要把這個(gè) div 添加到父元素里邊去:

<template>
  <!-- 在父元素上添加 ref -->
  <div class="watermark-container" ref="parentRef">
    <slot></slot>
    <!-- 添加一個(gè)div,填充滿整個(gè)區(qū)域,設(shè)置水印背景,重復(fù) -->
  </div>
</template>
<script setup>
import { ref, watchEffect } from 'vue';
import useWatermarkBg from './useWatermarkBg';
const props = defineProps({
  // ....
});
// 聲明一個(gè) ref 并添加到父元素上
const parentRef = ref(null);
const bg = useWatermarkBg(props);
// watchEffect 中判斷是否可以獲取到父組件的 ref
watchEffect(() => {
  // 獲取不到,就說(shuō)明還沒(méi)有掛載,先出去
  if (!parentRef.value) {
    return;
  }
  // 獲取到則添加到父元素中
  const { base64, styleSize } = bg;
  const div = document.createElement('div');
  div.style.backgroundImage = `url(${base64})`;
  div.style.backgroundSize = `${styleSize}px ${styleSize}px`;
  div.style.backgroundRepeat = 'repeat';
  div.style.inset = 0;
  div.style.zIndex = 9999;
  // 然后將 div 加到父元素里
  parentRef.value.appendChild(div);
});
</script>

你可以會(huì)發(fā)現(xiàn)我們這里使用的是 watchEffect 來(lái)判斷是否能獲取到父元素,而不是在 onMounted 里邊,這是因?yàn)檫@一塊會(huì)涉及到后邊的防篡改,我們一會(huì)就知道了,現(xiàn)在暫且不用管就放在這里。

可以看到 div 已經(jīng)被添加進(jìn)去了,背景圖以及屬性都是有的,只不過(guò)這個(gè) div 不是絕對(duì)定位,要填充滿的話就得設(shè)置絕對(duì)定位:

<script setup>
// etc...
watchEffect(() => {
  if (!parentRef.value) {
    return;
  }
  const div = document.createElement('div');
  const { base64, styleSize } = bg.value;
  div.style.backgroundImage = `url(${base64})`;
  div.style.backgroundSize = `${styleSize}px ${styleSize}px`;
  div.style.backgroundRepeat = 'repeat';
  div.style.inset = 0;
  div.style.zIndex = 9999;
  // 設(shè)置絕對(duì)定位
  div.style.position = 'absolute';
  // 設(shè)置點(diǎn)擊穿漏,防止底部元素失去鼠標(biāo)事件的交互
  div.style.pointerEvents = 'none';
  parentRef.value.appendChild(div);
});
</script>

你看,現(xiàn)在這個(gè)水印就加上了,沒(méi)有什么問(wèn)題,那么第一步加水印就完成了。

接下來(lái)我們就要說(shuō)第二步了,如何防篡改。

如何防篡改

用戶會(huì)怎么來(lái)篡改我們的水印呢?他有很多辦法,直接在頁(yè)面上操作不太可能,他主要的辦法就是進(jìn)入這個(gè)瀏覽器調(diào)試工具,找到我們這個(gè)水印的 div 然后刪除:

這樣一刪除就沒(méi)了,所以我們僅僅是把這個(gè)水印生成出來(lái)毫無(wú)意義,因?yàn)榭梢暂p松的刪除。

那這就要求我們必須要找到某一種方式,能夠監(jiān)控用戶對(duì)我們水印元素的操作,比如說(shuō)刪除。

所以這個(gè)防篡改就涉及到兩件事:

  1. 如何監(jiān)控
  2. 重新生成

這就解釋清楚了為什么不直接在父元素里寫 div 的原因,因?yàn)橹苯釉诟冈乩飳懙脑捜绻麆h除掉的話無(wú)法重新生成,但是通過(guò) document 添加的話就可以。

把 div 放在 watchEffect 里邊只要監(jiān)控到用戶動(dòng)了水印,只要在執(zhí)行一遍 watchEffect 就能重新生成一個(gè)新的水印添加進(jìn)去。

如果說(shuō)我們不是在 watchEffect 里還是在 onMounted 里就沒(méi)辦法那做到重新運(yùn)行了。

同時(shí)也解釋了為什么樣式不能寫在 class 里,因?yàn)樵?calss 里的話,用戶通過(guò)調(diào)試工具更改的話,我們同樣無(wú)法監(jiān)控到。

好了,剛才的三個(gè)疑問(wèn)現(xiàn)在都解決了。

如何監(jiān)控

現(xiàn)在的問(wèn)題就是我們?nèi)绾稳ケO(jiān)控的問(wèn)題了,我們?cè)趺粗烙脩魟?dòng)了水印呢?

那么這里就要說(shuō)到一個(gè) API 了,叫做 MutationObserve 它可以監(jiān)控一個(gè)元素的變化,不僅可以監(jiān)控元素本事,還可以監(jiān)控元素里邊所有的子元素,無(wú)論是改動(dòng)元素的屬性,還是元素的內(nèi)容,這個(gè) API 都可以收到通知。

我們現(xiàn)在就利用這會(huì) API 來(lái)實(shí)現(xiàn)監(jiān)控,首先我們要搞清楚的是,到底要監(jiān)控誰(shuí),我們要監(jiān)控的不是水印的 div,而是整個(gè)組件,這樣就可以監(jiān)控到所有的東西了。

所以我們可以這樣寫:

<script setup>
import { ref, watchEffect, onMounted, onUnmounted } from 'vue';
// etc...
let ob;
onMounted(() => {
  // 在 onMounted 里邊創(chuàng)建一個(gè) MutationObserver 來(lái)進(jìn)行監(jiān)控
  // 一旦某個(gè)東西有變化就會(huì)運(yùn)行這個(gè)回調(diào)函數(shù)
  ob = new MutationObserver((records) => {
    // 并把變化記錄下來(lái)傳遞給我們
    console.log('records >>> ', records)
  });
  // 創(chuàng)建好監(jiān)聽(tīng)器之后,告訴監(jiān)聽(tīng)器需要監(jiān)聽(tīng)的元素
  ob.observe(parentRef.value, {
    // 監(jiān)聽(tīng)的時(shí)候需要加一些配置
    childList: true, // 元素內(nèi)容有沒(méi)有發(fā)生變化
    attributes: true, // 元素本身的屬性有沒(méi)有發(fā)生變化
    subtree: true, // 告訴它監(jiān)控的是整個(gè)子樹(shù),就是包含整個(gè)子元素
  });
});
// 在組件卸載的時(shí)候取消監(jiān)聽(tīng)
onUnmounted(() => {
  ob && ob.disconnect(); // 取消監(jiān)聽(tīng)
});
</script>

現(xiàn)在我們就基本設(shè)置好了,看一下效果如何:

在最開(kāi)始的時(shí)候就打印了兩次,因?yàn)槲覀兲砑恿藘纱嗡〉?div,加這個(gè) div 的動(dòng)作就被監(jiān)聽(tīng)到了。

返回值是一個(gè)數(shù)組,表示我們的操作動(dòng)作,動(dòng)作里邊也明確的表示是添加節(jié)點(diǎn),并且是 div 節(jié)點(diǎn)。

如果我們刪除水印的 div,同樣也觸發(fā)了我們的回調(diào)函數(shù),動(dòng)作也記錄到了我們刪除了一個(gè) div 的節(jié)點(diǎn)。

通過(guò)對(duì)動(dòng)作的了解我們就可以知道如何來(lái)監(jiān)控節(jié)點(diǎn)的刪除,獲取到刪除的節(jié)點(diǎn)并且與我們添加的節(jié)點(diǎn)對(duì)比,就知道用戶是否刪除了我們的水印節(jié)點(diǎn),我們就可以這樣來(lái)寫:

<script setup>
// 將 div 保存在外部因?yàn)橐袛喙?jié)點(diǎn)時(shí)使用
let div;
watchEffect(() => {
  if (!parentRef.value) {
    return;
  }
  // 判斷之前的節(jié)點(diǎn)是否有內(nèi)容,如果有的話刪除
  if (div) {
    div.remove();
  }
  const { base64, styleSize } = bg.value;
  div = document.createElement('div');
  div.style.backgroundImage = `url(${base64})`;
  div.style.backgroundSize = `${styleSize}px ${styleSize}px`;
  div.style.backgroundRepeat = 'repeat';
  div.style.inset = 0;
  div.style.zIndex = 9999;
  div.style.position = 'absolute';
  div.style.pointerEvents = 'none';
  parentRef.value.appendChild(div);
});
let ob;
onMounted(() => {
  ob = new MutationObserver((records) => {
    // 循環(huán)節(jié)點(diǎn)的動(dòng)作
    for (const record of records) {
      // 如果有節(jié)點(diǎn)被刪除,循環(huán)一下判斷是否有水印的節(jié)點(diǎn)
      for (const dom of record.removedNodes) {
        if (dom === div) {
          console.log('水印被刪除')
          // ...
          return;
        }
      }
      // 如果有節(jié)點(diǎn)被修改,判斷一下是否是水印的節(jié)點(diǎn)
      if (record.target === div) {
        console.log('屬性被修改')
        // ...
        return;
      }
    }
  });
  ob.observe(parentRef.value, {
    childList: true,
    attributes: true,
    subtree: true,
  });
});
// 在組件卸載的時(shí)候取消監(jiān)聽(tīng)
onUnmounted(() => {
  ob && ob.disconnect(); // 取消監(jiān)聽(tīng)
  div = null; // 因?yàn)?div 是全局變量在寫在的時(shí)候值為空
});
</script>

水印刪除后事件就被觸發(fā)了。

屬性被修改時(shí)同樣會(huì)觸發(fā)事件。

重新生成

那么我們能監(jiān)控到事件了如何重新運(yùn)行 watchEffect 呢?因?yàn)?watchEffect 是收集依賴的,只要依賴變化了它就會(huì)重新運(yùn)行,所以我們可以手動(dòng)搞一個(gè)依賴:

<template>
  <div class="watermark-container" ref="parentRef">
    <slot></slot>
  </div>
</template>
<script setup>
import { onMounted, onUnmounted, ref, watchEffect } from 'vue';
import useWatermarkBg from './useWatermarkBg';
const props = defineProps({
  text: {
    type: String,
    required: true,
    default: 'watermark',
  },
  fontSize: {
    type: Number,
    default: 40,
  },
  gap: {
    type: Number,
    default: 20,
  },
});
const bg = useWatermarkBg(props);
const parentRef = ref(null);
const flag = ref(0); // 聲明一個(gè)依賴
let div;
watchEffect(() => {
  flag.value; // 將依賴放在 watchEffect 里
  if (!parentRef.value) {
    return;
  }
  if (div) {
    div.remove();
  }
  const { base64, styleSize } = bg.value;
  div = document.createElement('div');
  div.style.backgroundImage = `url(${base64})`;
  div.style.backgroundSize = `${styleSize}px ${styleSize}px`;
  div.style.backgroundRepeat = 'repeat';
  div.style.zIndex = 9999;
  div.style.position = 'absolute';
  div.style.inset = 0;
  parentRef.value.appendChild(div);
});
let ob;
onMounted(() => {
  ob = new MutationObserver((records) => {
    for (const record of records) {
      for (const dom of record.removedNodes) {
        if (dom === div) {
          flag.value++; // 刪除節(jié)點(diǎn)的時(shí)候更新依賴
          return;
        }
      }
      if (record.target === div) {
        flag.value++; // 修改屬性的時(shí)候更新依賴
        return;
      }
    }
  });
  ob.observe(parentRef.value, {
    childList: true,
    attributes: true,
    subtree: true,
  });
});
onUnmounted(() => {
  ob && ob.disconnect(); 
  div = null;
});
</script>

這樣就可以完成了,只要監(jiān)控到刪除或者修改屬性,就會(huì)重新運(yùn)行 watchEffect 重新生成一個(gè)新的水?。?/p>

總結(jié)

水印是一種保護(hù)知識(shí)產(chǎn)權(quán)的手段,但是如果只是簡(jiǎn)單的生成水印,很容易被用戶篡改或刪除。

所以我們需要使用一些技巧來(lái)防止水印被破壞,比如使用 canvas 生成背景圖,使用 document.createElement 添加水印元素,使用 MutationObserver 監(jiān)控元素變化,使用 watchEffect 重新生成水印等。

這樣我們就可以實(shí)現(xiàn)一個(gè)比較安全的水印組件,提高我們的網(wǎng)站的安全性和可信度。

像 Ant Design 里邊的水印就是這樣做的,沿著這個(gè)思路我們就可以一步一步的把這個(gè)組件給它完善掉。

以上就是使用Vue實(shí)現(xiàn)防篡改的水印的詳細(xì)內(nèi)容,更多關(guān)于Vue實(shí)現(xiàn)防篡改水印的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • vue中v-for循環(huán)給標(biāo)簽屬性賦值的方法

    vue中v-for循環(huán)給標(biāo)簽屬性賦值的方法

    這篇文章主要介紹了vue中v-for循環(huán)給標(biāo)簽屬性賦值的方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-10-10
  • vue二級(jí)路由設(shè)置方法

    vue二級(jí)路由設(shè)置方法

    下面小編就為大家分享一篇vue二級(jí)路由設(shè)置方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-02-02
  • vue實(shí)現(xiàn)密碼顯示隱藏功能的思路詳解

    vue實(shí)現(xiàn)密碼顯示隱藏功能的思路詳解

    這篇文章主要介紹了vue實(shí)現(xiàn)密碼顯示隱藏功能的思路詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • vue實(shí)現(xiàn)多欄布局拖拽

    vue實(shí)現(xiàn)多欄布局拖拽

    這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)多欄布局拖拽,改變盒子的寬度,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • elementUI table如何給表頭添加氣泡顯示

    elementUI table如何給表頭添加氣泡顯示

    這篇文章主要介紹了elementUI table如何給表頭添加氣泡顯示問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • vue修改對(duì)象的屬性值后頁(yè)面不重新渲染的實(shí)例

    vue修改對(duì)象的屬性值后頁(yè)面不重新渲染的實(shí)例

    今天小編就為大家分享一篇vue修改對(duì)象的屬性值后頁(yè)面不重新渲染的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08
  • 詳解vue-cli下ESlint 配置說(shuō)明

    詳解vue-cli下ESlint 配置說(shuō)明

    這篇文章主要介紹了詳解vue-cli下ESlint 配置說(shuō)明,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-09-09
  • vue框架render方法如何替換template

    vue框架render方法如何替換template

    這篇文章主要介紹了vue框架render方法如何替換template,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • VUE+elementui組件在table-cell單元格中繪制微型echarts圖

    VUE+elementui組件在table-cell單元格中繪制微型echarts圖

    這篇文章主要介紹了VUE+elementui組件在table-cell單元格中繪制微型echarts圖,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04
  • vue中Promise的使用方法詳情

    vue中Promise的使用方法詳情

    這篇文章主要介紹了vue中Promise的使用方法詳情,Promise可以說(shuō)是異步編程的一種解決方法,主要是為了解決代碼亂的情景而出現(xiàn)的,下文介紹其具體用法,需要的小伙伴可以參考一下
    2022-03-03

最新評(píng)論