Elaine's Blog 朝著 senior 前進的工程師

Vue 學習筆記

2018-06-03

Vue

  • 模板

    <div id="app">\{\{ message }}</div>
    
  • 資料與方法

    <script>
      var app = new Vue({
        el: "#app",
        data: {
          message: "Hello Vue!",
        },
      });
    </script>
    

模板語法

  • v—text 顯示文字
    • 或是 {{}} 也可以顯示文字
      • {{ dataname }}
      • 可以運算 {{ count + 1 }}
      • 若為條件式,只能用三元 {{ ok? “yes” : “no” }}
      • {{ mes.spilt(“”).reverse().join(“”) }}
  • v—html 顯示 HTML
  • v-if、v-else、v-elseif、v-show
    • v-if 切換時,真的會新增或移除 DOM,
    • v-show 僅是套用樣式,false 時套用 display: none
    • 如果條件常常改變,用 v-show 比較好
  • v-for

    <li v-for="n in 10">\{\{n}}</li>
    
    <li v-for="todo in todo_list">\{\{todo}}</li>
    
    • object

      • 一定要先寫 value 再寫 key
      <li v-for="(value, key) in todo_list">\{\{key}} : \{\{value}}</li>
      
    • Vue 1 的 track-by => key

      • 如果只用 for 沒有用 key 的話,如果裡面有 input 之類的,會有問題,原因是因為沒有綁定 id
  • v-bind 屬性綁定、class、style

    • v-bind:class="{is_finished: todo.is_finished}
    • v-bind 可以簡寫為 :
    • :style="{color: mycolor , fontSize: myFontSize }"
    • :href="url"
  • v-model 雙向綁定某個 data

    • 只用在 input、select、textarea

      <input v-model="new_todo_text" />
      
    • .lazy 提高頁面處理效能,整個輸入完才更新值 (預設類似 onkeyup,用 lazy 之後類似 onchange)

      <input v-model.lazy="username" />
      
    • .number 轉為數值

      <input v-model.number="age" type="number" />
      
    • .trim 自動過濾前後的空格

      <textarea v-model.trim="content" col="55" row="8">
      
  • v-on 事件綁定
    • v-on:click="delete_todo(todo)"
    • v-on 可以簡寫為 @
      • @click="delete_todo(todo)"
    • 取消冒泡或預設行為
      • event.stopPropagation()
      • event.preventDefault()
      • v-on:submit.stop.prevent="delete_todo(todo)"
    • 鍵盤事件 v-on:keyup.enter="delete_todo(todo)"

template

最外層只能有一個根節點

<body>
  <div id="app">
    <my-component></my-component>
  </div>

  <script>
    Vue.component("my-component", {
      template: '<div class="component"> <span> \{\{count}} </span> </div>',
      props: ["count"],
    });
    new Vue({
      el: "#app",
      data: {
        counts: 0,
      },
    });
  </script>
  <body></body>
</body>

或是

<body>
  <div id="app">
    <my-component></my-component>
  </div>

  <script type="text/x-template" id="my-component">
    <span> \{\{count}} </span>
  </script>

  <script>
    Vue.component("my-component", {
      template: "#my-component",
      props: ["count"],
    });
    new Vue({
      el: "#app",
      data: {
        counts: 0,
      },
    });
  </script>
  <body></body>
</body>

資料與方法

  • data 放資料
  • methods 放 function

    • 用 this 來讀取 data 資料

      var myapp = new Vue({
          el: '#app',
          data: {
              message: 'abc',
          }
          methods: {
              reverseMessage: function() {
                  return this.message.spilt("").reverse().join("");
              }
          }
      });
      
  • computed 資料變動時,某個資料也會變動時
    • computed 是在監控資料更動後,重新運算結果呈現於畫面上,一般來說不會修改資料,只會回傳用於畫面呈現的資料
    • methods 就是互動的函式,需要觸發才會運作,會用來修改資料內容
    • 如果資料量大,computed 自然會比較慢,只要資料變動就會觸發,無形之中執行次數也會增加,因此在大量資料時,會建議透過 methods 減少不必要的運算喔
  • watch 資料變動時,會 call 的 function
    • 常用在監聽滾動事件 scroll
  • filters 過濾器

    <div id="app">
      <p>\{\{ msg | touppercase }}</p>
      <p></p>
      <p>\{\{ num | topercetage }}</p>
      <p></p>
    </div>
    
    <script>
      var myapp = new Vue({
          el: '#app',
          data: {
              msg: 'abc',
              num: 0.3
          }
          filters: {
              touppercase: function(value){
                  return value.toUpperCase();
              },
              topercetage: function(value){
                  return value * 100 + '%';
              }
          }
      });
    </script>
    

