首頁 web前端 js教程 詳細解讀vue.js中props如何傳遞參數

詳細解讀vue.js中props如何傳遞參數

Jun 21, 2018 pm 02:33 PM
props vue.js 傳遞參數

給大家詳細分析了vue.js之props傳遞參數的相關知識以及問題解決方法,需要的朋友參考下。

這篇文章透過demo實例給大家詳細分析了props傳遞參數的用法以及遇到問題後的解決辦法,以下是全部內容。

前段時間用vue做一個後台管理系統,其中每一頁都需要一個表格來展示資訊。自然就想到了將表格提取出來做成公共元件,將不同頁面的資料傳入進行渲染,達到復用的目的。

demo位址

1. 問題發現

在父元件中,需要傳遞給表格元件的資料有表格的內容資料tableData,表格的頁面資料page。

<p>
 <my-table :table-data="tableData" :page-info="pageInfo" id="myTable"></my-table>
</p>
登入後複製

其中tableData是個Array對象,是所有需要在表格中展示的資料對象所組成的陣列。而pageInfo是個Object對象,包含了表格頁面資訊。在父元件對兩個資料對如下初始化,形式如下

tableData:[],
pageInfo: {
 current: 1, // 当前是第几页
 total: 100, // 数据对象的总数
 size: 20 // 每页显示的数量
}
登入後複製

按照官方文件上的說明,prop是單向綁定的,不應該在子元件內部改變prop。之所以有想修改prop中資料的衝動,主要是prop作為初始值傳入後,子元件想把它當作局部資料來用。對於這種情況,官方的說法是定義一個局部變量,並用prop 的值初始化它:

