v-model在自定義組件中的使用

前段時間出來面試,有一個面試?yán)蠋焼栁?code>v-model是什么施籍,我回答說其實是組件里props中的value的值和往父組件$emit事件input的語法糖實現(xiàn)。

<template>
  <input type='text' :value='inputValue' @input='changeValue($event)'>
</template>

<script>
  export default {
    data(){
      return {
        inputValue: 'aaa',
      }
    },
    methods: {
      changeValue(e){
        this.inputValue = e.target.value;
      }
    }
  }
</script>

一般能夠說出這個說明整體對vue的使用已經(jīng)達(dá)到了熟悉的級別,本以為回答完這些后關(guān)于v-model的問題算是完滿結(jié)束了捐川,沒成想面試?yán)蠋熒衩氐奈⑽⒁恍ψ耆鳎瑔柍隽讼旅娴膯栴}:

如果你的自定義組件里value屬性被占用了的話奋姿,如何實現(xiàn)v-model的功能?

聽到這個問題我立馬黑人問號臉素标!

這種問題沒法顧左右而言它称诗,只能老老實實說木雞啊。

現(xiàn)在面試雖然結(jié)束了头遭,但問題并沒有結(jié)束寓免!如何在自定義組件中value被占用的情況下實現(xiàn)v-model的功能?這問題只要一有閑暇便會浮現(xiàn)出來计维,看來是必須解決了袜香!

老規(guī)矩,翻vue官檔享潜,每次看文檔的時候總會有一種以前看的假文檔的錯覺困鸥,在表單輸入綁定這塊,翻出了一些關(guān)于v-model的內(nèi)容。

基礎(chǔ)用法

你可以用 v-model 指令在表單 <input>疾就、<textarea><select> 元素上創(chuàng)建雙向數(shù)據(jù)綁定澜术。它會根據(jù)控件類型自動選取正確的方法來更新元素。盡管有些神奇猬腰,但v-model本質(zhì)上不過是語法糖鸟废。它負(fù)責(zé)監(jiān)聽用戶的輸入事件以更新數(shù)據(jù),并對一些極端場景進(jìn)行一些特殊處理姑荷。

v-model 會忽略所有表單元素的 value盒延、checkedselected 特性的初始值而總是將 Vue 實例的數(shù)據(jù)作為數(shù)據(jù)來源鼠冕。你應(yīng)該通過 JavaScript 在組件的 data 選項中聲明初始值添寺。

v-model 在內(nèi)部為不同的輸入元素使用不同的屬性并拋出不同的事件:

  • texttextarea 元素使用 value 屬性和 input 事件;
  • checkboxradio 使用 checked 屬性和 change 事件懈费;
  • select 字段將 value 作為 prop 并將 change 作為事件计露。

對于需要使用輸入法 (如中文、日文憎乙、韓文等) 的語言票罐,你會發(fā)現(xiàn) v-model 不會在輸入法組合文字過程中得到更新。如果你也想處理這個過程泞边,請使用 input 事件该押。

基礎(chǔ)用法解析

在框架越來越盛行的時代,大部分人對原生htmljs的理解越來越模糊阵谚,為了徹底理解上面基礎(chǔ)用法說的是什么蚕礼,我決定用htmljs對這些valuechecked椭蹄、selected之類的東西再熟悉一遍闻牡。

  1. <input>元素的value屬性和input事件。
      <input value='測試' onInput='changeValue(event)'/>
    
      function changeValue(e){
        console.log(e.target.value);
      }
    

value對應(yīng)的值為輸入框的值绳矩,input事件為輸入框的值改變時發(fā)生的事件(js直接修改value值不會觸發(fā))罩润。

假裝不知道vue中可以對input直接使用v-model,那么自己封裝的組件如下:

<template>
  <input ref='input' @input='changeValue'/>
</template>

<script>
export default {
  name: 'model-input',
  mounted(){
    this.$refs.input.value = this.value;
  },
  props: {
    value: String,
  },
  methods: {
    changeValue(e){
      this.$emit('input',e.target.value);
    }
  },
  watch: {
    value(newVal){
      if(this.$refs.input.value !== newVal) this.$refs.input.value = newVal;
    }
  }
}
</script>
  1. 單選復(fù)選checked屬性和change事件翼馆。
  <input type='radio' name='fruits' id='apple' value='apple' onChange='chooseFruit(event)'>
  <label for='apple'>蘋果</label>
  <input type='radio' name='fruits' id='banana' value='banana' onChange='chooseFruit(event)' checked>
  <label for='banana'>香蕉</label>
  function chooseFruit(e){
    console.log(e.target.checked);
  }

checked為選中項割以,change事件為選中項發(fā)生改變時的事件。

  1. <select>元素的value屬性和change事件应媚。
