從零開始學 Web 之 Vue.js(六)Vue的元件

qq_42606051發表於2018-09-26

大家好,這裡是「 從零開始學 Web 系列教程 」,並在下列地址同步更新......

  • github:https://github.com/Daotin/Web
  • 微信公眾號:Web前端之巔
  • 部落格園:http://www.cnblogs.com/lvonve/
  • CSDN:https://blog.csdn.net/lvonve/

在這裡我會從 Web 前端零基礎開始,一步步學習 Web 相關的知識點,期間也會分享一些好玩的專案。現在就讓我們一起進入 Web 前端學習的冒險之旅吧!

一、Vue元件

什麼是元件: 元件的出現,就是為了拆分 Vue 例項的程式碼量的,能夠讓我們以不同的元件,來劃分不同的功能模組,將來我們需要什麼樣的功能,就可以去呼叫對應的元件即可;

元件化和模組化的不同:

  • 模組化: 是從程式碼邏輯的角度進行劃分的;方便程式碼分層開發,保證每個功能模組的職能單一;
  • 元件化: 是從UI介面的角度進行劃分的;前端的元件化,方便UI元件的重用;

二、定義元件

1、定義全域性元件

定義全域性元件有三種方式:

1、使用 Vue.extend 配合 Vue.component 方法:

// 1.使用 Vue.extend 來建立全域性的Vue元件
var login = Vue.extend({
  // 通過 template 屬性,指定了元件要展示的HTML結構
  template: '<h1>登入</h1>'
});

// 2.使用 Vue.component('元件的名稱', 建立出來的元件模板物件) 
Vue.component('login', login);

// 3.使用元件
<div id="app">
    <!-- 如果要使用元件,直接,把元件的名稱,以 HTML 標籤的形式,引入到頁面中即可 -->
    <login></login>
</div>

注意:

使用 Vue.component 定義全域性元件的時候,元件名稱使用了 駝峰命名(如myLogin),則在引用元件的時候,需要把 大寫的駝峰改為小寫的字母,同時在兩個單詞之前,使用 - 連結(<my-login></my-login>);如果不使用駝峰,則直接拿名稱來使用即可;

當然,上面兩步可以合成一個步驟完成:

Vue.component('login', Vue.extend({
  template: '<h1>登入</h1>'
}));

2、直接使用 Vue.component 方法:

Vue.component('login', {
  template: '<div><h3>註冊</h3><span>123</span></div>'
});

注意:不論是哪種方式建立出來的元件,元件的 template 屬性指向的模板內容,必須有且只能有唯一的一個根元素,否則會報錯。

3、將模板字串,定義到 template 標籤中:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="box">
    <!-- 3. 使用元件 -->
    <mycom></mycom>
  </div>
  <!-- 2.在 被控制的 #box 外面,使用 template 元素,定義元件的HTML模板結構  -->
  <template id="tmp1">
    <!-- 還是需要遵從template 模板內容,必須有且只能有唯一的一個根元素 -->
    <div>
      <h3>登入</h3>
      <p>p標籤</p>
    </div>
  </template>

  <script>
    // 1.定義元件
    Vue.component('mycom', {
      template: '#tmp1'
    });

    var vm = new Vue({
      el: "#box",
      data: {},
      methods: {}
    });
  </script>
</body>

</html>

注意:

1、template: '#tmp1' 是定義模板標籤的 id ,# 別忘寫了。

2、被控制的 #box 外面,使用 template 標籤;

3、 template 標籤裡面,還是遵從只能有唯一的一個根元素的原則。

2、定義私有元件

定義私有元件,就是再VM例項中定義元件。

如下,box中可以使用,box2不可以使用。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="box">
    <mycom></mycom>
  </div>

  <div id="box2">
    <mycom></mycom>
  </div>

  <template id="temp">
    <h3>自定義私有屬性</h3>
  </template>

  <script>
    var vm = new Vue({
      el: "#box",
      data: {},
      methods: {},
      // 定義私有元件
      components: {
        mycom: {
          template: '#temp'
        }
      }
    });
    var vm2 = new Vue({
      el: "#box2",
      data: {},
      methods: {}
    });
  </script>
