從零開始學 Web 之 Vue.js(二)過濾器,按鍵修飾符,自定義指令

你們好,這裏是「 從零開始學 Web 系列教程 」,並在下列地址同步更新......javascript

  • github:https://github.com/Daotin/Web
  • 微信公衆號:Web前端之巔
  • 博客園:http://www.cnblogs.com/lvonve/
  • CSDN:https://blog.csdn.net/lvonve/

在這裏我會從 Web 前端零基礎開始,一步步學習 Web 相關的知識點,期間也會分享一些好玩的項目。如今就讓咱們一塊兒進入 Web 前端學習的冒險之旅吧!html

1、品牌管理案例

以下圖,前端

一、實現輸入id和name後,點擊add按鈕,添加到table中;vue

二、點擊數據的del,能夠刪除這條數據。java

代碼:git

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

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="./lib/vue-2.4.0.js"></script>
    <style>
        * {
            padding: 0;
            margin: 0;
            position: relative;
        }
      
        /* 實現任意無寬高盒子居中顯示 */
        #app {
            position: absolute;
            left: 50%;
            top: 100px;
            transform: translateX(-50%);
        }

        .box {
            width: 500px;
            height: 40px;
            background-color: #ccc;
            display: inline-block;
            text-align: center;
            line-height: 40px;
            border: 1px solid #aaa;
            box-sizing: border-box;
            border-bottom: none;
        }

        .tb {
            width: 500px;
            text-align: center;
            border-collapse: collapse;
            border-color: #ccc;
        }
    </style>
</head>

<body>
    <div id="app">
        <div class="box">
            <label for="id">
                ID:
                <input type="text" id="id" v-model="id">
            </label>
            <label for="name">
                name:
                <input type="text" id="name" v-model="name">
            </label>
            <input type="button" value="add" @click="addClick">
        </div>

        <table border="1" cellspacing="0" class="tb">
            <tr v-for="item in list">
                <td>{{item.id}}</td>
                <td>{{item.name}}</td>
                <td>{{item.ctime}}</td>
                <td>
                    <!-- 綁定的事件是能夠傳參數的,這裏傳入須要刪除的對象id -->
                    <a href="javascript:;" @click.prevent="delClick(item.id)">del</a>
                </td>
            </tr>
        </table>
    </div>


    <script>
        var vm = new Vue({
            el: "#app",
            data: {
                id: "",
                name: "",
                list: [{
                        id: 1,
                        name: 'tony',
                        ctime: new Date()
                    },
                    {
                        id: 2,
                        name: 'stark',
                        ctime: new Date()
                    }
                ]
            },
            methods: {
                addClick() {
                    // 1.獲取表單數據
                    // 2.組織出一個對象
                    // 3.將對象添加到data中(不須要從新渲染頁面)
                    let item = {
                        id: this.id,
                        name: this.name,
                        ctime: new Date()
                    };
                    if ((this.id != "") && (this.name != "")) {
                        this.list.push(item);
                    }
                    // 4.最後將表單清空
                    this.id = this.name = "";
                },
                delClick(id) {
                    // 1.根據id找到索引(循環查找)
                    // 2.調用數組的 splice方法刪除
                    this.list.filter((item, index) => {
                        if (item.id == id) {
                            this.list.splice(index, 1);
                            return true;
                        }
                    });

                }
            }

        });
    </script>
</body>
</html>

注意:github

