国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

Maison interface Web js tutoriel Comment implémenter un composant de recadrage d'image à l'aide du terminal mobile Vue

Comment implémenter un composant de recadrage d'image à l'aide du terminal mobile Vue

Jun 23, 2018 pm 06:06 PM
vue

Cet article vous présente la fonction du composant de recadrage d'image du terminal mobile basée sur Vue. Parce que le terminal mobile utilise Vue, il est écrit comme un composant Vue Ci-dessous, je parlerai de certaines de mes idées d'implémentation. référez-vous à lui. Suivant

Un projet récent consiste à créer une fonction de reconnaissance de plaque d'immatriculation. Au départ, je pensais que c'était très simple, il suffit de jeter l'image en arrière-plan, mais après tests, le taux de reconnaissance n'était que de 20 à 40 %. Par conséquent, le produit recommande qu'après avoir pris une photo, vous puissiez faire glisser et zoomer sur l'image, puis recadrer la partie de la plaque d'immatriculation et la télécharger en arrière-plan pour améliorer le taux de reconnaissance. Au début, j'ai vérifié Baidu pour voir s'il y avait des composants prêts à l'emploi, mais je n'ai pas pu en trouver un qui me convienne. Heureusement, je n'étais pas très inquiet à propos de cette fonction, alors je l'ai étudiée à la maison le week-end.

Adresse de démonstration : https://vivialex.github.io/demo/imageClipper/index.html

Adresse de téléchargement : https://github.com/vivialex/vue-imageClipper

étant donné que le terminal mobile utilise Vue, je l'ai écrit en tant que composant Vue Parlons de certaines de mes idées d'implémentation (j'ai des compétences limitées, veuillez comprendre. De plus, le code affiché n'est pas nécessairement complet pour une certaine fonction. . code), jetez d'abord un ?il à l'effet?:

 1. Paramètres d'initialisation du composant

1. Image img (url ou data-url base64)

2. Largeur de la capture d'écran clipperImgWidth

3. Hauteur de la capture d'écran clipperImgHeight

props: {
  img: String, //url或dataUrl
  clipperImgWidth: {
    type: Number,
    default: 500
  },
  clipperImgHeight: {
    type: Number,
    default: 200
  }
}

2. Disposition

En regardant dans la direction de l'axe Z, elle est principalement composée de 4 couches. Le premier calque est un canevas (appelé cCanvas) qui occupe tout le conteneur?; le deuxième calque est un calque de masque transparent, le troisième calque est la zone recadrée (la zone blanche dans l'image d'exemple), qui contient un canevas de tailles égales?; (appelé pCanvas)?; le quatrième calque est un masque de geste de calque transparent, utilisé pour lier les événements touchstart, touchmove, touchend. Les deux toiles chargeront la même image, mais les coordonnées de départ sont différentes. Pourquoi avons-nous besoin de deux toiles ? Parce que je veux créer l'effet que lorsque le doigt quitte l'écran, une partie de la surface en dehors de la zone de recadrage aura un effet de calque de masque, qui peut mettre en évidence le contenu de la zone de recadrage.

<p class="cut-container" ref="cut">
  <canvas ref="canvas"></canvas>
  <!-- 裁剪部分 -->
  <p class="cut-part">
    <p class="pCanvas-container">
      <canvas ref="pCanvas"></canvas>
    </p>
  </p>
  <!-- 底部操作欄 -->
  <p class="action-bar">
    <button class="btn-cancel" @click="_cancel">取消</button>
    <button class="btn-ok" @click="_cut">確認(rèn)</button>
  </p>
  <!-- 背景遮罩 -->
  <p class="mask" :class="{opacity: maskShow}"></p>
  <!-- 手勢操作層 -->
  <p class="gesture-mask" ref="gesture"></p>
</p>

  3. Initialiser la toile