元件

  • 使用元件來避免共用資料
  • data 必須是一個 function
  • Vue.component 定義全局元件

    <div>
      <count-component></count-component>
      <count-component></count-component>
      <count-component></count-component>
    </div>
    
    <script>
      Vue.component("count-component", {
        template: "<button @click="add">8</button>",
        data: function() {
          return {
            count: 0,
          };
        },
        methods: {
          add: function() {
            this.count++;
          }
        }
      });
    
      const app = new Vue({
          el: '#app'
      });
    </script>
    
  • 也可以使用 component 定義區域元件

    new Vue({
      el: "#app",
      components: {
        "component-a": ComponentA,
        "component-b": ComponentB,
      },
    });
    
  • 在 ComponentB 可以使用 ComponentA,但 ComponentA 不可以使用 ComponentB

    var ComponentA = {
      /* ... */
    };
    
    var ComponentB = {
      components: {
        "component-a": ComponentA,
      },
      // ...
    };
    
  • props、emit event
    • 資料從爸爸來 => props
    • 資料要給爸爸 => emit event
      • $.on 綁定監聽事件
      • $.emit 向上發送事件

生命週期

event bus 同層去傳遞資料

  • 小心同名事件

:is 動態指定

  • 用來切換 tab 很方便
<div id="app">
    <div id="left">
        <button @click:"currentChannel = channel-1">channel-1</button>
        <button @click:"currentChannel = channel-2">channel-2</button>
        <button @click:"currentChannel = channel-3">channel-3</button>
    </div>
    <div id="right">
        <componet :is="currentChannel"></componet>
    </div>
</div>

<script>
    Vue.component('channel-1', {
        template: '<div class="channel">1</div>',
    });
    Vue.component('channel-2', {
        template: '<div class="channel">2</div>',
    });
    Vue.component('channel-3', {
        template: '<div class="channel">3</div>',
    });
    new Vue({
        el: '#app',
        data: {
            currentChannel: 'channel-1'
        }
    });
</script>

<keep alive> 保持狀態

  • 會保留在記憶體,但是在頁面不會顯示,避免重新渲染
  • 呈上 :is 一起運用,就可以用來保持狀態
  • 被呼叫到的,hook 是 activated()

slot

  • 在子元件挖個洞,讓外層的塞

Vue.set

  • 如果某個資料還沒被宣告,需要動態加入的話,可以使用 Vue.set
<div id="app">
  <button @click="work">work</button>
  <div v-for="person in people">\{\{person.name}}} - \{\{person.age}}}</div>
</div>

<script>
  var app = new Vue({
    el: "#app",
    data: {
      people: [
        {
          name: "elaine",
          age: 20,
        },
        {
          name: "nick",
          age: 70,
        },
      ],
    },
    methods: {
      work: function() {
        // this cannot work
        // this.people[0] = {
        //   name: "amy",
        //   age: 18,
        // };

        Vue.set(this.people, 0, {
          name: "amy",
          age: 18,
        });
      },
    },
  });
</script>

表單

  • true-value、false-value

    <input v-model="gender" true-value="male" false-value="female" />
    
    <script>
      var app = new Vue({
        el: "#app",
        data: {
          gender: "male",
        },
      });
    </script>
    

其他

  • 一個頁面可以有多個 Vue 的實例
  • Vue 的實例無法巢狀
  • js 裡面是無法有 -,所以 background-img 要改成 backgroundImg
  • 樣式的方法有
    • 物件
      • :class="{'active': isActive, 'bg-danger': boxColor}"
    • 陣列
      • :class="['active', 'bg-danger']"
    • 行內樣式
      • :style="{backgroundColor: 'red', color: 'white'}"
      • :style="[backgroundColor: 'red', color: 'white']"
    • Vue 會自動加上 prefix
  • v-for 注意事項
    • 物件的 index 是物件的屬性、陣列的 index 是從 0 開始的正數字
    • 有 input 的時候特別注意
      • 因為 Vue 並不會完全置換 DOM 物件,所以會有該 input 不會跟從原 DOM 的問題
      • 解決方法只要綁上 :key 就可以了
    • 直接操作陣列
      • 直接將陣列長度 = 0,並不會運行
      • 直接修改陣列 index,例如 array[2]=true,並不會運行
        • 需要用 Vue.set(array,2,true) 此方法,才能讓 Vue 重新監控
    • 因為只能回傳一個節點,可以使用 <template v-for="..."> 來協助輸出
    • 當 v-for 和 v-if 寫在同一個,會先執行 v-for 再執行 v-if
  • 如果我們要透過 Ajax 讀取資料,至少到 create 階段才能正確運作,常用 mounted 也可以
  • 必須要一開始就定義好 data 的格式,Vue 才有辦法追蹤資料來改變 DOM 節點

Similar Posts

上一篇 Sass 學習筆記

Content