最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue動(dòng)態(tài)渲染svg、添加點(diǎn)擊事件的實(shí)現(xiàn)

 更新時(shí)間:2020年03月13日 10:02:22   作者:小謳  
這篇文章主要介紹了vue動(dòng)態(tài)渲染svg、添加點(diǎn)擊事件的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

業(yè)務(wù)需求(vue項(xiàng)目中)

1.頁(yè)面展示svg內(nèi)容
2.監(jiān)聽svg內(nèi)部的點(diǎn)擊事件
3.動(dòng)態(tài)改變svg內(nèi)部元素的屬性和值

html標(biāo)簽

經(jīng)多次實(shí)驗(yàn),用embed、img等標(biāo)簽改變src屬性的方式,均無(wú)法實(shí)現(xiàn)上述全部功能(尤其是svg內(nèi)部點(diǎn)擊事件),最終采用Vue.extend()方法完整實(shí)現(xiàn),代碼也較為簡(jiǎn)潔,html結(jié)構(gòu)如下:

<template>
 <div>
  <div id="svgTemplate"></div>
 </div>
</template>

直接將svg文件的內(nèi)容復(fù)制粘貼到.vue文件里,是可以在標(biāo)簽內(nèi)直接添加@click事件完成需求的,方式簡(jiǎn)單但會(huì)造成文件過(guò)長(zhǎng),本文不多陳述

實(shí)現(xiàn)思路

1.創(chuàng)建xhr對(duì)象

const xhr = new XMLHttpRequest();
this.svgUrl = ...; // svg的絕對(duì)地址,在瀏覽器中打開能看到的那個(gè)
xhr.open("GET", this.svgUrl, true);
xhr.send();

2.監(jiān)聽xhr對(duì)象(獲取svg的dom -> 添加事件 -> 修改dom -> 轉(zhuǎn)成虛擬dom并掛載)

xhr.addEventListener("load", () => {
  // ① 獲取svg的dom
  const resXML = xhr.responseXML;
  this.svgDom = resXML.documentElement.cloneNode(true);   // console.log(this.svgDom);
  
  // ② 添加click事件
  let btn = this.svgDom.getElementById("...");
  btn.setAttribute("v-on:click", "this.handleClick()");
  // ↑↑↑ 此處注意:原生事件handleClick此時(shí)在window層,解決辦法見后文

  // ③ 修改 dom
  this.svgDom.getElementById("...").childNodes[0].nodeValue = ...
  this.svgDom.getElementById("...").setAttribute("style",
     `....; fill:${this.photoResult.resultColor}; ...`);
  // ↑↑↑ 用js操作dom的語(yǔ)法,動(dòng)態(tài)設(shè)置svg部件的屬性和值
  
  // ④ 將svgDom對(duì)象轉(zhuǎn)換成vue的虛擬dom,創(chuàng)建實(shí)例并掛載到元素上
  var oSerializer = new XMLSerializer();
  var sXML = oSerializer.serializeToString(this.svgDom);
  var Profile = Vue.extend({
    template: "<div id='svgTemplate'>" + sXML + "</div>"
  });
  new Profile().$mount("#svgTemplate");
});

3.將methods里要執(zhí)行的事件綁定到window下面,供外部(剛添加的 handleClick 事件)調(diào)用

async mounted() {
  window["handleClick"] = () => {
    this.takePhoto();
  };
},
methods:{
  takePhoto(){ ... }
}

到這里就基本完成需求:動(dòng)態(tài)渲染了svg、用js操作dom的語(yǔ)法修改svg部件的屬性和值、給svg部件動(dòng)態(tài)添加了事件 handleClick,最后將 takePhoto() 事件綁定給了 window 對(duì)象的 handleClick,可以放心大膽的在 takePhoto() 里寫你要執(zhí)行的內(nèi)容了!

特殊注意

給svg的dom部件添加事件時(shí):
1.經(jīng)多次嘗試,只有 setAttribute + v-on:click 寫法有效
2.setAttribute 不支持 @click(非原生事件),會(huì)報(bào)語(yǔ)法錯(cuò)誤
3.addEventListener 和 onclick 均會(huì)被 vue 攔截
將svgDom對(duì)象轉(zhuǎn)換成vue的虛擬dom時(shí):
1.如果報(bào)錯(cuò)如下