</body>

</html>

3、元件的data和methods屬性

元件中也可以有自己的data和methods屬性,可以傳入template中使用。

特點:

  • data屬性為一個匿名函式,其返回值為一個物件。
  • data 函式返回值為一個物件(最好是新開闢的物件,否則如果多次引用元件,不是新開闢的物件給的話,物件是同一份,而我們需要每一個元件有自己的物件),物件中可以放入資料。
  • 元件中 的data和methods,使用方式,和例項中的 data 和methods使用方式完全一樣
<div id="box2">
  <login></login>
</div>

<template id="temp2">
  <div>
    <input type="button" value="按鈕" @click="myclick">
    <h3>自定義私有屬性</h3>
    <p> {{msg}} </p>
  </div>
</template>

<script>
  Vue.component('login', {
    template: '#temp2',
    data: function () {
      return {
        msg: '這是元件中的data'
      }
    },
    methods: {
      myclick() {
        console.log("點選按鈕");
      }
  }
  });
</script>

三、元件切換

我們在登入註冊一個網站的時候,經常看到兩個按鈕,一個登入,一個註冊,如果你沒有賬號的話,需要先註冊才能登入。我們在點選登入和註冊的時候,網頁會相應的切換,登入頁面就是登陸元件,註冊頁面就是註冊元件,那麼點選登入和註冊,如何實現元件的切換呢?

1、方式一

使用flag識別符號結合v-ifv-else切換元件

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="box">
    <!-- 給a註冊點選事件,切換flag狀態 -->
    <a href="javascript:;" @click.prevent="flag=true">登入</a>
    <a href="javascript:;" @click.prevent="flag=false">註冊</a>
    <!-- 使用v-if v-else切換元件 -->
    <login v-if="flag">
    </login>
    <register v-else="flag">
    </register>
  </div>

  <script>
    Vue.component('login', {
      template: '<h3>登入元件</h3>'
    });
    Vue.component('register', {
      template: '<h3>註冊元件</h3>'
    });

    var vm = new Vue({
      el: "#box",
      data: {
        flag: true
      },
      methods: {}
    });
  </script>
</body>

</html>

缺陷:由於flag的值只有true和false,所以只能用於兩個元件間 的切換,當大於兩個元件的切換就不行了。

2、方式二

使用 component元素的:is屬性來切換不同的子元件

使用 <component :is="componentId"></component> 來指定要切換的元件。

componentId:為需要顯示的元件名稱,為一個字串,可以使用變數指定。

componentId: 'login' // 預設顯示登入元件。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="box">
    <!-- 給a註冊點選事件,切換flag狀態 -->
    <a href="javascript:;" @click.prevent="componentId='login'">登入</a>
    <a href="javascript:;" @click.prevent="componentId='register'">註冊</a>
    <component :is="componentId"></component>
  </div>

  <script>
    Vue.component('login', {
      template: '<h3>登入元件</h3>'
    });
    Vue.component('register', {
      template: '<h3>註冊元件</h3>'
    });

    var vm = new Vue({
      el: "#box",
      data: {
        componentId: 'login'   // 預設顯示登入
      },
      methods: {}
    });
  </script>
</body>

</html>

為元件切換新增過渡:

很簡單,只需要用 transition 將 component 包裹起來即可。

<transition>
  <component :is="componentId"></component>
</transition>

示例:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
  <link rel="stylesheet" href="./lib/animate.css">

  <style>
    .loginDiv {
      width: 200px;
      height: 200px;
      background-color: red;
    }

    .registerDiv {
      width: 200px;
      height: 200px;
      background-color: blue;
    }
  </style>
</head>

