溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Vue中Computed和Watch的作用是什么

發(fā)布時(shí)間:2021-07-09 11:13:39 來源:億速云 閱讀:322 作者:Leah 欄目:web開發(fā)

本篇文章給大家分享的是有關(guān)Vue中Computed和Watch的作用是什么,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

 Vue中的computed

Vue中的computed又叫做計(jì)算屬性,Vue官網(wǎng)中給了下面這樣一個(gè)示例。

模板中有一個(gè)message數(shù)據(jù)需要展示:

<template>   <div id="app">     {{message}}   </div> </template> <script> export default {   name: 'App',   data() {     return {       message: 'Hello'     }   } } </script>

假如此時(shí)有一個(gè)需求:對(duì)message進(jìn)行反轉(zhuǎn)并展示到模板中。

那最簡單的實(shí)現(xiàn)方式就是直接在模板中做這樣的轉(zhuǎn)化:

<template>   <div id="app">     <p>{{message}}</p>     <p>{{message.split('').reverse().join('')}}</p>   </div> </template>

那這個(gè)時(shí)候,Vue官方告訴我們:過多的邏輯運(yùn)算會(huì)讓模板變得重且難以維護(hù),而且這種轉(zhuǎn)化無法復(fù)用,并指導(dǎo)我們使用計(jì)算屬性-computed來實(shí)現(xiàn)這個(gè)需求。

export default {   name: 'App',   computed: {     reverseMessage: function(){       return this.message.split('').reverse().join('');     }   },   data() {     return {       message: 'Hello'     }   } }

在以上代碼中我們定義了一個(gè)計(jì)算屬性:reverseMessage,其值為一個(gè)函數(shù)并返回我們需要的結(jié)果。

之后在模板中就可以像使用message一樣使用reverseMessage。

<template>   <div id="app">     <p>{{message}}</p>     <p>{{reverseMessage}}</p>   </div> </template>

那么此時(shí)有人肯定要說了,我用methods也能實(shí)現(xiàn)呀。確實(shí)使用methods也能實(shí)現(xiàn)此種需求,但是在這種情況下我們的計(jì)算屬性相較于methods是有很大優(yōu)勢(shì)的,這個(gè)優(yōu)勢(shì)就是計(jì)算屬性存在緩存。

如果我們使用methods實(shí)現(xiàn)前面的需求,當(dāng)message的反轉(zhuǎn)結(jié)果有多個(gè)地方在使用,對(duì)應(yīng)的methods函數(shù)會(huì)被調(diào)用多次,函數(shù)內(nèi)部的邏輯也需要執(zhí)行多次;而計(jì)算屬性因?yàn)榇嬖诰彺?,只要message數(shù)據(jù)未發(fā)生變化,則多次訪問計(jì)算屬性對(duì)應(yīng)的函數(shù)只會(huì)執(zhí)行一次。

<template>   <div id="app">     <p>{{message}}</p>     <p>第一次訪問reverseMessage:{{reverseMessage}}</p>     <p>第二次訪問reverseMessage:{{reverseMessage}}</p>     <p>第三次訪問reverseMessage:{{reverseMessage}}</p>     <p>第四次訪問reverseMessage:{{reverseMessage}}</p>   </div> </template>  <script> export default {   name: 'App',   computed: {     reverseMessage: function(value){       console.log(" I'm reverseMessage" )       return this.message.split('').reverse().join('');     }   },   data() {     return {       message: 'Hello'     }   } } </script>

運(yùn)行項(xiàng)目,查看結(jié)果,會(huì)發(fā)現(xiàn)計(jì)算屬性reverseMessage對(duì)應(yīng)的函數(shù)只執(zhí)行了一次。

Vue中Computed和Watch的作用是什么

3. Vue中的watchVue

中的watch又名為偵聽屬性,它主要用于偵聽數(shù)據(jù)的變化,在數(shù)據(jù)發(fā)生變化的時(shí)候執(zhí)行一些操作。