則將 import Vue from "vue" 改為 import Vue from "vue/dist/vue.esm.js"
其原因及其他解決辦法本文不做探討可自行百度。
2.vue.extend() 方法是 vue 的一個(gè)構(gòu)造器,用來(lái)動(dòng)態(tài)創(chuàng)建 vue 實(shí)例,template 組件模板只能有一個(gè)根元素
3.$mount 手動(dòng)掛載到 id 為 svgTemplate的 元素上,掛載后將替換原本的dom(替換原本的 <div id="svgTemplate"></div>)。由于每次更新 svg 都要重新掛載,沒有找到 dom 元素是無(wú)法掛載的,因此 template 里面最外層的 div 也要加上 id 的屬性:

var Profile = Vue.extend({
   template: "<div id='svgTemplate'>" + sXML + "</div>" 
   // ↑↑↑ 最外層的 id 不能省略,否則首次渲染后找不到 #svgTemplate
});
new Profile().$mount("#svgTemplate"); 
// ↑↑↑ 原本的 #svgTemplate 將被替換成 Profile 的 template

完整代碼

<template>
 <div>
  <div id="svgTemplate"></div>
 </div>
</template>
<script>
import Vue from "vue/dist/vue.esm.js";

// window.handleClick = () => {
  // 原本的 handleClick 事件是 window 的
// };

export default {
 name: "svg-drawing",
 data() {
  return {
   /* 全局 */
   svgUrl: "", // svg的url
   svgDom: null, // 獲取到的svg元素
   /* svg的變量 */
   photoResult: {
    resultVal: 0, // 測(cè)試結(jié)果 - 值
    resultMsg: "未檢測(cè)", // 測(cè)試結(jié)果 - 字段
    resultColor: "#dcdee2" // 測(cè)試結(jié)果 - 字段背景色
   }
  };
 },
 async mounted() {
  // 將takePhoto方法綁定到window下面,提供給外部調(diào)用
  window["handleClick"] = () => {
   this.takePhoto();
  };
 },
 created() {
  this.getSvg();
 },
 methods: {
  // 初始化svg
  getSvg() {
   /* 創(chuàng)建xhr對(duì)象 */
   const xhr = new XMLHttpRequest();
   this.svgUrl = this.baseUrl + "/svgs/" + "test.svg";
   xhr.open("GET", this.svgUrl, true);
   xhr.send();

   /* 監(jiān)聽xhr對(duì)象 */
   xhr.addEventListener("load", () => {
    /* 1. 獲取 dom */
    const resXML = xhr.responseXML;
    this.svgDom = resXML.documentElement.cloneNode(true);

    /* 2.SVG對(duì)象添加click事件 */
    let btnTakePhotoDom = this.svgDom.getElementById("...");
    btnTakePhotoDom.setAttribute("v-on:click", "this.handleClick()");

    /* 3. 修改 dom */
    this.svgDom.getElementById("...").childNodes[0].nodeValue = ...;
    this.svgDom.getElementById("...").setAttribute("style",
     `....; fill:${this.photoResult.resultColor}; ...`);

    /* 4.將svgDom對(duì)象轉(zhuǎn)換成vue的虛擬dom */
    var oSerializer = new XMLSerializer();
    var sXML = oSerializer.serializeToString(this.svgDom);
    var Profile = Vue.extend({
     template: "<div id='svgTemplate'>" + sXML + "</div>"
    });
    // 創(chuàng)建實(shí)例,并掛載到元素上
    new Profile().$mount("#svgTemplate");
   });
  },
  // 事件
  takePhoto() { ... },
 },
 beforeDestroy() {
  this.svgDom = null;
 },
 watch: {
  photoResult: {
   handler(newVal, oldVal) {
    this.getSvg();
   },
   deep: true
  }
 }
};
</script>