一、事件名後面能夠加括號(@click="addClick" 等價於 @click="addClick() ,這樣寫的話,就能夠傳參。)express

一、增長搜索需求

在Query中輸入字符串,若是name項中包括Query中的字符串,則顯示。數組

分析:微信

若是要知足條件才顯示相關行,那麼 <tr v-for="item in list"> 中的list就是一個可變的。這裏咱們使用一個函數,函數裏面進行判斷是否包含Query中的字符串,而後將包含的拷貝到新數組中,填充到list的位置:

<tr v-for="item in search(keywords)">

methods: {
                addClick() {
                  //...
                },
                delClick(id) {
                  //...
                },
                // 添加的用於判斷的函數
                search(keywords) {
                    // 定義新數組保存符合條件的項
                    let newList = [];
                    this.list.forEach((item, index) => {
                        // 包含則返回true
                        if (item.name.includes(keywords)) {
                            newList.push(item);
                        }
                    });
                    return newList;
                }
            }

所有源碼:

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="./lib/vue-2.4.0.js"></script>
    <style>
        * {
            padding: 0;
            margin: 0;
            position: relative;
        }

        /* 實現任意無寬高盒子居中 */

        #app {
            position: absolute;
            left: 50%;
            top: 100px;
            transform: translateX(-50%);
        }

        .box {
            width: 800px;
            height: 40px;
            background-color: #ccc;
            display: inline-block;
            text-align: center;
            line-height: 40px;
            border: 1px solid #aaa;
            box-sizing: border-box;
            border-bottom: none;
        }

        .box>input[type="button"] {
            width: 60px;
            background-color: #aaa;
            border: 0;
            border: 1px solid #aaa;
        }

        .tb {
            width: 800px;
            text-align: center;
            border-collapse: collapse;
            border-color: #ccc;
        }
    </style>
</head>

<body>
    <div id="app">
        <div class="box">
            <label for="id">
                ID:
                <input type="text" id="id" v-model="id">
            </label>
            <label for="name">
                name:
                <input type="text" id="name" v-model="name">
            </label>
            <input type="button" value="add" @click="addClick">
            <label for="sel">
                Query:
                <input type="text" id="sel" v-model="keywords">
            </label>
        </div>

        <table border="1" cellspacing="0" class="tb">
            <!-- 有查詢的話,這裏就不該該固定死,而是根據keywords動態生成新的數組 -->
            <!-- <tr v-for="item in list"></tr> -->
            <tr v-for="item in search(keywords)">
                <td>{{item.id}}</td>
                <td>{{item.name}}</td>
                <td>{{item.ctime | ctimeFormat}}</td>
                <td>
                    <!-- 綁定的事件是能夠傳參數的,這裏傳入須要刪除的對象id -->
                    <a href="javascript:;" @click.prevent="delClick(item.id)">del</a>
                </td>
            </tr>
        </table>
    </div>


    <script>
        // ctime 過濾器
        Vue.filter('ctimeFormat', (data) => {
            let time = new Date(data);

            let year = time.getFullYear();
            let month = (time.getMonth() + 1).toString().padStart(2, '0');
            let day = (time.getDate()).toString().padStart(2, '0');
            let hour = (time.getHours()).toString().padStart(2, '0');
            let minute = (time.getMinutes()).toString().padStart(2, '0');
            let second = (time.getSeconds()).toString().padStart(2, '0');

            return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
        });

        var vm = new Vue({
            el: "#app",
            data: {
                id: "",
                name: "",
                keywords: "",
                list: [{
                        id: 1,
                        name: 'tony',
                        ctime: new Date()
                    },
                    {
                        id: 2,
                        name: 'stark',
                        ctime: new Date()
                    }
                ]
            },
            methods: {
                addClick() {
                    // 1.獲取表單數據
                    // 2.組織處一個對象
                    // 3.將對象添加到data中(不須要從新渲染頁面)
                    let item = {
                        id: this.id,
                        name: this.name,
                        ctime: new Date()
                    };
                    if ((this.id != "") && (this.name != "")) {
                        this.list.push(item);
                    }
                    // 4.最後將表單清空
                    this.id = this.name = "";
                },
                delClick(id) {
                    // 1.根據id找到索引(循環查找)
                    // 2.調用數組的 splice方法刪除
                    this.list.filter((item, index) => {
                        if (item.id == id) {
                            this.list.splice(index, 1);
                            return true;
                        }
                    });

                },
                search(keywords) {
                    // 定義新數組保存符合條件的項
                    let newList = [];
                    this.list.forEach((item, index) => {
                        // 包含則返回true
                        if (item.name.includes(keywords)) {
                            newList.push(item);
                        }
                    });
                    return newList;
                }
            }

        });
    </script>