<body>
  <div id="box">
    <!-- 給a註冊點選事件,切換flag狀態 -->
    <a href="javascript:;" @click.prevent="componentId='login'">登入</a>
    <a href="javascript:;" @click.prevent="componentId='register'">註冊</a>
    <transition mode="out-in" enter-active-class="animated bounceInRight" leave-active-class="animated bounceOutRight">
      <component :is="componentId"></component>
    </transition>
  </div>

  <template id="login">
    <div class="loginDiv">
    </div>
  </template>

  <template id="register">
    <div class="registerDiv">
    </div>
  </template>

  <script>
    Vue.component('login', {
      template: '#login'
    });
    Vue.component('register', {
      template: '#register'
    });

    var vm = new Vue({
      el: "#box",
      data: {
        componentId: 'login'
      },
      methods: {}
    });
  </script>
</body>

</html>

mode="out-in":可以設定切換元件的模式為先退出再進入。

四、元件傳值

1、父元件向子元件傳值

我們先通過一個例子看看子元件可不可以直接訪問父元件的資料:

<body>
  <div id="box">
    <mycom></mycom>
  </div>

  <template id="temp">
    <h3>子元件 --- {{msg}}</h3>
  </template>

  <script>
    var vm = new Vue({
      el: "#box",
      data: {
        msg: '父元件的msg'
      },
      methods: {},
      components: {
        mycom: {
          template: '#temp'
        }
      }
    });
  </script>
</body>

由於 components 定義的是私有元件,我們直接在子元件中呼叫父元件的msg會報錯。

那麼,怎麼讓子元件使用父元件的資料呢?

父元件可以在引用子元件的時候, 通過 屬性繫結(v-bind:) 的形式, 把需要傳遞給子元件的資料,以屬性繫結的形式,傳遞到子元件內部,供子元件使用 。

<body>
  <div id="box">
    <mycom v-bind:parentmsg="msg"></mycom>
  </div>

  <template id="temp">
    <h3>子元件 --- 父元件:{{parentmsg}}</h3>
  </template>

  <script>
    var vm = new Vue({
      el: "#box",
      data: {
        msg: '父元件的msg'
      },
      methods: {},
      components: {
        mycom: {
          template: "#temp",
          // 對傳遞給子元件的資料進行宣告,子元件才能使用 
          props: ['parentmsg']
        }
      }
    });
  </script>
</body>

注意:父元件繫結的屬性名稱不能有大寫字母,否則不會顯示,並且在命令列會有提示:

元件data資料和props資料的區別:

  • data資料是子元件私有的,可讀可寫;
  • props資料是父元件傳遞給子元件的,只能讀,不能寫。

案例:發表評論功能

父元件為評論列表,子元件為ID,評論者,內容和按鈕的集合,在輸入ID,評論者等內容,然後點選新增的時候,需要首先獲取子元件的list列表,然後再新增新的列表項到列表中。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="box">
    <mycom :plist="list"></mycom>

    <ul>
      <li v-for="item in list" :key="item.id">
        ID:{{item.id}} --- 內容:{{item.content}} --- 評論人:{{item.user}}
      </li>
    </ul>
  </div>

  <template id="tmp1">
    <div>
      <label>
        ID:
        <input type="text" v-model="id">
      </label>
      <br>
      <label>
        評論者:
        <input type="text" v-model="user">
      </label>
      <br>
      <label>
        內容:
        <textarea v-model="content"></textarea>
      </label>
      <br>
      <!-- 把父元件的資料作為子元件的函式引數傳入 -->
      <input type="button" value="新增評論" @click="addContent(plist)">
    </div>
  </template>

  <script>
    var vm = new Vue({
      el: "#box",
      data: {
        list: [{
          id: Date.now(),
          user: 'user1',
          content: 'what'
        }, {
          id: Date.now(),
          user: 'user2',
          content: 'are'
        }]
      },
      methods: {},
      components: {
        mycom: {
          template: '#tmp1',
          data: function () {
            return {
              id: '',
              user: '',
              content: '',
            }
          },
          methods: {
            addContent(plist) {
              plist.unshift({
                id: this.id,
                user: this.user,
                content: this.content
              });
            }
          },
          props: ['plist']
        }
      }
    });
  </script>
