Vue中父子元件的傳值
學習vue的過程中,我們總會遇到元件中資料傳遞的問題,比如將父元件的資料傳遞給子元件,或者將子元件的資料傳遞給父元件。作為一個初學者,看到這些過程難免有些頭疼,今天就總結了下具體的過程。
目標:當點選button按鈕時,輸入到input中的文字內容會在頁面中顯示。
邏輯:由於input中的資料在父元件中的list陣列內部儲存,為了在子元件todoItem中渲染出資料,就要將資料從父元件中傳遞給子元件,此時便涉及到資料傳遞問題。
為了實現在ul中渲染每一個li值的效果,我們需要在TodoItem元件中使用列表渲染功能,但是此時並沒有達到預期的效果,原因其實很簡單,由於list中的item屬於父元件的資料,子元件預設無法訪問到父元件的屬性,此時就需要進行父子元件中的傳值操作。
首先,子元件引用父元件的資料時,需要通過繫結屬性的方法,把需要傳遞給子元件的資料傳遞給自定義屬性,自定義屬性再將資料傳遞到子元件內部,供子元件使用。也就是說父元件通過v-bind:'自定義屬性'='資料值'
其次,子元件在props中建立屬性以便接收父元件傳遞過來的值,父元件在components屬性中註冊子元件
這樣便實現了簡單的父元件向 子元件的資料傳遞功能。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="vue.js"></script> </head> <body> <div id="app"> <input type="text" v-model="inputValue"> <button v-on:click="handleClick">提交</button> <!-- 在按鈕上繫結事件(自定義函式),在vue例項中的methods定義方法 --> <ul> <todo-item v-for="item in list" v-bind:content="item"></todo-item> <!-- 將item作為資料傳遞給自定義屬性content--> </ul> </div> <script> //區域性元件的實現方式 var todoItem={ props:['content'],//傳遞的屬性需要重新定義 template:'<li>{{content}}</li>'//模板中用content渲染item值 } var app=new Vue({ el:'#app', components:{ todoItem:todoItem//註冊元件 }, data:{ list:[], inputValue:'' }, methods:{ handleClick:function(){ this.list.push(this.inputValue);//將輸入框裡的值新增到list中 this.inputValue=''; } } }) </script> </body> </html>
使用繫結屬性和props屬性便能實現簡單的父傳子功能,那麼子元件如何向父元件進行數值的傳遞呢?
目標:點選當前的li標籤,實現刪除功能。
邏輯:若想實現以上的功能,子元件向父元件傳遞事件的索引值傳遞給父元件,父元件改變資料。
首先,給子元件繫結一個自定義事件併為事件自定義一個方法,在這裡我使用了click事件。
var todoItem={
template:'<li @click="handleItemClick">{{content}}</li>',
}
其次,子元件通過$emit方式主動觸發事件,第一個引數即為觸發的事件名,第二個引數需要作為實參傳遞給父元件的自定義方法。
var todoItem={
methods:{
handleItemClick:function(){
this.$emit('delete',this.index)//子元件主動觸發delete事件,並傳遞引數
}
}
}
繼續,父元件監聽子元件觸發的事件,並呼叫自定義方法。
<todo-item v-for="(item,index) in list" :content="item" @delete="handleItemDelete" :index="index">
</todo-item>
最後,父元件中新增響應子元件事件的方法。
var app=new Vue({
el:'#app',
methods:{
handleItemDelete:function(index){//父元件定義方法,用於接受子元件傳遞的資料
this.list.splice(index,1);}
}
})
總的來說,父元件向子元件傳值時需要借用props屬性,而子元件向父元件傳值時則需要借用自定義事件,二者都需要第三方來協助傳值。
實現以上效果的全部程式碼如下。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="inputValue">
<button v-on:click="handleClick">提交</button>
<ul>
<todo-item v-for="(item,index) in list" :content="item" @delete="handleItemDelete" :index="index"></todo-item>
<!-- 定義delete事件 -->
</ul>
</div>
<script>
//區域性元件的實現方式
var todoItem={
props:['content','index'],//傳遞的屬性需要重新定義
template:'<li @click="handleItemClick">{{content}}</li>',
//子元件向父元件傳遞方法,使用v-on的事件機制繫結自定義事件,子元件便可通過該種方式呼叫這個方法。
methods:{
handleItemClick:function(){
this.$emit('delete',this.index)//子元件主動觸發delete事件,並傳遞引數
}
}
}
var app=new Vue({
el:'#app',
components:{
todoItem:todoItem//註冊元件
},
data:{
list:[],
inputValue:''
},
methods:{
handleClick:function(){
this.list.push(this.inputValue);//將輸入框裡的值新增到list中
this.inputValue='';
},
handleItemDelete:function(index){//父元件定義方法,用於接受子元件傳遞的資料
this.list.splice(index,1);
}
}
})
</script>
</body>
</html>