<template>   <div id="app">     <p>計(jì)數(shù)器:{{counter}}</p>     <el-button type="primary" @click="counter++">       Click     </el-button>   </div> </template>  <script> export default {   name: 'App',   data() {     return {       counter: 0     }   },   watch: {     /**      * @name: counter      * @description:       *   監(jiān)聽Vue data中的counter數(shù)據(jù)      *   當(dāng)counter發(fā)生變化時(shí)會(huì)執(zhí)行對(duì)應(yīng)的偵聽函數(shù)      * @param {*} newValue counter的新值      * @param {*} oldValue counter的舊值      * @return {*} None      */     counter: function(newValue, oldValue){       if(this.counter == 10){         this.counter = 0;       }     }   } } </script>

我們定義了一個(gè)偵聽屬性counter,該屬性偵聽的是Vue  data中定義counter數(shù)據(jù),整個(gè)的邏輯就是點(diǎn)擊按鈕counter加1,當(dāng)counter等于10的時(shí)候,將counter置為0。

上面的代碼運(yùn)行后的結(jié)果如下:

Vue中Computed和Watch的作用是什么

Vue官網(wǎng)很明確的建議我們這樣使用watch偵聽屬性:當(dāng)需要在數(shù)據(jù)變化時(shí)執(zhí)行異步或開銷較大的操作時(shí),這個(gè)方式是最有用的。

4.  computed和watch之間的抉擇

看完以上兩部分內(nèi)容,關(guān)于Vue中computed和watch的基本用法算是掌握了。但實(shí)際上不止這些,所以接下來我們?cè)趤磉M(jìn)階學(xué)習(xí)一波。

這里我們還原Vue官網(wǎng)中的一個(gè)示例,示例實(shí)現(xiàn)的功能大致如下:

Vue中Computed和Watch的作用是什么

該功能可以簡單的描述為:在firstName和lastName數(shù)據(jù)發(fā)生變化時(shí),對(duì)fullName進(jìn)行更新,其中fullName的值為firstName和lastName的拼接。

首先我們使用watch來實(shí)現(xiàn)該功能:watch偵聽firstName和lastName,當(dāng)這兩個(gè)數(shù)據(jù)發(fā)生變化時(shí)更新fullName的值。

<template>   <div id="app">     <p>firstName: <el-input v-model="firstName" placeholder="請(qǐng)輸入firstName"></el-input></p>     <p>lastName: <el-input v-model="lastName" placeholder="請(qǐng)輸入lastName"></el-input></p>     <p>fullName: {{fullName}}</p>   </div> </template>  <script> export default {   name: 'App',   data() {     return {       firstName: '',       lastName: '',       fullName: '(空)'     }   },   // 使用watch實(shí)現(xiàn)   watch: {     firstName: function(newValue) {       this.fullName = newValue + ' ' + this.lastName;     },     lastName: function(newValue){       this.fullName = this.firstName + ' ' + newValue;     }   } } </script>

接著我們?cè)谑褂胏omputed來實(shí)現(xiàn):定義計(jì)算屬性fullName,將firstName和lastName的值進(jìn)行拼接并返回。

<template>   <div id="app">     <p>firstName: <el-input v-model="firstName" placeholder="請(qǐng)輸入firstName"></el-input></p>     <p>lastName: <el-input v-model="lastName" placeholder="請(qǐng)輸入lastName"></el-input></p>     <p>fullName: {{fullName}}</p>   </div> </template>  <script> export default {   name: 'App',   data() {     return {       firstName: '',       lastName: ''     }   }   computed: {     fullName: function() {       return this.firstName + ' ' + this.lastName;     }   }  } </script>

我們發(fā)現(xiàn)computed和watch都可以實(shí)現(xiàn)這個(gè)功能,但是我們?cè)趯?duì)比一下這兩種不同的實(shí)現(xiàn)方式:

// 使用computed實(shí)現(xiàn) computed: {   fullName: function() {     return this.firstName + ' ' + this.lastName;   } },  // 使用watch實(shí)現(xiàn) watch: {   firstName: function(newValue) {     this.fullName = newValue + ' ' + this.lastName;   },   lastName: function(newValue){     this.fullName = this.firstName + ' ' + newValue;   } }