props: [&#39;tableData&#39;, &#39;pageInfo&#39;],
data() {
 return {
  tData: this.tableData,
  page: this.pageInfo
 }
}
登入後複製
登入後複製

然後根據官方文件的說法,當每次父組件更新時,子組件的所有prop都會更新為最新值。而tableData和pageInfo的資訊是非同步透過api從server端取得的:

{
 error: 0,
 msg: "调用成功.",
 data: {
  restrictioninfo: [...],
  total: 42
 }
}
登入後複製

因此當取得到資料時父元件需要改變傳入子元件中的值:

me.tableData = Json.data.restrictioninfo;
me.pageInfo.total = Json.data.total;
登入後複製

依理說這時候子元件中的值應該更新成server回傳的值,但是子元件頁面的總數更新了,但table資料依然是初始化時的空數組。 (黑人問號???)


2.賦值與綁定

#首先需要定位資料是在哪個地方出了問題,於是我做了一個demo來定位問題。

首先看父元件與子元件中各元素的初始值:

#然後只改變父元件中陣列的參考時可以看到子元件的props數組隨之改變,而子元件中綁定的數組確並沒有隨之改變

因此,可以發現,問題是出在了這一步

props: [&#39;tableData&#39;, &#39;pageInfo&#39;],
data() {
 return {
  tData: this.tableData,
  page: this.pageInfo
 }
}
登入後複製
登入後複製

而要弄清楚問題的根源,就得弄清楚vue文件中深入響應式原理。

"在Vue實例的data選項中,Vue將遍歷此物件所有的屬性,並使用Object.defineProperty將這些屬性全部轉為getter/setter","每個元件實例都有對應的watcher 實例對象,它會在元件渲染的過程中把屬性記錄為依賴,之後當依賴項的setter 被呼叫時,會通知watcher 重新計算,從而致使它關聯的元件得以更新。」文件中說了這麼一大堆,簡單理解就是Vue將data選項中的vm.$data.a與DOM中的vm.a進行了雙向綁定,即其中一個變化,另一個也會跟著變化。在Vue原始碼中是由defineReactive$$1函數實現的:

但在子其中主要利用了Object.defineProperty的get和set方法實現了雙向綁定。而在子元件中,pros資料與子元件的$data則是透過以下方式連結在一起的:

tData: this.tableData
登入後複製

查詢Vue原始碼可知this.tableData與tData之間僅是賦值,即"="關係

而上述的initData函數是在元件建置時候執行的,因此只會在create時執行一次。這也是為什麼官方文件中"作為初始值傳入"這一說法,因為他本來就只會執行一次。當元件建置完成後,this.tableData與tData就沒有半毛錢關係了,其中一個的變化不會造成另一個變化。當然,這種說法並不準確,因為在上文中,我們動態改變父組件傳入的total,子組件也"隨之"改變,感覺就像是綁定在一起了啊,這又是怎麼回事呢?

3.引用型別帶來的假象

#當然,我們還是要從官方文件出發來解決這個問題。文檔中有這樣一個提示:

这里就需要理解引用类型的概念,引用数据类型值指保存在堆内存中的对象。也就是,变量中保存的实际上的只是一个指针,这个指针指向内存中的另一个位置,该位置保存着对象。访问方式是按引用访问。例如一个js对象a,他在内存中的存储形式如下图所示:

var a = new Object();
登入後複製

当操作时,需要先从栈中读取内存地址,然后再延指针找到保存在堆内存中的值再操作。

a.name = &#39;xz&#39;;
登入後複製


引用类型变量赋值,本质上赋值的是存储在栈中的指针,将指针复制到栈中未新变量分配的空间中,而这个指针副本和原指针指向存储在堆中的同一个对象;赋值操作结束后,两个变量实际上将引用同一个对象。因此,在使用时,改变其中的一个变量的值,将影响另一个变量。

var b = a;
登入後複製


在了解了引用类型之后,我们在来看看上文提到的动态改变传入子组件前后内存中的情况:

me.tableData = Json.data.restrictioninfo;
me.pageInfo.total = Json.data.total;
========================================
props: [&#39;tableData&#39;, &#39;pageInfo&#39;],
data() {
 return {
  tData: this.tableData,
  page: this.pageInfo
 }
}
登入後複製

首先对tableData的改变是改变了其引用的指针,而对pageInfo则改变了其中一个属性的值,因此动态改变前:

动态改变后:

这样就解释了为什么子组件页面的总数更新了,但table数据依然是初始化时的空数组。因为引用类型的存在,我们动态改变父组件传入的total,子组件也"随之"改变了。

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

在jQuery中如何实现点击DIV触发点击CheckBox

使用JS如何实现点击复选框修改显示状态

在Vue中标准的处理方法(详细教程)

以上是詳細解讀vue.js中props如何傳遞參數的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

深入探討vite是怎麼解析.env檔的 深入探討vite是怎麼解析.env檔的 Jan 24, 2023 am 05:30 AM

使用vue框架開發前端專案時,我們部署的時候都會部署多套環境,往往開發、測試以及線上環境呼叫的介面網域都是不一樣的。如何能做到區分呢?那就是使用環境變數和模式。

圖文詳解如何在Vue專案中整合Ace程式碼編輯器 圖文詳解如何在Vue專案中整合Ace程式碼編輯器 Apr 24, 2023 am 10:52 AM

Ace 是一個用 JavaScript 寫的可嵌入程式碼編輯器。它與 Sublime、Vim 和 TextMate 等原生編輯器的功能和效能相符。它可以很容易地嵌入到任何網頁和 JavaScript 應用程式中。 Ace 被維護為Cloud9 IDE的主要編輯器 ,並且是 Mozilla Skywriter (Bespin) 專案的繼承者。

探討如何在Vue3中撰寫單元測試 探討如何在Vue3中撰寫單元測試 Apr 25, 2023 pm 07:41 PM

在當今前端開發中,Vue.js 已經成為了一個非常流行的框架。隨著 Vue.js 的不斷發展,單元測試變得越來越重要。今天,我們將探討如何在 Vue.js 3 中編寫單元測試,並提供一些最佳實踐和常見的問題及解決方案。

深入聊聊vue3中的reactive() 深入聊聊vue3中的reactive() Jan 06, 2023 pm 09:21 PM

前言:在vue3的開發中,reactive是提供實現響應式資料的方法。日常開發這個是使用頻率很高的api。這篇文章筆者就來探索其內部運作機制。

Vue中JSX語法和模板語法的簡單比較(優劣勢分析) Vue中JSX語法和模板語法的簡單比較(優劣勢分析) Mar 23, 2023 pm 07:53 PM

在Vue.js中,開發人員可以使用兩種不同的語法來建立使用者介面:JSX語法和範本語法。這兩種文法各有優劣,以下就來探討它們的差異和優劣勢。

淺析vue怎麼實現檔案切片上傳 淺析vue怎麼實現檔案切片上傳 Mar 24, 2023 pm 07:40 PM

在實際開發專案過程中有時候需要上傳比較大的文件,然後呢,上傳的時候相對來說就會慢一些,so,後台可能會要求前端進行文件切片上傳,很簡單哈,就是把比如說1個G的檔案流切割成若干個小的檔案流,然後分別請求介面傳遞這個小的檔案流。

解析Vue2實作composition API的原理 解析Vue2實作composition API的原理 Jan 13, 2023 am 08:30 AM

自從Vue3 發布之後,composition API 這個詞走入寫Vue 同學的視野之中,相信大家也一直聽到composition API 比之前的options API 有多好多強,如今由於@vue/composition-api 插件的發布,Vue2的同學也可以上車咯,接下來我們主要以響應式的ref 和reactive 來深入分析一下,這個插件是怎麼實現此

聊聊vue3怎麼使用高德地圖api 聊聊vue3怎麼使用高德地圖api Mar 09, 2023 pm 07:22 PM

在我們使用高德地圖的時候,官方給我們推薦了很多案例,demo,但是這些案例都是使用原生方法接入,並沒有提供vue或者react 的demo,vue2的接入網上也很多人都有寫過,以下這篇文章就來看看vue3怎麼使用常用的高德地圖api,希望對大家有幫助!

See all articles