Vue2 第一天學習

龍恩0707發表於2017-05-01
個人小總結:1年多沒有寫部落格,感覺很多知識點生疏了,雖然工作上能解決問題,但是當別人問到某個知識點的時候,還是迷迷糊糊的,所以堅持寫部落格是硬道理的,因為大腦不可能把所有的知識點記住,有可能某一天忘了,但是我們工作上還是會使用,只是理論忘了,所以寫部落格的好處是可以把之前的東西重新看一遍後會在大腦裡面重新浮現起來,特別在面試的時候,別人問你的知識點的時候答不上來那種尷尬,但是平時經常使用到,只是說不出所以來的,因此寫部落格是最好的思路。

閱讀目錄

1.vue元件註冊步驟

Vue.js 的元件有三個步驟: 建立元件構造器(Vue.extend()方法 ),註冊元件(Vue.component())和例項化元件。
如下demo:

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id="container">
      <component1></component1>
    </div>
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    // 1. 建立一個元件構造器
    var component1 = Vue.extend({
      template: '<div>hello world</div>'
    });
    // 2. 註冊元件,並指定元件的標籤為<component1>
    Vue.component('component1', component1);

    // 3. 例項化元件
    new Vue({
      el: '#container'
    });
  </script>
</html>

瀏覽器編譯後html結構會變為 

<div id="container">
  <div>hello world</div>
</div>

頁面執行顯示為
hello world

2.理解元件的建立和註冊。

2-1 Vue.extend() 是Vue構造器的擴充套件,呼叫Vue.extend()建立的是一個元件構造器,該構造器有一個選項物件,選項物件的template屬性用於定義元件要渲染的html。
2-2 Vue.component() 是註冊元件,需要2個引數,第一個引數是自定義元件的標籤,第二個引數是元件的構造器。
2-3 元件需要掛載到某個Vue的例項下,否則不生效。
如下例項:

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id="container1">
      <component1></component1>
    </div>
    <div id="container2">
      <component1></component1>
    </div>

    <div id="container3">
      <component1></component1>
    </div>
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    // 1. 建立一個元件構造器
    var component1 = Vue.extend({
      template: '<div>hello world</div>'
    });
    // 2. 註冊元件,並指定元件的標籤為<component1>
    Vue.component('component1', component1);

    // 3. 例項化元件 container1
    new Vue({
      el: '#container1'
    });
    // 3. 例項化元件 container2
    new Vue({
      el: '#container2'
    });
    // 不例項化 container3 因此第三個自定義標籤是不會生效的
  </script>
</html>

最終程式碼被渲染成為如下:

<div id="container1"><div>hello world</div></div>
<div id="container2"><div>hello world</div></div>

3.理解Vue全域性註冊和區域性註冊

呼叫Vue.component()註冊元件時,元件的註冊是全域性的,如果想要使用元件的區域性註冊的話,可以用選項物件的components屬性實現區域性註冊。
如下程式碼:中間就把第二步註冊元件哪項移到例項化元件裡面來了;如下程式碼:

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id="container1">
      <component1></component1>
    </div>
    <!-- 不能使用component1元件,因為它是container1裡面區域性註冊的 -->
    <div id="container2">
      <component1></component1>
    </div>
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    // 1. 建立一個元件構造器
    var component1 = Vue.extend({
      template: '<div>hello world</div>'
    });
    
    // 3. 例項化元件 container1
    new Vue({
      el: '#container1',
      components: {
        'component1': component1
      }
    });
    // 例項化container2 是不生效的
    new Vue({
      el: '#container2'
    })
  </script>
</html>
例項化container2 是不生效的,並且在瀏覽器控制檯會報如下錯誤:

4.理解父元件和子元件。

在一個元件中包含另一個元件,那麼另一個元件就是該元件的子元件。
如下程式碼:

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id="container1">
      <parent-component></parent-component>
    </div>
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    // 1. 建立一個元件構造器
    var Child = Vue.extend({
      template: '<div>hello world</div>'
    });
    
    var Parent = Vue.extend({
      // 在元件內部使用<child-component>元件
      template: '<div>hello world <child-component></child-component></div>',
      components: {
        // 區域性註冊Child元件
        'child-component': Child
      }
    });
    // 全域性註冊Parent元件
    Vue.component('parent-component', Parent);
    
    // 例項化元件
    new Vue({
      el: '#container1'
    })
  </script>
