【Vue】vue元件的建立與傳值

component、props、$emit()

【Vue】vue元件的建立與傳值

component、props、$emit()


元件(Component)

  • 元件資料是獨立運作,也可以重複使用。

  • 元件裡面可以再包元件。

  • 建立元件有兩種方式:

    • 全域註冊 : 使用Vue.component()建立,其他app也可以使用。

    • 局部註冊 : 在app裡使用components建立,只有app自己可以使用。


全域註冊元件

  1. 使用Vue.component()建立,第一個參數自訂[標籤名稱]。

  1. 在HTML建立一個類型為 text/x-template 的<script>,並賦予一個[id]名稱。

  1. 並在底下建立元件結構。

  1. Vue.component() ,使用[template]對應<script>的[id]。

  1. 在HTML上使用自訂[標籤名稱]。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// <-----html----->
#app
  list-com  //5.

script(type="text/x-template" id="list-com")  //2.
  ul  //3.
    li 蘋果
    li 香蕉
    li 鳳梨

// <-----js----->
Vue.component("list-com",{   //1.
  template: "#list-com"  //4.
});

var app = new Vue({
  el: "#app"
});


局部註冊元件

  1. 在app裡使用[components]建立元件。

  1. 先自訂[標籤名稱]。

  1. 使用物件方式,帶入[template],並建立元件結構。

  1. 在HTML上使用自訂[標籤名稱]。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// <-----html----->
#app
  list-com

// <-----js----->
var app = new Vue({
  el: "#app",
  components:{
    "list-com":{
      template:
      `
      <ul>
        <li>蘋果</li>
        <li>香蕉</li>
        <li>鳳梨</li>
      </ul>
      `
    }
  }
});


元件的data資料

元件的data需使用function(){return{...}}

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// <-----html----->
#app
  num-btn

script(type="text/x-template" id="num-btn") 
  button(@click="num += 1") {{num}} 

// <-----js----->
Vue.component("num-btn",{  
  template: "#num-btn",
  data: function(){
    return {
      num: 50
    }
  }
});

var app = new Vue({
  el: "#app"
});

元件的陣列資料

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// <-----html----->
#app
  fruit-list

script(type="text/x-template" id="fruit-list")
  ul
    li(v-for="fruit in fruits") {{fruit.name}}

// <-----js----->
Vue.component("fruit-list",{  
  template: "#fruit-list",
  data: function(){
    return{
      fruits:[
        {name:"蘋果",amount:100},
        {name:"香蕉",amount:300},
        {name:"鳳梨",amount:500}
      ]
    }
  }
});

var app = new Vue({
  el: "#app"
});

元件的ajax資料

因ajax載入與顯示有時間差,要在該元件上使用v-if來確保資料載入

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// <-----html----->
#app
  .row
    .col-4
      user-card
  
script(type="text/x-template" id="user-card")
  .card(v-if="user.cell")
    img.card-img-top(:src="user.picture.large")
    .card-body
      .card-title {{user.name.title}}{{user.name.first}}{{user.name.last}}
      .card-text {{user.email}}

// <-----js----->
Vue.component("user-card",{
  template: "#user-card",
  data: function(){
    return {
      user: {}
    }
  },
  created: function(){
    var vm = this;
    $.ajax({
      url: "https://randomuser.me/api/"
    }).done(function(data){
      vm.user = data.results[0];
    });
  }
})

var app = new Vue({
  el: "#app"
});

使用keep-alive 標籤可以讓元件被消失後再顯示時,不重新載入ajax


使用props將資料傳入元件

  1. 使用props以陣列方式傳入屬性名稱。

  1. 在標籤上動態綁定屬性,並賦予值。此時更動傳入的屬性會出現單向數據流的錯誤

  1. 使用一個新的data來接收props傳入的資料。

  1. 在元件建構上套用新的data資料。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// <-----html----->
#app
  num-btn(:num="num")  //2.

script(type="text/x-template" id="num-btn") 
  button(@click="newnum += 1") {{newnum}}  //4.

// <-----js----->
Vue.component("num-btn",{  
  template: "#num-btn",
  props: ["num"],  //1.
  data: function(){
    return{
      newnum: this.num  //3.
    }
  }
});

var app = new Vue({
  el: "#app",
  data:{
    num: 50
  }
});

使用props將陣列傳入元件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// <-----html----->
#app
  fruit-list(:fruits="fruits")

script(type="text/x-template" id="fruit-list")
  ul
    li(v-for="fruit in newfruits") {{fruit.name}}

// <-----js----->
Vue.component("fruit-list",{  
  template: "#fruit-list",
  props: ["fruits"],
  data: function(){
    return{
      newfruits: this.fruits
    }
  }
});

var app = new Vue({
  el: "#app",
  data:{
    fruits:[
      {name:"蘋果",amount:100},
      {name:"香蕉",amount:300},
      {name:"鳳梨",amount:500}
    ]
  }
});

使用props將ajax傳入元件

因ajax載入與顯示有時間差,要在該標籤上使用v-if來確保資料載入

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// <-----html----->
#app
  .row
    .col-4
      user-card(:user="user" v-if="user.cell")
  
script(type="text/x-template" id="user-card")
  .card
    img.card-img-top(:src="newuser.picture.large")
    .card-body
      .card-title {{newuser.name.title}}{{newuser.name.first}}{{newuser.name.last}}
      .card-text {{newuser.email}}

// <-----js----->
Vue.component("user-card",{
  props:["user"],
  template: "#user-card",
  data: function(){
    return {
      newuser: this.user
    }
  }
})

var app = new Vue({
  el: "#app",
  data:{
    user: {},
  },
  created: function(){
    $.ajax({
      url: "https://randomuser.me/api/"
    }).done(function(data){
      app.user = data.results[0];
    });
  }
});


props傳入的型別和預設值

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// <-----html----->
#app
  num-input(:num="num")  //50
  num-input  //300

script(type="text/x-template" id="num-input")
  div
    input(type="text" v-model="newnum")
    p {{newnum}}

// <-----js----->
Vue.component("num-input",{
  template: "#num-input",
  props:{
    num:{
      type: Number,
      default: 300
    }
  },
  data: function(){
    return {
      newnum: this.num
    }
  }
});

var app = new Vue({
  el: "#app",
  data:{
    num: 50
  }
});


使用$emit()讓元件方法影響到外層data

  1. 先建立好元件的template。

  1. 在元件的methods上新增[addCash1]方法,並將使用$emit(),傳出一個[item]。

  1. 在HTML上使用自訂標籤,並在該標籤上使用v-on:[item],然後呼叫[addCash2]方法。

  1. 在methods方法中新增[addCash2]方法。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// <-----html----->
#app
  p {{num}}
  button(@click="num += 1") 按鈕B
  num-btn(v-on:event="addNum2")
  
script(type="text/x-template" id="num-btn")
  button(@click="addNum1") 按鈕A

// <-----js----->
Vue.component("num-btn",{
  template: "#num-btn",
  methods:{
    addNum1: function(){
      this.$emit("event")
    }
  }
});

var app =new Vue({
  el: "#app",
  data:{
    num: 50
  },
  methods:{
    addNum2: function(){
      this.num += 1;
    }
  }
});
vue 

其他相關