對(duì)比之下很明顯的會(huì)發(fā)現(xiàn)發(fā)現(xiàn)computed的實(shí)現(xiàn)方式更簡潔高級(jí)。

所以在日常項(xiàng)目開發(fā)中,對(duì)于computed和watch的使用要慎重選擇:

Vue中Computed和Watch的作用是什么

這兩者選擇和使用沒有對(duì)錯(cuò)之分,只是希望能更好的使用,而不是濫用。

5. 計(jì)算屬性進(jìn)階

接下來我們?cè)趯?duì)計(jì)算屬性的內(nèi)容進(jìn)行進(jìn)階學(xué)習(xí)。

>>> 5.1 計(jì)算屬性不能和Vue Data屬性同名

在聲明計(jì)算屬性的時(shí)候,計(jì)算屬性是不能和Vue Data中定義的屬性同名,否則會(huì)出現(xiàn)錯(cuò)誤:The computed property "xxxxx" is  already defined in data。

如果有閱讀過Vue源碼的同學(xué)對(duì)這個(gè)原因應(yīng)該會(huì)比較清楚,Vue在初始化的時(shí)候會(huì)按照:initProps-> initMethods ->  initData -> initComputed ->  initWatch這樣的順序?qū)?shù)據(jù)進(jìn)行初始化,并且會(huì)通過Object.definedProperty將數(shù)據(jù)定義到vm實(shí)例上,在這個(gè)過程中同名的屬性會(huì)被后面的同名屬性覆蓋。

通過打印組件實(shí)例對(duì)象,可以很清楚的看到props、methods、data、computed會(huì)被定義到vm實(shí)例上。

>>> 5.2 計(jì)算屬性的set函數(shù)

在前面代碼示例中,我們的computed是這么實(shí)現(xiàn)的:

computed: {   reverseMessage: function(){     return this.message.split('').reverse().join('');   } },

這種寫法實(shí)際上是給reverseMessage提供了一個(gè)get方法,所以上面的寫法等同于:

