1. 程式人生 > >Vue中父子元件的傳值

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>