<select id='carBrand' onChange='selectBrand(event)'>
  <option value="volvo">Volvo</option>
  <option value="saab">Saab</option>
  <option value="opel">Opel</option>
  <option value="audi">Audi</option>
</select>
function selectBrand(e){
  console.log(e.target.value);
}

<select>value值為選中的<option>value值严沥,change為選中項發(fā)生改變時的事件(老規(guī)矩,js直接改變的不會觸發(fā))中姜。

自定義組件上使用v-model

<template>
  <div>
    <span>{{num}}</span>
    <button @click='addNum'>增加</button>
  </div>
</template>

<script>
  export default {
    data(){
      return {
        num: null,
      }
    },
    props: {
      value: Number,
    },
    mounted(){
      this.num = this.value;
    },
    methods: {
      addNum(){
        this.$emit('input',++ this.num);
      }
    },
    watch: {
      value(newVal){
        if(this.num !== newVal) this.num = newVal;
      }
    }
  }
</script>

以上便是是自定義組件上使用v-model的一般方法消玄。

到此處跟伏,似乎還是沒有解決面試?yán)蠋焼柕哪莻€問題,別急翩瓜,翻翻官檔受扳,發(fā)現(xiàn)可以設(shè)置model配置來自定義v-model相關(guān)的變量值和事件。上面自定義組件可調(diào)整如下依舊可以正常使用v-model兔跌。

<template>
  <div>
    <span>{{num}}</span>
    <button @click='addNum'>增加</button>
  </div>
</template>

<script>
  export default {
    data(){
      return {
        num: null,
      }
    },
    props: {
      notValue: Number,
    },
    model: {
      prop: 'notValue',
      event: 'notInput',
    },
    mounted(){
      this.num = this.notValue;
    },
    methods: {
      addNum(){
        this.$emit('notInput',++ this.num);
      }
    },
    watch: {
      notValue(newVal){
        if(this.num !== newVal) this.num = newVal;
      }
    }
  }
</script>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末勘高,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子坟桅,更是在濱河造成了極大的恐慌华望,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件仅乓,死亡現(xiàn)場離奇詭異赖舟,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)夸楣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進(jìn)店門建蹄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人裕偿,你說我怎么就攤上這事⊥吹ィ” “怎么了嘿棘?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長旭绒。 經(jīng)常有香客問我鸟妙,道長,這世上最難降的妖魔是什么挥吵? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任重父,我火速辦了婚禮,結(jié)果婚禮上忽匈,老公的妹妹穿的比我還像新娘房午。我一直安慰自己,他們只是感情好丹允,可當(dāng)我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布郭厌。 她就那樣靜靜地躺著,像睡著了一般雕蔽。 火紅的嫁衣襯著肌膚如雪折柠。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天批狐,我揣著相機(jī)與錄音扇售,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛承冰,可吹牛的內(nèi)容都是我干的华弓。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼巷懈,長吁一口氣:“原來是場噩夢啊……” “哼该抒!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起顶燕,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤凑保,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后涌攻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體欧引,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年恳谎,在試婚紗的時候發(fā)現(xiàn)自己被綠了芝此。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡因痛,死狀恐怖婚苹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情鸵膏,我是刑警寧澤膊升,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站谭企,受9級特大地震影響廓译,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜债查,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一非区、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧盹廷,春花似錦征绸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至颠放,卻和暖如春排惨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背碰凶。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工暮芭, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留鹿驼,地道東北人。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓辕宏,卻偏偏與公主長得像畜晰,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子瑞筐,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 主要還是自己看的凄鼻,所有內(nèi)容來自官方文檔。 介紹 Vue.js 是什么 Vue (讀音 /vju?/聚假,類似于 vie...
    Leonzai閱讀 3,329評論 0 25
  • vue概述 在官方文檔中块蚌,有一句話對Vue的定位說的很明確:Vue.js 的核心是一個允許采用簡潔的模板語法來聲明...
    li4065閱讀 7,187評論 0 25
  • 以下內(nèi)容是我在學(xué)習(xí)和研究Vue時,對Vue的特性膘格、重點和注意事項的提取峭范、精練和總結(jié),可以做為Vue特性的字典瘪贱; 1...
    科研者閱讀 14,048評論 3 24
  • 原教程內(nèi)容詳見精益 React 學(xué)習(xí)指南纱控,這只是我在學(xué)習(xí)過程中的一些閱讀筆記,個人覺得該教程講解深入淺出菜秦,比目前大...
    leonaxiong閱讀 2,810評論 1 18
  • Vue.js是一個很優(yōu)秀的前端框架甜害,熟練運(yùn)用可以幫助您快速搭建各種應(yīng)用。如何理解Vue.js教程中的“使用自定義事...
    daling菜鳥閱讀 1,274評論 1 3