</html>

簡單理解程式碼如下:
1. var Child = Vue.extend(...) 定義一個Child元件構造器。
2. var Parent = Vue.extend(...) 定義一個Parent元件構造器。
3. components: {'child-component': Child}, 將Child元件註冊到Parent元件,並將Child元件的標籤設定為 child-component;
4. template: 渲染html模板,找到template選項,然後使用 child-component元件。
5. 註冊Parent元件 Vue.component('parent-component', Parent);
6. 最後例項化元件,需要到html元素為id='container1'裡面去。
Child元件是在Parent元件中註冊的,只能在Parent元件中註冊的。如下幾種情況都不行的。

4-1 以子標籤的形式在父元件中使用;如下程式碼:

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id="container1">
      <parent-component>
        <child-component></child-component>
      </parent-component>
    </div>
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    // 1. 建立一個元件構造器
    var Child = Vue.extend({
      template: '<div>hello world</div>'
    });
    
    var Parent = Vue.extend({
      // 在元件內部使用<child-component>元件
      template: '<div>hello world</div>',
      components: {
        // 區域性註冊Child元件
        'child-component': Child
      }
    });
    // 全域性註冊Parent元件
    Vue.component('parent-component', Parent);

    // 例項化元件
    new Vue({
      el: '#container1'
    })
  </script>
</html>

上面呼叫子元件的方式是無效的,因為在js裡面當父元件要需要的html模板template的內容的時候已經決定了需要渲染什麼,所以當parent-component執行的時候,在父元件使用自定義的子標籤。
執行時會當做html的普通標籤來渲染,但是它又不是普通的html標籤,因此會被忽略掉。

4-2. 在父元件標籤外使用子元件。

<div id="container1">
  <parent-component></parent-component>
  <child-component></child-component>
</div>

js程式碼還是上面的一樣,執行完成後,在瀏覽器下會報錯如下:

5.理解元件的語法糖。

我們可以使用更簡單的方式來註冊元件。
5-1 使用Vue.component()直接建立和註冊元件。如下程式碼:

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id="container1">
      <component1></component1>
    </div>
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    // 全域性註冊
    Vue.component('component1', {
      template: '<div>hello world222</div>'
    });
    // 例項化
    var vm1 = new Vue({
      el: '#container1'
    });
  </script>
</html>

Vue.component()的第一個引數是標籤名稱,第二個引數是一個選項物件,使用選項物件的template屬性定義,使用該方式,在Vue原始碼中會呼叫Vue.extend()方法。
注意: 在template元素中需要使用一個標籤容器包圍,比如我們可以把div元素去掉的話,只放內容的話,會報錯如下:

5-2 在選項物件的components屬性中實現區域性註冊

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id="container1">
      <component1></component1>
    </div>

    <div id="container2">
      <component2></component2>
      <component3></component3>
    </div>
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    // 全域性註冊,my-component1是標籤名稱
    Vue.component('component1',{
      template: '<div>This is the first component!</div>'
    })
    var vm1 = new Vue({
      el: '#container1'
    })
    
    // 例項化 區域性註冊
    var vm1 = new Vue({
      el: '#container2',
      components: {
        // 區域性註冊, component2 是標籤名稱
        'component2': {
          template: '<div>component2</div>'
        },
        // 區域性註冊,component3 是標籤名稱
        'component3': {
          template: '<div>component3</div>'
        }
      }
    });
  </script>
</html>

6.學會使用 script或 template 標籤。

雖然語法糖簡化了元件註冊,但是在template選項中拼接了html元素,這導致View和C層的高耦合性。幸運的是Vue.js 提供了2種方式將javascript中的html模板分離出來。
6-1 使用script標籤, 如下程式碼:

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id="container1">
      <component1></component1>
    </div>
    <script type='text/x-template' id="myComponent">
      <div>hello world!!!!!</div>
    </script>
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    new Vue({
      el: '#container1',
      components: {
        'component1': {
          template: '#myComponent'
        }
      }
    })
  </script>
</html>

