zoukankan      html  css  js  c++  java
  • Vue3手册译稿

    本章节需要掌握组件基础
    emit我译成发射,觉得发射这个词比较形象的形容将子组件事件发射出来的一个动作。

    事件名

    像组件和props,事件名也会进行自动转换,如果你在子组件里发射一个驼峰命名的事件,你就可以在父组件中添加一个短横线分隔的监听:

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

    因为有props情形存在,模板内DOM议使用短横线分隔命名方式。如果你使用字符串模板,则不存在这个限制。

    自定义事件定义

    Vue School自定义事件视频教程

    自定义事件发射(请子组件传递到父组件)可以通过emits选项:

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

    当在emits中定义了一个原生事件(如click)时,组件事件将会代替原生事件监听。

    提示
    推荐定义所有已发射的事件,以便记录组件是如何工作的

    验证已射事件

    prop类型验证一样,一个已发射事件如果通过对象语法而不是数组语法,也可以被验证。
    添加一个验证,事件会分配一个函数来接收参数,并传递给$emit调用,返回一个布尔值来确认事件是否有效。

    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修改这些名称:

    <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 {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 }
      }
    })
    
  • 相关阅读:
    对var和let作用域用闭包的特性做最好的解释
    Js函数作用域
    问题记录
    Git学习
    React-router BrowserRouter导致axios请求时会重复url中的某些字段
    leetcode python 032 识别最长合法括号
    leetcode python 030 Substring with Concatenation of All Words
    n阶楼梯,一次走1,2,3步,求多少种不同走法
    leetcode python 012 hard 合并k个有序链表
    leetcode python 011
  • 原文地址:https://www.cnblogs.com/zhouyu629/p/14539610.html
Copyright © 2011-2022 走看看