L'image dessinée par la toile appara?tra floue sur l'écran HDPI. Les raisons spécifiques ne le seront pas. analysé ici. Vous pouvez vous y référer ici. Ce que je fais ici, c'est faire en sorte que la largeur et la hauteur du canevas soient multipliées par le devicePixelRatio de sa largeur/hauteur CSS, et les paramètres transmis lors de l'appel de l'API du canevas doivent être multipliés par window.devicePixelRatio. Enfin, enregistrez la différence x, y entre les deux origines des coordonnées du canevas (originXDiff et originYDiff). Comme suit

_ratio(size) {
  return parseInt(window.devicePixelRatio * size);
},
_initCanvas() {
  let $canvas = this.$refs.canvas,
    $pCanvas = this.$refs.pCanvas,
    clipperClientRect = this.$refs.clipper.getBoundingClientRect(),
    clipperWidth = parseInt(this.clipperImgWidth / window.devicePixelRatio),
    clipperHeight = parseInt(this.clipperImgHeight / window.devicePixelRatio);

  this.ctx = $canvas.getContext(&#39;2d&#39;);
  this.pCtx = $pCanvas.getContext(&#39;2d&#39;);

  //判斷clipperWidth與clipperHeight有沒有超過容器值
  if (clipperWidth < 0 || clipperWidth > clipperClientRect.width) {
    clipperWidth = 250
  }

  if (clipperHeight < 0 || clipperHeight > clipperClientRect.height) {
    clipperHeight = 100
  }

  //因為canvas在手機上會被放大,因此里面的內(nèi)容會模糊,這里根據(jù)手機的devicePixelRatio來放大canvas,然后再通過設(shè)置css來收縮,因此關(guān)于canvas的所有值或坐標(biāo)都要乘以devicePixelRatio
  $canvas.style.width = clipperClientRect.width + &#39;px&#39;;
  $canvas.style.height = clipperClientRect.height + &#39;px&#39;;
  $canvas.width = this._ratio(clipperClientRect.width);
  $canvas.height = this._ratio(clipperClientRect.height);

  $pCanvas.style.width = clipperWidth + &#39;px&#39;;
  $pCanvas.style.height = clipperHeight + &#39;px&#39;;
  $pCanvas.width = this._ratio(clipperWidth);
  $pCanvas.height = this._ratio(clipperHeight);

  //計算兩個canvas原點的x y差值
  let cClientRect = $canvas.getBoundingClientRect(),
    pClientRect = $pCanvas.getBoundingClientRect();

  this.originXDiff = pClientRect.left - cClientRect.left;
  this.originYDiff = pClientRect.top - cClientRect.top;
  this.cWidth = cClientRect.width;
  this.cHeight = cClientRect.height;
}

IV. Chargement d'images

Le chargement d'images est relativement simple. Tout d'abord, créez un objet Image et écoutez le chargement. événement (car l'image chargée peut être inter-domaines, définissez donc son attribut crossOrigin sur Anonyme, puis définissez l'en-tête de réponse Access-Control-Allow-Origin sur le serveur). Si la largeur et la hauteur de l'image chargée sont supérieures à la largeur et à la hauteur du conteneur, elles doivent être réduites. Enfin, l'affichage de centrage vertical et horizontal () (notez ici qu'il faut enregistrer la valeur de largeur et de hauteur avant que l'image ne soit dessinée, car la future mise à l'échelle de l'image sera basée sur cette valeur puis multipliée par le facteur de zoom, prenez ici imgStartWidth, imgStartHeight) comme suit

_loadImg() {
  if (this.imgLoading || this.loadImgQueue.length === 0) {
    return;
  }
  let img = this.loadImgQueue.shift();
  if (!img) {
    return;
  }
  let $img = new Image(),
    onLoad = e => {
      $img.removeEventListener(&#39;load&#39;, onLoad, false);
      this.$img = $img;
      this.imgLoaded = true;
      this.imgLoading = false;
      this._initImg($img.width, $img.height);
      this.$emit(&#39;loadSuccess&#39;, e);
      this.$emit(&#39;loadComplete&#39;, e);
      this._loadImg();
    },
    onError = e => {
      $img.removeEventListener(&#39;error&#39;, onError, false);
      this.$img = $img = null;
      this.imgLoading = false;
      this.$emit(&#39;loadError&#39;, e);
      this.$emit(&#39;loadComplete&#39;, e);
      this._loadImg();
    };
  this.$emit(&#39;beforeLoad&#39;);
  this.imgLoading = true;
  this.imgLoaded = false;
  $img.src = this.img;
  $img.crossOrigin = &#39;Anonymous&#39;; //因為canvas toDataUrl不能操作未經(jīng)允許的跨域圖片,這需要服務(wù)器設(shè)置Access-Control-Allow-Origin頭
  $img.addEventListener(&#39;load&#39;, onLoad, false);
  $img.addEventListener(&#39;error&#39;, onError, false);
}
_initImg(w, h) {
  let eW = null,
    eH = null,
    maxW = this.cWidth,
    maxH = this.cHeight - this.actionBarHeight;
  //如果圖片的寬高都少于容器的寬高,則不做處理
  if (w <= maxW && h <= maxH) {
    eW = w;
    eH = h;
  } else if (w > maxW && h <= maxH) {
    eW = maxW;
    eH = parseInt(h / w * maxW);
  } else if (w <= maxW && h > maxH) {
    eW = parseInt(w / h * maxH);
    eH = maxH;
  } else {
    //判斷是橫圖還是豎圖
    if (h > w) {
      eW = parseInt(w / h * maxH);
      eH = maxH;
    } else {
      eW = maxW;
      eH = parseInt(h / w * maxW);
    }
  }
  if (eW <= maxW && eH <= maxH) {
    //記錄其初始化的寬高,日后的縮放功能以此值為基礎(chǔ)
    this.imgStartWidth = eW;
    this.imgStartHeight = eH;
    this._drawImage((maxW - eW) / 2, (maxH - eH) / 2, eW, eH);
  } else {
    this._initImg(eW, eH);
  }
}

  5. Dessinez une image

Le _drawImage suivant a quatre paramètres, qui sont le x, Coordonnées y de l'image correspondant à cCanvas et la largeur actuelle de l'image High w, h. La fonction effacera d'abord le contenu des deux toiles en réinitialisant la largeur et la hauteur de la toile. Mettez ensuite à jour la valeur correspondante dans l'instance du composant, et enfin appelez le drawImage des deux canevas pour dessiner l'image. Pour pCanvas, les valeurs de coordonnées de l'image dessinée sont x et y moins les originXDiff et originYDiff correspondants (en fait, cela équivaut à changer l'affichage du système de coordonnées, il vous suffit donc de soustraire la différence x et y entre les origines du deux systèmes de coordonnées) ). Jetez un ?il au code

_drawImage(x, y, w, h) {
  this._clearCanvas();
  this.imgX = parseInt(x);
  this.imgY = parseInt(y);
  this.imgCurrentWidth = parseInt(w);
  this.imgCurrentHeight = parseInt(h);
  //更新canvas
  this.ctx.drawImage(this.$img, this._ratio(x), this._ratio(y), this._ratio(w), this._ratio(h));
  //更新pCanvas,只需要減去兩個canvas坐標(biāo)原點對應(yīng)的差值即可
  this.pCtx.drawImage(this.$img, this._ratio(x - this.originXDiff), this._ratio(y - this.originYDiff), this._ratio(w), this._ratio(h));
},
_clearCanvas() {
  let $canvas = this.$refs.canvas,
    $pCanvas = this.$refs.pCanvas;
  $canvas.width = $canvas.width;
  $canvas.height = $canvas.height;
  $pCanvas.width = $pCanvas.width;
  $pCanvas.height = $pCanvas.height;
}

  6. Images animées

La mise en ?uvre des images animées est très simple. Commencez par lier touchstart et. touchmove to geste-mask , événement touchend, le contenu de ces trois événements est présenté ci-dessous

Définissez d'abord quatre variables scx, scy (les coordonnées de départ du doigt), iX, iY (les coordonnées actuelles de l'image , par rapport à cCanvas).

1. touchstart

La méthode est très simple, il suffit d'obtenir la pageX et la pageY de touches[0] pour mettre à jour scx et scy et mettre à jour iX et iY

2. touchmove

 Récupérez la pageX de touches[0], déclarez la variable f1x pour la stocker, la coordonnée x après le mouvement est égale à iX + f1x - scx, la coordonnée y est la même, et enfin appelez _drawImage à mettre à jour l'image.

Jetons un coup d'?il au code

_initEvent() {
  let $gesture = this.$refs.gesture,
    scx = 0,
    scy = 0;
  let iX = this.imgX,
    iY = this.imgY;
  $gesture.addEventListener(&#39;touchstart&#39;, e => {
    if (!this.imgLoaded) {
      return;
    }
    let finger = e.touches[0];
      scx = finger.pageX;
      scy = finger.pageY;
      iX = this.imgX;
      iY = this.imgY;  
  }, false);
  $gesture.addEventListener(&#39;touchmove&#39;, e => {
    e.preventDefault();
    if (!this.imgLoaded) {
      return;
    }
    let f1x = e.touches[0].pageX,
      f1y = e.touches[0].pageY;
      this._drawImage(iX + f1x - scx, iY + f1y - scy, this.imgCurrentWidth, this.imgCurrentHeight);
  }, false);
}

   七、縮放圖片(這里不作特別說明的坐標(biāo)都是相對于cCanvas坐標(biāo)系)

  繪制縮放后的圖片無非需要4個參數(shù),縮放后圖片左上角的坐標(biāo)以及寬高。求寬高相對好辦,寬高等于imgStartWidth * 縮放比率與imgstartHeight * 縮放倍率(imgStartWidth ,imgstartHeight 上文第四節(jié)有提到)。接下來就是求縮放倍率的問題了,首先在touchstart事件上求取兩手指間的距離d1;然后在touchmove事件上繼續(xù)求取兩手指間的距離d2,當(dāng)前縮放倍率= 初始縮放倍率 + (d2-d1) / 步長(例如每60px算0.1),touchend事件上讓初始縮放倍率=當(dāng)前縮放倍率。

  至于如何求取縮放后圖片左上角的坐標(biāo)值,在草稿紙上畫來畫去,畫了很久......終于有點眉目。首先要找到一個縮放中心(這里做法是取雙指的中點坐標(biāo),但是這個坐標(biāo)必須要位于圖片上,如果不在圖片上,則取圖片上離該中點坐標(biāo)最近的點),然后存在下面這個等式

 ?。s放中心x坐標(biāo) - 縮放后圖片左上角x坐標(biāo))/ 縮放后圖片的寬度 = (縮放中心x坐標(biāo) - 縮放前圖片左上角x坐標(biāo))/ 縮放前圖片的寬度;(y坐標(biāo)同理)

  接下來看看下面這個例子(在visio找了很久都沒有畫坐標(biāo)系的功能,所以只能手工畫了)

  

  綠色框是一張10*5的圖片,藍色框是寬高放大兩倍后的圖片20*10,根據(jù)上面的公式推算的x2 = sx - w2(sx - x1) / w1,y2 = sy - h2(sy - y1) / h1。

  堅持...繼續(xù)看看代碼吧

_initEvent() {
  let $gesture = this.$refs.gesture,
    cClientRect = this.$refs.canvas.getBoundingClientRect(),
    scx = 0, //對于單手操作是移動的起點坐標(biāo),對于縮放是圖片距離兩手指的中點最近的圖標(biāo)。
    scy = 0,
    fingers = {}; //記錄當(dāng)前有多少只手指在觸控屏幕
  //one finger
  let iX = this.imgX,
    iY = this.imgY;
  //two finger
  let figureDistance = 0,
    pinchScale = this.imgScale;
  $gesture.addEventListener(&#39;touchstart&#39;, e => {
    if (!this.imgLoaded) {
      return;
    }
    if (e.touches.length === 1) {
      let finger = e.touches[0];
      scx = finger.pageX;
      scy = finger.pageY;
      iX = this.imgX;
      iY = this.imgY;
      fingers[finger.identifier] = finger;
    } else if (e.touches.length === 2) {
      let finger1 = e.touches[0],
        finger2 = e.touches[1],
        f1x = finger1.pageX - cClientRect.left,
        f1y = finger1.pageY - cClientRect.top,
        f2x = finger2.pageX - cClientRect.left,
        f2y = finger2.pageY - cClientRect.top;
      scx = parseInt((f1x + f2x) / 2);
      scy = parseInt((f1y + f2y) / 2);
      figureDistance = this._pointDistance(f1x, f1y, f2x, f2y);
      fingers[finger1.identifier] = finger1;
      fingers[finger2.identifier] = finger2;
      //判斷變換中點是否在圖片中,如果不是則去離圖片最近的點
      if (scx < this.imgX) {
        scx = this.imgX;
      }
      if (scx > this.imgX + this.imgCurrentWidth) {
        scx = this.imgX + this.imgCurrentHeight;
      }
      if (scy < this.imgY) {
        scy = this.imgY;
      }
      if (scy > this.imgY + this.imgCurrentHeight) {
        scy = this.imgY + this.imgCurrentHeight;
      }
    }
  }, false);
  $gesture.addEventListener(&#39;touchmove&#39;, e => {
    e.preventDefault();
    if (!this.imgLoaded) {
      return;
    }
    this.maskShowTimer && clearTimeout(this.maskShowTimer);
    this.maskShow = false;
    if (e.touches.length === 1) {
      let f1x = e.touches[0].pageX,
        f1y = e.touches[0].pageY;
      this._drawImage(iX + f1x - scx, iY + f1y - scy, this.imgCurrentWidth, this.imgCurrentHeight);
    } else if (e.touches.length === 2) {
      let finger1 = e.touches[0],
        finger2 = e.touches[1],
        f1x = finger1.pageX - cClientRect.left,
        f1y = finger1.pageY - cClientRect.top,
        f2x = finger2.pageX - cClientRect.left,
        f2y = finger2.pageY - cClientRect.top,
        newFigureDistance = this._pointDistance(f1x, f1y, f2x, f2y),
        scale = this.imgScale + parseFloat(((newFigureDistance - figureDistance) / this.imgScaleStep).toFixed(1));
      fingers[finger1.identifier] = finger1;
      fingers[finger2.identifier] = finger2;
      if (scale !== pinchScale) {
        //目前縮放的最小比例是1,最大是5
        if (scale < this.imgMinScale) {
          scale = this.imgMinScale;
        } else if (scale > this.imgMaxScale) {
          scale = this.imgMaxScale;
        }
        pinchScale = scale;
        this._scale(scx, scy, scale);
      }
    }
  }, false);
  $gesture.addEventListener(&#39;touchend&#39;, e => {
    if (!this.imgLoaded) {
      return;
    }
    this.imgScale = pinchScale;
    //從finger刪除已經(jīng)離開的手指
    let touches = Array.prototype.slice.call(e.changedTouches, 0);
    touches.forEach(item => {
      delete fingers[item.identifier];
    });
    //迭代fingers,如果存在finger則更新scx,scy,iX,iY,因為可能縮放后立即單指拖動
    let i,
      fingerArr = [];
    for(i in fingers) {
      if (fingers.hasOwnProperty(i)) {
        fingerArr.push(fingers[i]);
      }
    }
    if (fingerArr.length > 0) {
      scx = fingerArr[0].pageX;
      scy = fingerArr[0].pageY;
      iX = this.imgX;
      iY = this.imgY;
    } else {
      this.maskShowTimer = setTimeout(() => {
        this.maskShow = true;
      }, 300);
    }
    //做邊界值檢測
    let x = this.imgX,
      y = this.imgY,
      pClientRect = this.$refs.pCanvas.getBoundingClientRect();
    if (x > pClientRect.left + pClientRect.width) {
      x = pClientRect.left
    } else if (x + this.imgCurrentWidth < pClientRect.left) {
      x = pClientRect.left + pClientRect.width - this.imgCurrentWidth;
    }
    if (y > pClientRect.top + pClientRect.height) {
      y = pClientRect.top;
    } else if (y + this.imgCurrentHeight < pClientRect.top) {
      y = pClientRect.top + pClientRect.height - this.imgCurrentHeight;
    }
    if (this.imgX !== x || this.imgY !== y) {
      this._drawImage(x, y, this.imgCurrentWidth, this.imgCurrentHeight);
    }
  });
},
_scale(x, y, scale) {
  let newPicWidth = parseInt(this.imgStartWidth * scale),
    newPicHeight = parseInt(this.imgStartHeight * scale),
    newIX = parseInt(x - newPicWidth * (x - this.imgX) / this.imgCurrentWidth),
    newIY = parseInt(y - newPicHeight * (y - this.imgY) / this.imgCurrentHeight);
  this._drawImage(newIX, newIY, newPicWidth, newPicHeight);
},
_pointDistance(x1, y1, x2, y2) {
  return parseInt(Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)));
}

  說明一下fingers是干嘛的,是用來記錄當(dāng)前有多少只手指在屏幕上觸摸。可能會出現(xiàn)這種情況,雙指縮放后,其中一只手指移出顯示屏,而另外一個手指在顯示屏上移動。針對這種情況,要在touchend事件上根據(jù)e.changedTouches來移除fingers里已經(jīng)離開顯示屏的finger,如果此時fingers里只剩下一個finger,則更新scx,scy,iX,iY為移動圖片做初始化準(zhǔn)備。

  八、裁剪圖片

  這里很簡單,就調(diào)用pCanvas的toDataURL方法就可以了

_clipper() {
  let imgData = null;
  try {
    imgData = this.$refs.pCanvas.toDataURL();
  } catch (e) {
    console.error(&#39;請在response header加上Access-Control-Allow-Origin,否則canvas無法裁剪未經(jīng)許可的跨域圖片&#39;);
  }
  this.$emit(&#39;sure&#39;, imgData);
}

上面是我整理給大家的,希望今后會對大家有幫助。

相關(guān)文章:

在Bootstrap框架里使用treeview如何實現(xiàn)動態(tài)加載數(shù)據(jù)

在Nginx中如何配置多站點vhost

在vue中如何實現(xiàn)跳轉(zhuǎn)到之前頁面

在express+mockjs中如何實現(xiàn)后臺數(shù)據(jù)發(fā)送

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefa?on, veuillez contacter admin@php.cn

Outils d'IA chauds

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

Video Face Swap

Video Face Swap

échangez les visages dans n'importe quelle vidéo sans effort grace à notre outil d'échange de visage AI entièrement gratuit?!

Article chaud

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds

Tutoriel PHP
1502
276
Comment développer une application Web Python complète? Comment développer une application Web Python complète? May 23, 2025 pm 10:39 PM

Pour développer une application Web Python complète, suivez ces étapes: 1. Choisissez le cadre approprié, tel que Django ou Flask. 2. Intégrez les bases de données et utilisez des orms tels que Sqlalchemy. 3. Concevez le frontal et utilisez Vue ou React. 4. Effectuez le test, utilisez Pytest ou Unittest. 5. Déployer les applications, utiliser Docker et des plates-formes telles que Heroku ou AWS. Grace à ces étapes, des applications Web puissantes et efficaces peuvent être construites.

Comment travailler et configuration du routage frontal (routeur Vue, routeur React)? Comment travailler et configuration du routage frontal (routeur Vue, routeur React)? May 20, 2025 pm 07:18 PM

Le c?ur du système de routage frontal est de mapper les URL aux composants. VUerouter et Reactrouter réalisent la commutation de page sans rafra?chissement en écoutant les modifications de l'URL et en chargeant des composants correspondants. Les méthodes de configuration incluent: 1. Routing imbriqué, permettant aux composants enfants imbriqués dans le composant parent; 2. Routing dynamique, chargeant différents composants en fonction des paramètres URL; 3. Route Guard, effectuer une logique telle que les vérifications d'autorisation avant et après la commutation de l'itinéraire.

Quelle est la signification de la transformation de la réactivité de Vue (expérimentale, puis supprimée) et de ses objectifs? Quelle est la signification de la transformation de la réactivité de Vue (expérimentale, puis supprimée) et de ses objectifs? Jun 20, 2025 am 01:01 AM

ReactivitytransforminVue3aimedtosimplifyhandlingreactivedatabyautomaticallytrackingandmanagingreactivitywithoutrequiringmanualref()or.valueusage.Itsoughttoreduceboilerplateandimprovecodereadabilitybytreatingvariableslikeletandconstasautomaticallyreac

Quelles sont les différences de base entre Vue.js et réagir dans le développement composant? Quelles sont les différences de base entre Vue.js et réagir dans le développement composant? May 21, 2025 pm 08:39 PM

Les différences de base entre Vue.js et React dans le développement des composants sont: 1) Vue.js utilise la syntaxe du modèle et l'option API, tandis que React utilise JSX et les composants fonctionnels; 2) Vue.js utilise des systèmes réactifs, React utilise des données immuables et un DOM virtuel; 3) Vue.js fournit plusieurs crochets de cycle de vie, tandis que React utilise plus de crochets d'effet d'utilisation.

Comment l'internationalisation (I18N) et la localisation (L10N) peuvent-elles être mises en ?uvre dans une application VUE? Comment l'internationalisation (I18N) et la localisation (L10N) peuvent-elles être mises en ?uvre dans une application VUE? Jun 20, 2025 am 01:00 AM

Internationalisation et olocalisation dans la variation des acquis

Vue Principe et solution réactifs pour ne pas déclencher des mises à jour de la vue lorsque les mises à jour du tableau? Vue Principe et solution réactifs pour ne pas déclencher des mises à jour de la vue lorsque les mises à jour du tableau? May 20, 2025 pm 06:54 PM

Lorsque Vue.js gère les mises à jour du tableau, la vue n'est pas mise à jour car object.defineproperty ne peut pas écouter directement les modifications du tableau. Les solutions incluent: 1. Utilisez la méthode Vue.Set pour modifier l'index du tableau; 2. Réaffectez l'intégralité du tableau; 3. Utilisez la méthode de mutation réécrite de Vue pour faire fonctionner le tableau.

Quels sont les avantages de l'utilisation d'attributs clés (: clé) avec les directives V-FOR dans Vue? Quels sont les avantages de l'utilisation d'attributs clés (: clé) avec les directives V-FOR dans Vue? Jun 08, 2025 am 12:14 AM

En utilisant: keyattributewithv-forrinvuesessentialforperformanceAndCorrectBehavior.Ort, itHelpsvueTrackEachElementation efficace par ce que

Comment pouvez-vous optimiser la rediffusion de grandes listes ou de composants complexes dans VUE? Comment pouvez-vous optimiser la rediffusion de grandes listes ou de composants complexes dans VUE? Jun 07, 2025 am 12:14 AM

Les méthodes pour optimiser les performances des grandes listes et des composants complexes dans Vue incluent: 1. Utilisez la directive V-ONCE pour traiter le contenu statique pour réduire les mises à jour inutiles; 2. Implémentez le défilement virtuel et ne rendez que le contenu de la zone visuelle, comme l'utilisation de la bibliothèque Vue-Virtual-Croller; 3. Composants de cache via Keep-Alive ou V-ONCE pour éviter les supports en double; 4. Utilisez des propriétés et des auditeurs calculés pour optimiser la logique réactive pour réduire la plage de réinstallation; 5. Suivez les meilleures pratiques, comme l'utilisation de clés uniques en V-FOR, en évitant les fonctions en ligne dans les modèles et en utilisant des outils d'analyse des performances pour localiser les goulots d'étranglement. Ces stratégies peuvent améliorer efficacement la ma?trise de l'application.

See all articles