</body>

</html>

把新增ID,評論人,內容作為子元件,把列表作為父元件,然後把新增的資料放到父元件列表上,由於要獲取到父元件列表的資料,所以必然涉及到父元件向子元件傳值的過程。這裡還通過子元件方法引數來儲存父元件的資料到子元件的資料中。

2、父元件向子元件傳方法

既然父元件可以向子元件傳遞資料,那麼也可以向子元件傳遞方法。

<body>
  <div id="box">
    <mycom v-bind:parentmsg="msg" @parentfunc="show"></mycom>
  </div>

  <template id="temp">
    <div>
      <input type="button" value="呼叫父元件方法" @click="sonClick">
      <h3>子元件 --- 父元件:{{parentmsg}}</h3>
    </div>
  </template>

  <script>
    var vm = new Vue({
      el: "#box",
      data: {
        msg: '父元件的msg'
      },
      methods: {
        show(data1, data2) {
          console.log("這是父元件的show方法" + data1 + data2);
        }
      },
      components: {
        mycom: {
          template: "#temp",
          // 對傳遞給子元件的資料進行宣告,子元件才能使用 
          props: ['parentmsg'],
          methods: {
            sonClick() {
              // 呼叫父元件的show方法
              this.$emit("parentfunc", 111, 222);
            }
          }
        }
      }
    });
  </script>
</body>

1、@parentfunc="show" 繫結父元件的show方法。

2、<input type="button" value="呼叫父元件方法" @click="sonClick"> 點選按鈕呼叫父元件的show方法

3、在 子元件的 sonClick 方法中使用 this.$emit("parentfunc"); 來呼叫父元件的show方法

4、父元件的show方法也可以傳參,在呼叫的時候,實參從 this.$emit 的第二個引數開始傳入。

5、如果 this.$emit 的第二個引數傳的是子元件的data資料,那麼父元件的方法就可以獲得子元件的資料,這也是把子元件的資料傳遞給父元件的方式。

3、使用 ref 獲取DOM和元件的引用

我們知道Vue不推薦直接獲取DOM元素,那麼在Vue裡面怎麼獲取DOM及元件元素呢?

我們呢可以在元素上使用 ref 屬性來獲取元素。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <script src="./lib/vue-2.4.0.js"></script>
</head>

<body>
  <div id="box">
    <input type="button" value="獲取元素" @click="getrefs" ref="mybtn">
    <h3 ref="myh3">這是H3</h3>
    <mycom ref="mycom"></mycom>
  </div>

  <template id="tmp1">
  </template>

  <script>
    // 定義元件
    Vue.component('mycom', {
      template: '#tmp1',
      data: function () {
        return {
          msg: '子元件的msg',
          pmsg: ''
        }
      },
      methods: {
        show(data) {
          console.log('呼叫子元件的show');
          this.pmsg = data;
          console.log(this.pmsg);
        },

      }
    });

    var vm = new Vue({
      el: "#box",
      data: {
        parentmsg: '父元件的msg'
      },
      methods: {
        getrefs() {
          console.log(this.$refs.myh3);
          console.log(this.$refs.mycom.msg);
          this.$refs.mycom.show(this.parentmsg);
        }
      }
    });
  </script>
</body>

</html>

總結:

1、ref 屬性不僅可以獲取DOM元素,也可以獲取元件(無論全域性還是私有元件)元素。

2、獲取到元件元素後,就可以獲取元件元素的data資料和methods方法。

3、獲取到元件中的方法後,可以傳入VM的data資料,就可以把VM的data資料傳入元件中。

form: https://www.cnblogs.com/lvonve/p/9699711.html

鄭州婦科醫院哪家好

鄭州婦科醫院排名

鄭州人流多少錢

鄭州無痛人流醫院

相關文章