Vue3手冊譯稿 - 深刻組件 - 自定義事件

本章節須要掌握組件基礎
emit我譯成發射,以爲發射這個詞比較形象的形容將子組件事件發射出來的一個動做。javascript

事件名

像組件和props,事件名也會進行自動轉換,若是你在子組件裏發射一個駝峯命名的事件,你就能夠在父組件中添加一個短橫線分隔的監聽:css

this.$emit('myEvent')
<my-component @my-event="doSomething"></my-component>

由於有props情形存在,模板內DOM議使用短橫線分隔命名方式。若是你使用字符串模板,則不存在這個限制。html

自定義事件定義

Vue School自定義事件視頻教程vue

自定義事件發射(請子組件傳遞到父組件)能夠經過emits選項:java

app.component('custom-form', {
  emits: ['inFocus', 'submit']
})

當在emits中定義了一個原生事件(如click)時,組件事件將會代替原生事件監聽。api

提示
推薦定義全部已發射的事件,以便記錄組件是如何工做的數組

驗證已射事件

prop類型驗證同樣,一個已發射事件若是經過對象語法而不是數組語法,也能夠被驗證。
添加一個驗證,事件會分配一個函數來接收參數,並傳遞給$emit調用,返回一個布爾值來確認事件是否有效。app

app.component('custom-form', {
  emits: {
    // 無驗證
    click: null,

    // 驗證提交事件
    submit: ({ email, password }) => {
      if (email && password) {
        return true
      } else {
        console.warn('不合法的 submit 事件加載!')
        return false
      }
    }
  },
  methods: {
    submitForm() {
      this.$emit('submit', { email, password })
    }
  }
})

v-model參數

默認組件的v-model使用modelValue做爲prop和update:modelValue做爲事件。咱們能夠傳遞一個參數給v-model修改這些名稱:less

<my-component v-model:title="bookTitle"></my-component>
app.component('my-component', {
  props: {
    title: String
  },
  emits: ['update:title'],
  template: `
    <input
      type="text"
      :value="title"
      @input="$emit('update:title', $event.target.value)">
  `
})

在這個案例中,子組件會同步接收titleprop,發射update:title事件:函數

app.component('my-component', {
  props: {
    title: String
  },
  emits: ['update:title'],
  template: `
    <input
      type="text"
      :value="title"
      @input="$emit('update:title', $event.target.value)">
  `
})
<my-component v-model:title="bookTitle"></my-component>

v-model綁定

正如前面所學習v-model參數,咱們能夠爲同一個組件實例添加多個v-model參數。
每一個v-model能夠與不一樣的prop相同步,組件不須要額外的選項:

<user-name
  v-model:first-name="firstName"
  v-model:last-name="lastName"
></user-name>
app.component('user-name', {
  props: {
    firstName: String,
    lastName: String
  },
  emits: ['update:firstName', 'update:lastName'],
  template: `
    <input
      type="text"
      :value="firstName"
      @input="$emit('update:firstName', $event.target.value)">

    <input
      type="text"
      :value="lastName"
      @input="$emit('update:lastName', $event.target.value)">
  `
})

咱們來寫一個完整點的例子,實現一個區號-座機輸入組件,結果以下圖:
image

代碼以下:

<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>component v-model</title>
	<script src="https://unpkg.com/vue@next"></script>
   </head>
   <body>
		<div id="app">
			<tel-input v-model:tel-number="telNumber" v-model:area-number="areaNumber"></tel-input>
			<p>
				{{areaNumber}}-{{telNumber}}
			</p>
		</div>
   </body>
   <script type="text/javascript">
	const data_and_methods = {
		data() {
			return {
				telNumber: '',
				areaNumber:  ''
			}
		},
		methods: {
			
		}
	}
	const app = Vue.createApp(data_and_methods)
	app.component('tel-input',{
		props: {
			areaNumber:String,
			telNumber:String
		},
		emits: ['update:areaNumber','update:telNumber'],
		template: `
			<input placeholder="區號" type="number" class="area-number" :value="areaNumber" @input="$emit('update:areaNumber',$event.target.value)" />
			-
			<input placeholder="座機號碼" type="number" class="tel-number" :value="telNumber" @input="$emit('update:telNumber',$event.target.value)" />
		`
	})
	
	app.mount("#app")
   </script>
   <style type="text/css">
		.area-number {width:60px;}
	</style>
</html>

處理v-model修飾符

在前面咱們學習輸入綁定時,v-model有一些內置的修飾符如.trim,.number,.lazy等。有些情形,你也想增長一些自定義的修飾符。
讓咱們來建立一個capitalize修飾符,使用v-model綁定將輸入首字母轉換爲大寫。
組件v-model修飾符經過modelModifersprop提供給組件。下面的例子,咱們建立了一個含有默認爲空對象 的modelModifiersprop組件。
注意在組件created生命週期勾子觸發器中,modelModifiersprop包含capitalize且值是true - 當它被設置在v-model綁定v-model.capitalize="myText"

<my-component v-model.capitalize="myText"></my-component>
app.component('my-component', {
  props: {
    modelValue: String,
    modelModifiers: {
      default: () => ({})
    }
  },
  emits: ['update:modelValue'],
  template: `
    <input type="text"
      :value="modelValue"
      @input="$emit('update:modelValue', $event.target.value)">
  `,
  created() {
    console.log(this.modelModifiers) // { capitalize: true }
  }
})

如今咱們設置好了prop,咱們檢測modelModifiers對象的鍵,而後經過方法處理要發射出去的值。下面咱們來把輸入框的首字母轉換爲大寫:

<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>component v-model modifiers</title>
	<script src="https://unpkg.com/vue@next"></script>
   </head>
   <body>
		<div id="app">
			<my-component v-model.capitalize="myText"></my-component>
			<p>{{ myText }}</p>
		</div>
   </body>
   <script type="text/javascript">
	const data_and_methods = {
		data() {
			return {
				myText: ''
			}
		}
	}
	const app = Vue.createApp(data_and_methods)
	app.component('my-component',{
		props: {
			modelValue: String,
			modelModifiers: {
				default: () => ({})
			}
		},
		emits: ['update:modelValue'],
		template: `
			<input type="text"
				:value="modelValue"
				@input="emitValue" />
		`,
		methods: {
			emitValue(e){
				let value = e.target.value
				if(this.modelModifiers.capitalize){
					value = value.charAt(0).toUpperCase() + value.slice(1)
				}
				this.$emit('update:modelValue',value)
			}
		},
		created() {
			console.log(this.modelModifiers)
		}
	})
	
	app.mount("#app")
   </script>
</html>

v-model綁定參數,生成的prop名將會是arg+"modelModifiers"

<my-component v-model:description.capitalize="myText"></my-component>
app.component('my-component', {
  props: ['description', 'descriptionModifiers'],
  emits: ['update:description'],
  template: `
    <input type="text"
      :value="description"
      @input="$emit('update:description', $event.target.value)">
  `,
  created() {
    console.log(this.descriptionModifiers) // { capitalize: true }
  }
})
相關文章
相關標籤/搜索