到此這篇關(guān)于vue動(dòng)態(tài)渲染svg、添加點(diǎn)擊事件的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)vue動(dòng)態(tài)渲染svg、添加點(diǎn)擊事件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue3 element-plus二次封裝組件系列之伸縮菜單制作

    vue3 element-plus二次封裝組件系列之伸縮菜單制作

    這篇文章主要介紹了vue3 element-plus二次封裝組件系列之伸縮菜單制作,是基于vue3 vite element-plus搭建的,值的注意的時(shí)候,里面的圖標(biāo)組件是經(jīng)過(guò)處理的,結(jié)合實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-01-01
  • 在vs code 中如何創(chuàng)建一個(gè)自己的 Vue 模板代碼

    在vs code 中如何創(chuàng)建一個(gè)自己的 Vue 模板代碼

    這篇文章主要介紹了在vs code 中如何創(chuàng)建一個(gè)自己的 Vue 模板代碼,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • vue實(shí)現(xiàn)全選和反選功能

    vue實(shí)現(xiàn)全選和反選功能

    這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)全選和反選功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • vuex頁(yè)面刷新數(shù)據(jù)丟失問(wèn)題的四種解決方式

    vuex頁(yè)面刷新數(shù)據(jù)丟失問(wèn)題的四種解決方式

    vuex是大家使用vue時(shí)大多數(shù)都會(huì)選擇的,但是當(dāng)頁(yè)面刷新之后vuex數(shù)據(jù)會(huì)丟失,下面這篇文章主要給大家介紹了關(guān)于vuex頁(yè)面刷新數(shù)據(jù)丟失問(wèn)題的四種解決方式,需要的朋友可以參考下
    2022-02-02
  • VUE中computed 、created 、mounted的先后順序說(shuō)明

    VUE中computed 、created 、mounted的先后順序說(shuō)明

    這篇文章主要介紹了VUE中computed 、created 、mounted的先后順序說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • vue-video-player?播放m3u8視頻流的實(shí)現(xiàn)

    vue-video-player?播放m3u8視頻流的實(shí)現(xiàn)

    本文主要介紹了vue-video-player?播放m3u8視頻流的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • vue3父組件使用ref獲取子組件的屬性和方法

    vue3父組件使用ref獲取子組件的屬性和方法

    在vue3中父組件訪問(wèn)子組件中的屬性和方法是需要借助于ref,蘇哦一本文小編給大家介紹了vue3父組件如何使用ref獲取獲取子組件的屬性和方法,文中詳細(xì)的代碼講解,需要的朋友可以參考下
    2023-11-11
  • 淺談vue-router 路由傳參的方法

    淺談vue-router 路由傳參的方法

    這篇文章主要介紹了淺談vue-router 路由傳參的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12
  • vue+element搭建后臺(tái)小總結(jié) el-dropdown下拉功能

    vue+element搭建后臺(tái)小總結(jié) el-dropdown下拉功能

    這篇文章主要為大家詳細(xì)介紹了vue+element搭建后臺(tái)小總結(jié),el-dropdown下拉功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-09-09
  • Vue SPA單頁(yè)面的應(yīng)用和對(duì)比

    Vue SPA單頁(yè)面的應(yīng)用和對(duì)比

    單頁(yè)面是指整個(gè)應(yīng)用程序只有一個(gè)唯一完整的 HTML 頁(yè)面,而其它所謂的頁(yè)面,其實(shí)都是組件片段而已,切換頁(yè)面也只是切換一個(gè) HTML 中顯示不同的組件片段。在今后所有的開發(fā)項(xiàng)目都是單頁(yè)面應(yīng)用
    2022-08-08

最新評(píng)論

礼泉县| 黔南| 黄浦区| 泾川县| 沈丘县| 柏乡县| 会理县| 万山特区| 漳州市| 宜阳县| 静宁县| 青浦区| 无锡市| 邻水| 浮山县| 云浮市| 西吉县| 扬州市| 通江县| 周口市| 台州市| 鱼台县| 左贡县| 白山市| 宜章县| 德化县| 建湖县| 巫山县| 灵川县| 金川县| 哈尔滨市| 永平县| 石渠县| 运城市| 宣武区| 翁源县| 郑州市| 铜川市| 延庆县| 繁峙县| 濮阳县|