注意: 使用<script>標籤時,type指定為 text/x-template,是告訴瀏覽器這不是一段js指令碼,瀏覽器在解析html文件時會忽略script標籤內定義的內容。
6-2 使用<template>標籤。不需要指定type屬性。
如下程式碼:

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id="container1">
      <component1></component1>
    </div>
    <template id="myComponent">
      <div>hello world2222!!!!!</div>
    </template>
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    new Vue({
      el: '#container1',
      components: {
        'component1': {
          template: '#myComponent'
        }
      }
    })
  </script>
</html>

7.理解使用props。

父元件的資料如何傳給子元件呢?可以使用props把資料傳給子元件。
程式碼如下:

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
    </head>
    <div id="container1">
      <component1 v-bind:my-name="name" v-bind:my-age="age"></component1>
    </div>
    <template id="myComponent">
      <table>
        <tr>
          <th colspan="2">
            子元件資料
          </th>
        </tr>
        <tr>
          <td>myName</td>
          <td>{{ myName }}</td>
        </tr>
        <tr>
          <td>myAge</td>
          <td>{{ myAge }}</td>
        </tr>
      </table>
    </template>
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    new Vue({
      el: '#container1',
      data: {
        name: 'longen',
        age: 30
      },
      components: {
        'component1': {
          template: '#myComponent',
          props: ['myName', 'myAge']
        }
      }
    })
  </script>
</html>

注意: 在子元件中定義prop時,使用了camelCase命名法。由於HTML特性不區分大小寫,camelCase的prop用於特性時,會轉為短橫線隔開的,比如上面的程式碼:
在props中定義的myName,在用作特性時需要轉換為 my-name

理解prop的單向繫結
既然父元件使用props把資料傳給了子元件,那麼如果子元件修改了資料,對父元件是否有影響呢?
看下面的程式碼如下:

<!DOCTYPE html>
<html>
  <body>
    <head>
      <title>演示Vue</title>
      <style>
        * {
          margin: 0;
          padding: 0;
          box-sizing: border-box
        }
        html {
          font-size: 12px;
          font-family: Ubuntu, simHei, sans-serif;
          font-weight: 400
        }
        body {
          font-size: 1rem
        }

        table,
        td,
        th {
          border-collapse: collapse;
          border-spacing: 0
        }

        table {
          width: 100%;
          margin: 20px;
        }

        td,
        th {
          border: 1px solid #bcbcbc;
          padding: 5px 10px
        }

        th {
          background: #42b983;
          font-size: 1.2rem;
          font-weight: 400;
          color: #fff;
          cursor: pointer
        }

        tr:nth-of-type(odd) {
          background: #fff
        }

        tr:nth-of-type(even) {
          background: #eee
        }

        fieldset {
          border: 1px solid #BCBCBC;
          padding: 15px;
        }

        input {
          outline: none
        }

        input[type=text] {
          border: 1px solid #ccc;
          padding: .5rem .3rem;
        }

        input[type=text]:focus {
          border-color: #42b983;
        }

        button {
          outline: none;
          padding: 5px 8px;
          color: #fff;
          border: 1px solid #BCBCBC;
          border-radius: 3px;
          background-color: #009A61;
          cursor: pointer;
        }
        button:hover{
          opacity: 0.8;
        }

        #container1 {
          margin: 0 auto;
          max-width: 480px;
        }
      </style>
    </head>
    <div id="container1">
      <table>
        <tr>
          <th colspan="3">
            父元件資料
          </th>
        </tr>
        <tr>
          <td>name</td>
          <td>{{ name }}</td>
          <td><input type='text' v-model = "name" /></td>
        </tr>
        <tr>
          <td>age</td>
          <td>{{ age }}</td>
          <td><input type="text" v-model="age" /></td>
        </tr>
      </table>
      <component1 v-bind:my-name="name" v-bind:my-age="age"></component1>
    </div>
    <template id="myComponent">
      <table>
        <tr>
          <th colspan="3">
            子元件資料
          </th>
        </tr>
        <tr>
          <td>myName</td>
          <td>{{ myName }}</td>
          <td><input type="text" v-model="myName" /></td>
        </tr>
        <tr>
          <td>myAge</td>
          <td>{{ myAge }}</td>
          <td><input type="text" v-model="myAge" /></td>
        </tr>
      </table>
    </template>
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    new Vue({
      el: '#container1',
      data: {
        name: 'longen',
        age: 30
      },
      components: {
        'component1': {
          template: '#myComponent',
          props: ['myName', 'myAge']
        }
      }
    })
  </script>
</html>

相關文章