不管用哪種前端框架,一定少不了遇到 Checkbox 清單需求,之前寫過 KO 版,寫過 NG 版,如今改學 Vue,不寫個 Vue 版成何體統?

廢話少說,放碼過來!

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>Checkbox List Vue Component</title>
    <style>
        html,
        body {
            font-size: 9pt;
        }

        [v-cloak] {
            display: none;
        }

        fieldset { 
            width: 320px; 
            padding: 12px;
        }

        fieldset div { background-color: #eee; }
    </style>
</head>

<body>
    <div id="app" v-cloak>
        <fieldset>
            <legend>Checkbox List (string array options &amp; multi-select)</legend>
            <v-chkbox-list v-model="SelValues1" v-bind:items="StrArrayOptions"></v-chkbox-list>
            <div class="value-view">{{SelValues1}}</div>
        </fieldset>
        <fieldset>
            <legend>Checkbox List (value/text options &amp; exclusive choice)</legend>
            <v-chkbox-list v-model="SelValue2" v-bind:items="ValueTextArrayOptions" exclusive="true"></v-chkbox-list>
            <div class="value-view">{{SelValue2}}</div>
        </fieldset>
    </div>
    <script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.js"></script>
    <script>
        //實際應用時,元件會另存成 vue-components-filename.js 方便重複利用
        Vue.component('v-chkbox-list', {
            props: {
                value: Array,
                items: Array,
                exclusive: Boolean
            },
            template: '<span><label v-for="item in items">' +
                '<input type="checkbox" v-bind:value="item.value || item" />' + 
                '<span>{{item.text || item}}</span>&#160;&#160;</label></span>',
            mounted: function () {
                var self = this;
                var el = $(self.$el);
                el.find("input").each(function () {
                    if (self.exclusive) {
                        this.checked = this.value == self.value;
                    }
                    else {
                        this.checked = $.inArray(this.value, self.value) > -1;
                    }
                });
                el.on("change", "input[type=checkbox]", function () {
                    if (self.exclusive) {
                        $(this).closest("span").find("input").not(this).prop("checked", false);
                        self.$emit('input', this.value);
                    }
                    else {
                        var selValues = $.map(el.find(":checked"), function (cbx) {
                            return cbx.value;
                        });
                        self.$emit('input', selValues);
                    }
                });

            }
        });
    </script>
    <script>
        var vm = new Vue({
            el: "#app",
            data: {
                StrArrayOptions: ["Value1", "Value2", "Value3"],
                SelValues1: ["Value2"],
                ValueTextArrayOptions: [
                    { value: "Value1", text: "Text1" },
                    { value: "Value2", text: "Text2" },
                    { value: "Value3", text: "Text3" }
                ],
                SelValue2: "Value2"
            }
        });
    </script>
</body>
</html>

我選擇寫成 Vue Component,重點跟上一篇 Kendo UI 日期選擇器封裝元件講的大同小異,這裡不多贅述。選項來源支援兩種型別,一種直接給字串陣列,顯示文字等於選擇值;若二者不同,則可提供具有 value 及 text 屬性的物件陣列。選取方式則分為單選或多選,選取結果支援 v-model 繫結,單選時型別為字串、多選時則為字串陣列,用講的有點抽象,看示範比較快: 線上展示

[2020/9/21 補充:讀者 milkmidi 留言分享了更能發揮 Vue 特色的簡潔寫法,我的版本相較之下像是莽夫揮著 jQuery 斧頭硬幹(掩面),稍晚再補上我的學習心得]

Vue 3.0 正式版昨天發佈了,這篇用的還是 2.x 寫法(我計劃明年再升級現有專案,原因請參考昨天的文章),V3 寫法改天再來研究。

Writing a checkbox list as Vue component.


Comments

# by milkmidi

黑暗大大你好,我把你的exmaple小改一下,主要就是拿掉 jQuery, 讓 Code 更簡單一些 https://jsbin.com/vowuwek/15/edit?html,console,output

# by Jeffrey

to milkmidi, 謝謝分享,用 Vue v-model 取代 click 事件很酷,學習了。另外實測 IE11 不支援 template: `...`,但改回 '...' 就 OK 了。

# by milkmidi

忘了 ie11不支援template vue真的很好用

# by plastic

建議一下,目前Vue 2版應該到2.6,上面還是用2.0,然後是如果沒有用到Jquery UI或其他必須要Jquery的,裡面的內容應該是可以全換成 Vue 的

# by Jeffrey

to plastic,jquery 與 vue.js 我是用 JSBin 內建功能加上的,感謝提醒。milkmidi 有給了一個純 Vue 版範例,本案例的確可以完全不用 jQuery,之後再寫心得文。

Post a comment