computed: {   reverseMessage: {     // 計(jì)算屬性的get方法     get: function(){       return this.message.split('').reverse().join('');     }   } },

除此之外,我們也可以給計(jì)算屬性提供一個(gè)set方法:

computed: {   reverseMessage: {     // 計(jì)算屬性的get方法     get: function(){       return this.message.split('').reverse().join('');     },     set: function(newValue){        // set方法的邏輯     }   } },

只有我們主動(dòng)修改了計(jì)算屬性的值,set方法才會(huì)被觸發(fā)。

關(guān)于計(jì)算屬性的set方法在實(shí)際的項(xiàng)目開發(fā)中暫時(shí)還沒有遇到,不過經(jīng)過一番思考,做出來下面這樣一個(gè)示例:

Vue中Computed和Watch的作用是什么

這個(gè)示例是分鐘和小時(shí)之間的一個(gè)轉(zhuǎn)化,利用計(jì)算屬性的set方法就能很好實(shí)現(xiàn):

<template>   <div id="app">     <p>分鐘<el-input v-model="minute" placeholder="請(qǐng)輸入內(nèi)容"></el-input></p>     <p>小時(shí)<el-input v-model="hours" placeholder="請(qǐng)輸入內(nèi)容"></el-input></p>   </div> </template>  <script> export default {   name: 'App',   data() {     return {       minute: 60,     }   },   computed: {     hours:{       get: function() {         return this.minute / 60;       },       set: function(newValue) {         this.minute = newValue * 60;       }     }   }  } </script>

>>> 5.3 計(jì)算屬性的緩存

前面我們總結(jié)過計(jì)算屬性存在緩存,并演示相關(guān)的示例。那計(jì)算屬性的緩存是如何實(shí)現(xiàn)的呢?

關(guān)于計(jì)算屬性的緩存這個(gè)知識(shí)點(diǎn)需要我們?nèi)ラ喿xVue的源碼實(shí)現(xiàn),所以我們一起來看看源碼吧。

相信大家看到源碼這個(gè)詞就會(huì)有點(diǎn)膽戰(zhàn)心驚,不過不用過分擔(dān)心,文章寫到這里的時(shí)候考慮到本篇文章的內(nèi)容和側(cè)重點(diǎn),所以不會(huì)詳細(xì)去解讀計(jì)算屬性的源碼,著重學(xué)習(xí)計(jì)算屬性的緩存實(shí)現(xiàn),并且點(diǎn)到為止。

那如果你沒有仔細(xì)解讀過Vue的響應(yīng)式原理,那建議忽略這一節(jié)的內(nèi)容,等對(duì)源碼中的響應(yīng)式有一定了解之后在來看這一節(jié)的內(nèi)容會(huì)更容易理解。(我自己之前也寫過的一篇相關(guān)文章:1W字長文+多圖,帶你了解vue2.x的雙向數(shù)據(jù)綁定源碼實(shí)現(xiàn),點(diǎn)擊文末閱讀原文即可查看)

關(guān)于計(jì)算屬性的入口源代碼如下:

/* * Vue版本:v2.6.12 * 代碼位置:/vue/src/core/instance/state.js */ export function initState (vm: Component) {   // ......省略......   const opts = vm.$options   // ......省略......   if (opts.computed) initComputed(vm, opts.computed)   // ......省略                                                                       ...... }

接著我們來看看initComputed:

/* * Vue版本:v2.6.12 * 代碼位置:/vue/src/core/instance/state.js * @params: vm        vue實(shí)例對(duì)象 * @params: computed  所有的計(jì)算屬性 */ function initComputed (vm: Component, computed: Object) {     /*    * Object.create(null):創(chuàng)建一個(gè)空對(duì)象   * 定義的const watchers是用于保存所有計(jì)算屬性的Watcher實(shí)例   */   const watchers = vm._computedWatchers = Object.create(null)     // 遍歷計(jì)算屬性   for (const key in computed) {     const userDef = computed[key]     /*     * 獲取計(jì)算屬性的get方法      * 計(jì)算屬性可以是function,默認(rèn)提供的是get方法     * 也可以是對(duì)象,分別聲明get、set方法     */     const getter = typeof userDef === 'function' ? userDef : userDef.get         /*      * 給計(jì)算屬性創(chuàng)建watcher     * @params: vm       vue實(shí)例對(duì)象      * @params: getter   計(jì)算屬性的get方法     * @params: noop                noop是定義在 /vue/src/shared/util.js中的一個(gè)函數(shù)           export function noop (a?: any, b?: any, c?: any) {}     * @params: computedWatcherOptions     *     computedWatcherOptions是一個(gè)對(duì)象,定義在本文件的167行     *     const computedWatcherOptions = { lazy: true }     */     watchers[key] = new Watcher(       vm,       getter || noop,       noop,       computedWatcherOptions     )     // 函數(shù)調(diào)用     defineComputed(vm, key, userDef)   } }

在initComputed這個(gè)函數(shù)中,主要是遍歷計(jì)算屬性,然后在遍歷的過程中做了下面兩件事:

  • 第一件:為計(jì)算屬性創(chuàng)建watcher,即new Watcher

  • 第二件:調(diào)用defineComputed方法

那首先我們先來看看new Watcher都做了什么。

為了方便大家看清楚new Watcher的作用,我將Watcher的源碼進(jìn)行了簡化,保留了一些比較重要的代碼。

同時(shí)代碼中重要的部分都添加了注釋,有些注釋描述的可能有點(diǎn)重復(fù)或者啰嗦,但主要是想以這種重復(fù)的方式讓大家可以反復(fù)琢磨并理解源碼中的內(nèi)容,方便后續(xù)的理解  ~

/* * Vue版本:v2.6.12 * 代碼位置: /vue/src/core/observer/watcher.js * 為了看清楚Watcher的作用 * 將源碼進(jìn)行簡化,所以下面是一個(gè)簡化版的Watcher類 * 同時(shí)部分代碼順序有所調(diào)整 */ export default class Watcher {   constructor (     vm: Component,     expOrFn: string | Function,     cb: Function,     options?: ?Object,   ) {     // vm為組件實(shí)例     this.vm = vm       // expOrFn在new Watcher時(shí)傳遞的參數(shù)為計(jì)算屬性的get方法     // 將計(jì)算屬性的get方法賦值給watcher的getter屬性     this.getter = expOrFn     // cb為noop:export function noop (a?: any, b?: any, c?: any) {}     this.cb = cb       // option在new Watcher傳遞的參數(shù)值為{lazy: true}      // !!操作符即將options.lazy強(qiáng)轉(zhuǎn)為boolean類型     // 賦值之后this.lazy的值為true     this.lazy = !!options.lazy      // 賦值之后this.dirty的值true     this.dirty = this.lazy           /*     * 在new Watcher的時(shí)候因?yàn)閠his.lazy的值為true     * 所以this.value的值還是undefined     */     this.value = this.lazy ? undefined : this.get()   }   get () {      const vm = this.vm     /*     * 在構(gòu)造函數(shù)中,計(jì)算屬性的get方法賦值給了watcher的getter屬性     * 所以該行代碼即調(diào)用計(jì)算屬性的get方法,獲取計(jì)算屬性的值     */     value = this.getter.call(vm, vm)     return value   }   evaluate () {     /*     * 調(diào)用watcher的get方法     * watcher的get方法邏輯為:調(diào)用計(jì)算屬性的get方法獲取計(jì)算屬性的值并返回     * 所以evaluate函數(shù)也就是獲取計(jì)算屬性的值,并賦值給watcher.value     * 并且將watcher.dirty置為false,這個(gè)dirty是實(shí)現(xiàn)緩存的關(guān)鍵     */      this.value = this.get()     this.dirty = false   } }

看了這個(gè)簡化版的Watcher以后,想必我們已經(jīng)很清楚的知道了Watcher類的實(shí)現(xiàn)。

那接下來就是關(guān)于緩存的重點(diǎn)了,也就是遍歷計(jì)算屬性做的第二件事:調(diào)用defineComputed函數(shù):

/* * Vue版本:v2.6.12 * 代碼位置:/vue/src/core/instance/state.js * @params: target  vue實(shí)例對(duì)象 * @params: key     計(jì)算屬性名 * @params: userDef 計(jì)算屬性定義的function或者object */ export function defineComputed (   target: any,   key: string,   userDef: Object | Function ) {      // ......暫時(shí)省略有關(guān)sharedPropertyDefinition的代碼邏輯......      /*   * sharedPropertyDefinition本身是一個(gè)對(duì)象,定義在本文件31行:   * const sharedPropertyDefinition = {   *   enumerable: true,   *   configurable: true,   *   get: noop,   *   set: noop   * }   * 最后使用Object.defineProperty傳入對(duì)應(yīng)的參數(shù)使得計(jì)算屬性變得可觀測   */   Object.defineProperty(target, key, sharedPropertyDefinition) }

defineComputed方法最核心也只有一行代碼,也就是使用Object.defineProperty將計(jì)算屬性變得可觀測。

那么接下來我們的關(guān)注點(diǎn)就是調(diào)用Object.defineProperty函數(shù)時(shí)傳遞的第三個(gè)參數(shù):sharedPropertyDefinition。

sharedPropertyDefinition是定義在當(dāng)前文件中的一個(gè)對(duì)象,默認(rèn)值如下:

const sharedPropertyDefinition = {   enumerable: true,   configurable: true,   get: noop,   set: noop }

前面貼出來的defineComputed源碼中,我注釋說明省略了一段有關(guān)sharedPropertyDefinition的代碼邏輯,那省略的這段源代碼就不展示了,它的主要作用就是在對(duì)sharedPropertyDefinition.get和sharedPropertyDefinition.set進(jìn)行重寫,重寫之后sharedPropertyDefinition的值為:

const sharedPropertyDefinition = {   enumerable: true,   configurable: true,   get: function(){       // 獲取計(jì)算屬性對(duì)應(yīng)的watcher實(shí)例       const watcher = this._computedWatchers && this._computedWatchers[key]       if (watcher) {         if (watcher.dirty) {           watcher.evaluate()         }         if (Dep.target) {           watcher.depend()         }         return watcher.value       }     }   },   // set對(duì)應(yīng)的值這里寫的是noop   // 但是我們要知道set真正的值是我們?yōu)橛?jì)算屬性提供的set函數(shù)   // 千萬不要理解錯(cuò)了哦    set: noop,   }

那sharedPropertyDefinition.get函數(shù)的邏輯已經(jīng)非常的清晰了,同時(shí)它的邏輯就是計(jì)算屬性緩存實(shí)現(xiàn)的關(guān)鍵邏輯:在sharedPropertyDefinition.get函數(shù)中,先獲取到計(jì)算屬性對(duì)應(yīng)的watcher實(shí)例;然后判斷watcher.dirty的值,如果該值為false,則直接返回watcher.value;否則調(diào)用watcher.evaluate()重新獲取計(jì)算屬性的值。

關(guān)于計(jì)算屬性緩存的源碼分析就到這里,相信大家對(duì)計(jì)算屬性的緩存實(shí)現(xiàn)已經(jīng)有了一定的認(rèn)識(shí)。不過僅僅是了解這些還不夠,我們應(yīng)該去通讀計(jì)算屬性的完整源碼實(shí)現(xiàn),才能對(duì)計(jì)算屬性有一個(gè)更通透的認(rèn)識(shí)。

6. 偵聽屬性進(jìn)階

>>> 6.1 handler

前面我們是這樣實(shí)現(xiàn)偵聽屬性的:

watch: {   counter: function(newValue, oldValue){     if(this.counter == 10){       this.counter = 0;     }   } }

那上面的這種寫法等同于給counter提供一個(gè)handler函數(shù):

watch: {   counter: {     handler: function(newValue, oldValue){       if(this.counter == 10){         this.counter = 0;       }     }   } }

>>> 6.2 immediate

正常情況下,偵聽屬性提供的函數(shù)是不會(huì)立即執(zhí)行的,只有在對(duì)應(yīng)的vue data發(fā)生變化時(shí),偵聽屬性對(duì)應(yīng)的函數(shù)才會(huì)執(zhí)行。

那如果我們需要偵聽屬性對(duì)應(yīng)的函數(shù)立即執(zhí)行一次,就可以給偵聽屬性提供一個(gè)immediate選項(xiàng),并設(shè)置其值為true。

watch: {   counter: {     handler: function(newValue, oldValue){       if(this.counter == 10){         this.counter = 0;       }     },     immediate: true   } }

>>> 6.3 deep

如果我們對(duì)一個(gè)對(duì)象類型的vue data進(jìn)行偵聽,當(dāng)這個(gè)對(duì)象內(nèi)的屬性發(fā)生變化時(shí),默認(rèn)是不會(huì)觸發(fā)偵聽函數(shù)的。

<template>   <div id="app">     <p><el-input v-model="person.name" placeholder="請(qǐng)輸入姓名"></el-input></p>     <p><el-input v-model="person.age" placeholder="請(qǐng)輸入年齡"></el-input></p>   </div> </template> <script> export default {   name: 'App',   data() {     return {       person: {         name: 'jack',         age: 20       }     }   },   watch: {     person: function(newValue){       console.log(newValue.name + ' ' + newValue.age);     }   } } </script>

監(jiān)聽對(duì)象類型的數(shù)據(jù),偵聽函數(shù)沒有觸發(fā):

Vue中Computed和Watch的作用是什么

通過給偵聽屬性提供deep: true就可以偵聽到對(duì)象內(nèi)部屬性的變化:

watch: {   person: {     handler: function(newValue){       console.log(newValue.name + ' ' + newValue.age);     },     deep: true   } }
Vue中Computed和Watch的作用是什么

不過仔細(xì)觀察上面的示例會(huì)發(fā)現(xiàn)這種方式去監(jiān)聽Object類型的數(shù)據(jù),Object數(shù)據(jù)內(nèi)部任一屬性發(fā)生變化都會(huì)觸發(fā)偵聽函數(shù),那如果我們想單獨(dú)偵聽對(duì)象中的某個(gè)屬性,可以使用下面這樣的方式:

watch: {   'person.name': function(newValue, oldValue){       // 邏輯    } }

以上就是Vue中Computed和Watch的作用是什么,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見到或用到的。希望你能通過這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI