Vue元件、元件傳值和元件插槽

小丕發表於2020-10-21

Vue元件、元件傳值和元件插槽

一、Vue元件:

1.元件 (Component) 是 Vue.js 最強大的功能之一,通過元件可以擴充套件 HTML 元素,封裝可重用的程式碼;
2.元件是可複用的 Vue 例項,與 new Vue 接收相同的選項,例如 data、computed、watch、methods 以及生命週期鉤子等
3.元件註冊:
3.1 元件引數的data值必須是函式 同時這個函式要求返回一個物件
3.2 元件模板必須是單個根元素
3.3 元件模板的內容可以是模板字串
3.4 元件可以重複使用多次 ;因為data中返回的是一個物件所以每個元件中的資料是私有的,即每個例項可以維護一份被返回物件的獨立的拷貝
3.5 如果使用駝峰式命名元件,那麼在使用元件的時候,只能在字串模板中用駝峰的方式使用元件;
命名:Vue.component(‘HelloWorld’…
使用:< hello-world >
a.全域性註冊
a.1 全域性元件註冊後,任何vue例項都可以用

<div id="app">
    <button-counter></button-counter>
    <button-counter></button-counter>
     <hello-world></hello-world>
  </div>
<script type="text/javascript">
     Vue.component('HelloWorld', {
      data: function(){
        return {
          msg: 'HelloWorld'
        }
      },
      template: '<div>{{msg}}</div>'
    });
    Vue.component('button-counter', {
      // 1、
      data: function(){
        return {
          count: 0
        }
      },
   // 2、元件模板必須是單個根元素;元件模板的內容可以是模板字串  
      template: `
        <div>
          <button @click="handle">點選了{{count}}次</button>
          <button>測試123</button>
			#  6 在字串模板中可以使用駝峰的方式使用元件	
		   <HelloWorld></HelloWorld>
        </div>
      `,
      methods: {
        handle: function(){
          this.count += 2;
        }
      }
    })
    var vm = new Vue({
      el: '#app',
      data: {
      }
    });
  </script>

b.區域性註冊:只能在當前註冊它的vue例項中使用

//定義:
//對應元件名的實際元件
var HelloWorld = {
  data: function(){
    return {
      msg: 'HelloWorld'
    }
  },
  template: '<div>{{msg}}</div>'
};
//區域性註冊元件名
var vm = new Vue({
  el: '#app',
  data: {   
  },
  components: {
    'hello-world': HelloWorld,
  }
});
//使用
  <div id="app">
    <!-- 不能使用駝峰命名 -->
    <hello-world></hello-world>
    <test-com></test-com>
  </div>

二、Vue元件之間傳值

  1. 父元件向子元件傳值(子元件props:屬性;父元件繫結)
    父元件傳值形式是以屬性的形式繫結值到子元件身上。
    父元件:
<blog-post
  v-for="post in posts"
  v-bind:key="post.id"
  v-bind:title="post.title"
></blog-post>

new Vue({
  el: '#blog-post-demo',
  data: {
    posts: [
      { id: 1, title: 'My journey with Vue' },
      { id: 2, title: 'Blogging with Vue' },
      { id: 3, title: 'Why Vue is so fun' }
    ]
  }
})

子元件:

Vue.component('blog-post', {
  props: ['title'],
  template: '<h3>{{ title }}</h3>'
})

2.子元件向父元件傳值
(例項物件的方法$emit:發射,發射自定義事件名稱和引數 父元件監聽自定義的事件名稱和定義處理函式

a. 子元件用$emit()觸發事件:
子元件監聽按鈕的點選事件對應的處理就是:觸發另一個自定義的事件,並該事件的處理函式傳遞引數:
$emit() 第一個引數為 自定義的事件名稱 第二個引數為需要傳遞的資料

Vue.component('menu-item', {
  props: ['parr'],
  template: `
    <div>
      <ul>
        <li :key='index' v-for='(item,index) in parr'>{{item}}</li>
      </ul>
      <button @click='$emit("enlarge-text, 5")'>擴大父元件中字型大小</button>
    </div>
  `
});

b. 父元件用v-on(縮寫@) 監聽子元件的事件
監聽:
@enlarge-text=‘handle’
解析:@子元件定義的事件名稱=‘父元件實際處理函式’

父元件:
<div id="app">
  <div :style='{fontSize: fontSize + "px"}'>{{pmsg}}</div>
  <menu-item :parr='parr' @enlarge-text='handle'></menu-item>
</div>

    var vm = new Vue({
      el: '#app',
      data: {
        pmsg: '父元件中內容',
        parr: ['apple','orange','banana'],
        fontSize: 10
      },
      methods: {
        handle: function(val){
          // 擴大字型大小
          this.fontSize += val;
        }
      }
    });
  1. 兄弟元件之間的傳遞 (事件中心hub,事件觸發 hub的emit(),事件中心監聽hub.$on|off)
    ;兄弟之間傳遞資料需要藉助於事件中心,通過事件中心傳遞資料; var hub = new Vue() 全域性下建立hub物件,其實就是vue例項
    a. 傳遞資料方: 通過一個事件觸發emit(自定義事件名稱,傳遞的資料)
    Vue.component('test-tom', {
      data: function(){
        return {
          num: 0
        }
      },
      template: `
        <div>
          <div>TOM:{{num}}</div>
          <div>
            <button @click='handle'>點選</button>
          </div>
        </div>
      `,
      methods: {
        handle: function(){
          //2、傳遞資料方,通過一個事件觸發hub.$emit(方法名,傳遞的資料)   觸發兄弟元件的事件
          hub.$emit('jerry-event', 2);
        }
      },
      
    });

b. 接收資料方,【通過mounted(){} 鉤子中】 事件中心監聽hub.$on(事件名稱,事件處理箭頭函式)

Vue.component('test-jerry', {
      data: function(){
        return {
          num: 0
        }
      },
      template: `
        <div>
          <div>JERRY:{{num}}</div>
          <div>
            <button @click='handle'>點選</button>
          </div>
        </div>
      `,
      mounted: function() {
        // 3、接收資料方,通過mounted(){} 鉤子中  觸發hub.$on()方法名
        hub.$on('jerry-event', (val) => {
          this.num += val;
        });
      }
    });

接收方:mounted中呼叫事件中心監聽元件1中自定義的事件名稱和接收引數val
hub.$on(‘jerry-event’, (val) => {this.num += val; });

銷燬事件 通過hub.$off()方法名銷燬之後無法進行傳遞資料

d. 傳送方變為接收方,在mounted中新增監聽;接收方變傳送方則emit傳送函式名稱和引數;

三、元件插槽

有時讓插槽內容能夠訪問子元件中才有的資料是很有用的
例如,設想一個帶有如下模板的 元件:

<span>
  <slot>{{ user.lastName }}</slot>
</span>

我們可能想換掉備用內容,用名而非姓來顯示。如下:

<current-user>
  {{ user.firstName }}
</current-user>

然而上述程式碼不會正常工作,因為只有 元件可以訪問到 user 而我們提供的內容是在父級渲染的。

為了讓 user 在父級的插槽內容中可用,我們可以將 user 作為 元素的一個 attribute 繫結上去:

<span>
  <slot v-bind:user="user">
    {{ user.lastName }}
  </slot>
</span>

繫結在 元素上的 attribute 被稱為插槽 prop 。現在在父級作用域中,我們可以使用帶值的 v-slot 來定義我們提供的插槽 prop 的名字:

<current-user>
  <template v-slot:default="slotProps">
    {{ slotProps.user.firstName }}
  </template>
</current-user>

在這個例子中,我們選擇將包含所有插槽 prop 的物件命名為 slotProps,但你也可以使用任意你喜歡的名字。

獨佔預設插槽的縮寫語法:
在上述情況下,當被提供的內容只有預設插槽時,元件的標籤才可以被當作插槽的模板來使用。這樣我們就可以把 v-slot 直接用在元件上:

<current-user v-slot:default="slotProps">
  {{ slotProps.user.firstName }}
</current-user><current-user v-slot="slotProps">
  {{ slotProps.user.firstName }}
</current-user>

連結: https://www.jianshu.com/p/e10baeff888d.

相關文章