Vue 2.0 入門系列(11)雙向綁定其餘元素以及自定義表單控件

以前咱們學過用 v-model 進行雙向數據綁定:css

<div id="root">
    <textarea class="textarea" v-model="comment"></textarea>
</div>

<script>

    var vm = new Vue({
        el:"#root",
        data:{
            comment:"這是一條評論"
        }
    });

</script>

並且,提到過,v-model 只能用於表單控件,若是用於其餘元素,好比 p:html

<p contenteditable="true" v-model="comment"></p>

那麼就會報錯:vue

v-model is not supported on this element type. If you are working with contenteditable, it's recommended to wrap a library dedicated for that purpose inside a custom component.ajax

它會提示用 custom component,即自定義組件。在使用自定義組件以前,先來看看 v-model 的另一種等價寫法:ide

<textarea :value="comment" @input="comment = $event.target.value"></textarea>

該過程很好理解,首先,動態綁定輸入控件的 value 屬性到 comment 變量上,而後對 input 事件進行監控,實時同步 comment 的值。this

若是用這種寫法,就能夠對 p 等元素進行雙向綁定了。因爲 p 元素沒有 value 屬性,能夠使用 v-text 或者插值:spa

<p contenteditable="true" @input="comment = $event.target.innerText">{{ comment }}</p>

或者:雙向綁定

<p contenteditable="true" v-text="comment" @input="comment = $event.target.innerText"></p>

如今,咱們對評論的內容進行過濾,效果以下:code

clipboard.png

能夠使用自定義組件,好比:component

<comment v-model="comment"></comment>

如何讓組件的 v-model 生效呢?須要按照 Vue 的約定:

  1. 接受一個 value 屬性

  2. 在有新的 value 時觸發 input 事件

跟咱們以前的寫法相似:

Vue.component('comment',{
    props:['value'],
    template:`
        <textarea :value="value" @input="filterComment($event.target.value)"></textarea>
    `,
    methods: {
        filterComment(comment){
            this.$emit('input',comment)
        }
    }
});

這樣就能夠實現簡單的雙向綁定了,並且咱們能夠在 filterComment 方法中定義過濾規則:

filterComment(comment){
    var filterRst = (comment.indexOf('敏感詞') >= 0 ? comment.replace(\敏感詞\g,"河蟹") : comment);
    this.$emit('input',filterRst)
}

完整示例:

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="https://cdn.bootcss.com/vue/2.2.6/vue.js"></script>
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.4.1/css/bulma.css">
</head>
<body>
    <div id="root" class="container">
        <comment v-model="comment"></comment>
    </div>

    <script>
        Vue.component('comment',{
            props:['value'],
            template:`
                <textarea class="textarea" :value="value" @input="filterComment($event.target.value)"></textarea>
            `,
            data(){
                return {
                    sensitiveList:['包子','蛤蛤'],
                    replaceWord:'河蟹'
                }
            },
            methods: {
                filterComment(comment){
                    var that = this;
                    this.sensitiveList.forEach(function(word){
                        var regex = new RegExp(word,'g');;
                        comment = (comment.indexOf(word) >= 0 ? comment.replace(regex,that.replaceWord) : comment);
                    })
                    this.$emit('input',comment)
                }
            }
        });
    
        var vm = new Vue({
            el:"#root",
            data:{
                comment:'這是一條評論'
            }
        });
    </script>
    
</body>
相關文章
相關標籤/搜索