</body>

</html>

2、過濾器

vue 容許自定義過濾器,可被用做一些常見的文本格式化。

過濾器只能用在兩個地方:插值表達式v-bind表達式

一、全局過濾器

基本用法:

<body>
    <div id="box">
        <p>{{msg | msgFormat}}</p>
    </div>

    <script>
        // 使用Vue.filter來定義一個過濾器:
        // 第一個參數:過濾器函數名稱
        // 第二個參數:過濾器函數體
        // 過濾器的參數就是管道符的前面待處理的字符串。
        Vue.filter('msgFormat', (data) => {
            return data.replace("vue", "Daotin");
        });

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

一、使用 Vue.filter(); 來定義一個過濾器。

二、第一個參數:過濾器函數名稱;第二個參數:過濾器函數體

三、過濾器的參數就是管道符的前面待處理的字符串

插值表達式裏的過濾器函數能夠帶參數:

相應的,在 Vue.filter('msgFormat', (data, arg1,arg2,...) 中msgFormat 的參數從第二位開始放置。

能夠帶多個參數。

<body>
    <div id="box">
        <p>{{msg | msgFormat('is a boy', 'and good')}}</p>
    </div>

    <script>
        // 使用Vue.filter來定義一個過濾器:
        // 第一個參數:過濾器函數名稱
        // 第二個參數:過濾器函數體
        // 過濾器的參數就是管道符的前面待處理的字符串。
        Vue.filter('msgFormat', (data, arg1, arg2) => {
            return data.replace("vue", "Daotin " + arg1 + arg2);
        });

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

使用全局過濾器格式化品牌管理案例的 ctime:

<td>{{item.ctime | ctimeFormat}}</td>
...

// ctime 過濾器
Vue.filter('ctimeFormat', (data) => {
  let time = new Date(data);

  let year = time.getFullYear();
  let month = time.getMonth() + 1;
  let day = time.getDate();
  let hour = time.getHours();
  let minute = time.getMinutes();

  return `${year}-${month}-${day} ${hour}:${minute}`;
});

二、私有過濾器

全局過濾器就是若是有多個vm實例的話,全部的VM實例均可以使用。

全局過濾器書寫在 script直接標籤下。

而私有過濾器書寫在VM對象中:

注意:過濾器的調用原則是就近原則,即先調用私有過濾器再調用全局過濾器。

padStart和padEnd

// ctime 過濾器
Vue.filter('ctimeFormat', (data) => {
    let time = new Date(data);

    let year = time.getFullYear();
    let month = (time.getMonth() + 1).toString().padStart(2, '0');
    let day = (time.getDate()).toString().padStart(2, '0');
    let hour = (time.getHours()).toString().padStart(2, '0');
    let minute = (time.getMinutes()).toString().padStart(2, '0');
    let second = (time.getSeconds()).toString().padStart(2, '0');

    return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
});

使用ES6中的字符串新方法 String.prototype.padStart(maxLength, fillString='')String.prototype.padEnd(maxLength, fillString='')來填充字符串;

padStart:從開頭填充

padEnd:從結尾填充

maxLength:填充後最大的長度

fillString:須要填充的字符串(fillString='',不填則以空字符填充)

3、按鍵修飾符

咱們如今有個需求就是輸入ID和name後不點擊add按鈕,而是按下回車鍵也須要添加到列表中。

咱們能夠在name輸入框中加入按鍵擡起事件,而且指定是enter鍵擡起時才觸發。

<label for="name">
  name:
  <input type="text" id="name" v-model="name" @keyup.enter="addClick">

.enter : 就是按鍵修飾符。

系統提供的按鍵修飾符有:

  • .enter
  • .tab
  • .delete (捕獲「刪除」和「退格」鍵)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

若是咱們想自定義其餘的按鍵怎麼辦呢?

經過Vue.config.keyCodes.f2 = 113; ;能夠將f2做爲按鍵修飾符添加到系統按鍵修飾符中。

具體每一個按鍵的值是多少?下面是常見的按鍵的碼。

keyCode 8 = BackSpace BackSpace
keyCode 9 = Tab Tab
keyCode 12 = Clear
keyCode 13 = Enter
keyCode 16 = Shift_L
keyCode 17 = Control_L
keyCode 18 = Alt_L
keyCode 19 = Pause
keyCode 20 = Caps_Lock
keyCode 27 = Escape Escape
keyCode 32 = space
keyCode 33 = Prior
keyCode 34 = Next
keyCode 35 = End
keyCode 36 = Home
keyCode 37 = Left
keyCode 38 = Up
keyCode 39 = Right
keyCode 40 = Down
keyCode 41 = Select
keyCode 42 = Print
keyCode 43 = Execute
keyCode 45 = Insert
keyCode 46 = Delete
keyCode 47 = Help
keyCode 48 = 0 equal braceright
keyCode 49 = 1 exclam onesuperior
keyCode 50 = 2 quotedbl twosuperior
keyCode 51 = 3 section threesuperior
keyCode 52 = 4 dollar
keyCode 53 = 5 percent
keyCode 54 = 6 ampersand
keyCode 55 = 7 slash braceleft
keyCode 56 = 8 parenleft bracketleft
keyCode 57 = 9 parenright bracketright
keyCode 65 = a A
keyCode 66 = b B
keyCode 67 = c C
keyCode 68 = d D
keyCode 69 = e E EuroSign
keyCode 70 = f F
keyCode 71 = g G
keyCode 72 = h H
keyCode 73 = i I
keyCode 74 = j J
keyCode 75 = k K
keyCode 76 = l L
keyCode 77 = m M mu
keyCode 78 = n N
keyCode 79 = o O
keyCode 80 = p P
keyCode 81 = q Q at
keyCode 82 = r R
keyCode 83 = s S
keyCode 84 = t T
keyCode 85 = u U
keyCode 86 = v V
keyCode 87 = w W
keyCode 88 = x X
keyCode 89 = y Y
keyCode 90 = z Z
keyCode 96 = KP_0 KP_0
keyCode 97 = KP_1 KP_1
keyCode 98 = KP_2 KP_2
keyCode 99 = KP_3 KP_3
keyCode 100 = KP_4 KP_4
keyCode 101 = KP_5 KP_5
keyCode 102 = KP_6 KP_6
keyCode 103 = KP_7 KP_7
keyCode 104 = KP_8 KP_8
keyCode 105 = KP_9 KP_9
keyCode 106 = KP_Multiply KP_Multiply
keyCode 107 = KP_Add KP_Add
keyCode 108 = KP_Separator KP_Separator
keyCode 109 = KP_Subtract KP_Subtract
keyCode 110 = KP_Decimal KP_Decimal
keyCode 111 = KP_Divide KP_Divide
keyCode 112 = F1
keyCode 113 = F2
keyCode 114 = F3
keyCode 115 = F4
keyCode 116 = F5
keyCode 117 = F6
keyCode 118 = F7
keyCode 119 = F8
keyCode 120 = F9
keyCode 121 = F10
keyCode 122 = F11
keyCode 123 = F12
keyCode 124 = F13
keyCode 125 = F14
keyCode 126 = F15
keyCode 127 = F16
keyCode 128 = F17
keyCode 129 = F18
keyCode 130 = F19
keyCode 131 = F20
keyCode 132 = F21
keyCode 133 = F22
keyCode 134 = F23
keyCode 135 = F24

示例:

<input type="text" id="name" v-model="name" @keyup.f2="addClick">
  
 //...
  
<script>
    Vue.config.keyCodes.f2 = 113;
</script>

4、自定義指令

除了核心功能默認內置的指令 (v-model 等),Vue 也容許註冊自定義指令。自定義指令是以 v-開頭的指令。

好比咱們想讓品牌管理案例中,在剛進入頁面的時候,就獲取 Query輸入框的焦點,可是vue並無提供這樣的指令。

以前咱們能夠經過獲取DOM元素,而後使用 DOM元素.focus(); 方法來獲取焦點。可是在vue裏面不推薦獲取DOM元素的方式。這時咱們可使用自定義指令的方式來達到獲取焦點。

好比:咱們想定義一個v-focus 的指令來獲取焦點。

<label for="sel">
  Query:
  <input type="text" id="sel" v-model="keywords" v-focus>
</label>

<script>
    // 自定義全局指令 v-focus,爲綁定的元素自動獲取焦點:
        Vue.directive('focus', {
            inserted: function (el) { // inserted 表示被綁定元素插入父節點時調用
                el.focus();
            }
        });
</script>

一、定義自定義指令的時候,不須要加v- ,使用的時候須要加。

二、注意: 在每一個 函數中,第一個參數,永遠是 el ,表示 被綁定了指令的那個元素,這個 el 參數,是一個原生的JS對象。

三、和JS行爲有關的操做,最好在 inserted 中去執行

一、鉤子函數

inserted 是鉤子函數,相似的鉤子函數還有幾個,可是應用場景不一樣:

  • inserted :被綁定元素插入DOM元素時調用一次(從內存渲染到頁面時若是綁定了 inserted 就執行)。
  • bind:只調用一次,指令第一次綁定到元素時調用。在這裏能夠進行一次性的初始化設置(在代碼加載到內存中的時候,若是綁定了bind就執行,好比樣式style的設定,使用bind綁定)。
  • update:所在組件的 VNode 更新時調用,可是可能發生在其子 VNode 更新以前。指令的值可能發生了改變,也可能沒有。

總結:通常:

一、與JS行爲相關的操做在inserted中執行;

二、與樣式相關的在bind中執行。

二、鉤子函數參數

指令鉤子函數會被傳入如下參數:

  • el:指令所綁定的元素,能夠用來直接操做 DOM 。
  • binding:一個對象,包含如下屬性:
    • name:指令名,不包括 v- 前綴。
    • value:指令的綁定值,例如:v-my-directive="1 + 1" 中,綁定值爲 2
    • expression:字符串形式的指令表達式。例如 v-my-directive="1 + 1" 中,表達式爲 "1 + 1"
    • ...
  • ...

咱們能夠爲自定義指令賦值,好比咱們想給Query文本框的字體顏色賦值:

<label for="sel">
  Query:
  <input type="text" id="sel" v-model="keywords" v-focus v-color="'red'">
</label>

之因此使用v-color="'red'",而不是v-color="red",是由於若是是red字符串的話,就當作變量在vue的data中查找,而這裏要表達的是字符串red。

自定義v-color指令:

Vue.directive("color", {
  bind(el, binding) {
    el.style.color = binding.value;
  }
});

binding:這個名稱能夠隨意。

三、自定義私有指令

自定義私有指令就是在vm實例中加入 directives 屬性,它是一個對象,其中屬性爲自定義指令的名稱(不加 v-),值也是一個對象,對象裏面是鉤子函數列表。

var vm = new Vue({
  el: "#app",
  data: {
    //...
  },
  methods: {
    //...
  },
  directives: {
    "color": {
      bind(el, binding) {
        el.style.color = binding.value;
      }
    }
  }
});

四、自定義指令的簡寫

咱們以前都是在自定義指令名稱的後面跟上一個對象,裏面寫上 bind,inserted,update的鉤子函數列表。

如今簡寫的話,就不須要跟上一個對象了:

directives: {
  "color": (el, binding) => {
    el.style.color = binding.value;
  }
}

自定義名稱後能夠直接跟上一個匿名函數,這個匿名函數就至關於bind和update的鉤子函數集合。因此,若是你只須要在bind或者update中進行元素的設置的話,就能夠用這種簡寫的方式,固然若是是inserted的話,仍是要寫回對象的方式。

相關文章
相關標籤/搜索