深入自定义事件和原生DOM事件($attr等)

76 篇文章 2 订阅
26 篇文章 2 订阅

深入自定义事件和原生DOM事件

自定义事件

  1. 在组件上标签上添加的事件就是自定义事件,不管系统是否带这些事件

  2. 比如添加<自定义组件 @自定义事件 = "回调函数"></自定义组件> 那么@自定义事件在自定义组件上就是自定义事件

  3. <自定义组件 @click = "回调函数"></自定义组件>,那么@click就是自定义事件

  4. 添加的事件如果没有传入参数,那么输出就是undefined

  • 如图,传入了参数,单击button,输出为10,如果没有传递参数10,则输出undefined

  1. 自定义组件上绑定原生DOM事件使用native和不使用的区别,如下图
  • 如图

自定义事件示例

App.vue

<template>
  <div id="app">
    <!-- 给自定义组件绑定自定义事件为click事件,并将事件的回调函数绑定在事件check上 -->
    <MyComponent @click="check"></MyComponent>
  </div>
</template>

<script>
import MyComponent from '@/components/MyComponent'
export default {
  name: 'App',
  components: {
    MyComponent,
  },
  methods:{
    //给自定义组件绑定的自定义事件
    check(event){
      console.log("event",event);
    }
  }
}
</script>

自定义组件MyComponent

<template>
  <div class="my">
    这是我的组件
    <!-- 用于触发给其绑定的自定义事件 -->
    <button @click="chufa">触发自定义事件</button>
  </div>
</template>

<script>
export default {
  name: 'MyComponent',
  methods:{
    //触发自定义事件click,并传入一个参数100
    chufa(){    
        this.$emit("click",1000);
    }
  }
}
</script>

<style  scoped>
    .my{
        border: 1px solid red;
    }
</style>

效果

原生DOM事件

  1. 在HTML标签上添加就是原生DOM事件,比如说@click @mousemove这些系统自带的原生事件

  2. 添加的事件如果没有传入参数,那么系统会默认传入event参数

    <button @click="test1">我是按钮1</button>
    //等同于
    <button @click="test1($event)">我是按钮2</button>
    

vue自定义的事件在html标签和组件标签上的区别

  1. 在html标签上添加自定义事件无意义,所以自定义事件是给组件标签添加的

  2. 事件名可以任意,也可以和原生DOM事件名相同,但是是自定义的

  3. 如果自定义事件上想绑定原生的事件,那么就需要在事件对象名称后面添加 .native 并且绑定的事件添加在添加到组件根元素上,通过委派的形式使得子元素可以被触发

  • 如图

深入理解v-model

  1. 首先我们需要知道v-model在HTML标签上的原理

  2. v-model原来写法

    // 标准v-model写法 普通写法
    <input type="text" v-model="msg" />
    
  3. v-model拆解写法(等同于上方直接写v-model)

    • 先使用v-bind绑定一个值给输入框,再添加事件@input,当触发就将当前触发对象的值传递给v-bind绑定的那个值,就这样子完成了数据更新
    // v-model拆解写法
    <input type="text" :value="msg" @input="msg = $event.target.value"/>
    

那么v-model当中在自定义组件要怎么实现呢?

  • 根据v-model在原生DOM上拆解的写法,我们应该这样子写( 以自定义组件CustomInput为例 )

  • 需要知道的是: 在自定义组件当中,$event就是$emit当中第二个参数传递过来的数据

  • 组件

    <!--父亲给CustomInput传递 "msg2" 数据  -->
    <!--儿子要使用props接收( props:["value"] ),并且传递了自定义事件input -->
    <CustomInput :value="msg" @input="msg = $event"></CustomInput>
    <!--上面这一行代码可以简写为下面这一行但是子组件不能简写-->
    <!--必须要写下面这些内容!!!!!!!!!!!!!! -->
    <CustomInput v-model="msg"></CustomInput>
    
  • 组件 CustomInput.vue

    <template>
    	<div>
            <input type="text" 
                   // 绑定从父亲传递过来的参数
                   :value = "value"
                   // 绑定原生DOM事件@input,输入框内容发生改变,就将改变的值作为$emit的第二个参数
    			   // 并通过$emit触发父亲给子组件的自定义事件input
                   @input="$emit('input',$event.target.value)"/>
        </div>
    </template>
    <script>
    	export default {
            name: "CustomInput",
            // 接收从父亲传递过来的:value="msg"的值
            // 如果是简写形式(<CustomInput v-model="msg"></CustomInput>)也是从value接收
            props:["value"]
        }
    </script>
    

.sync修饰符实现父子数据同步和.sync和v-model的区别

[需求]
父亲向儿子传递一个值叫money),儿子每次都花100块钱,要求儿子花了多少钱,爸爸那边可以同步
第一次(无效果) (直接传递数据给儿子, 儿子每次单击都花100块钱)
  • 父亲 (直接传递数据给儿子)

     <!-- 会弹出警告说数据不同步 --> 
    <Child :money="moneyFather"></Child>
    

    弹出警告

  • 儿子

    <template>
    	<span>小明每次花100</span>
    
    	<!-- 每次单击爸爸的钱就减少100 -->
    	<button @click="money = money - 100">单击我花钱</button>
    	
    	<!-- 显示爸爸剩余多少钱 -->
    	爸爸还剩 {{ money }}</template>
    
    <script>
    	export default {
            name:"Child",
            //接收父亲传递过来的信息,告诉了我现在父亲有多少钱
            props:["money"]
        }
    
    </script>
    
  • 结果

    • 儿子花钱按钮被单击,儿子当中的父亲的钱数量被改变,但是父亲兜兜里面的钱没有变化

第二次(有效果) 数据传递给儿子,但是儿子每次单击花钱的时候就告诉父亲我花钱了
  • 父亲 ($event在自定义组件当中是$emit传递的参数 父亲收到儿子传递过来的金钱数,就更新自己的金钱数)

    <!-- $event在自定义组件当中是$emit传递的参数 -->
    <!-- @update:xxx为固定格式,不可以更改,xxx为绑定的数据属性也就是v-bind:xxx="值"(当中的xxx) 
    	对应简写属性 :xxx="值" 当中的xxx
    -->
    <Child :money="moneyFather" @update:money="moneyFather = $event"></Child>
    
  • 儿子每次单击爸爸的钱就减少100 并且告诉爸爸 (通过$emit),并且传递 金钱-100的 值 给父亲

    <template>
      <div style="background: #ccc; height: 50px">
        <span>小明每次花100</span>
    
        <!-- 每次单击爸爸的钱少100 并且告诉爸爸 $emit,并且传递  金钱-100的值  给父亲-->
        <!-- update:money 为自定义事件名称 -->
        <button @click="$emit('update:money', money - 100)">花钱</button>
    
        <!-- 显示爸爸剩余多少钱 -->
        爸爸还剩 {{ money }}</div>
    </template>
    
    <script type="text/ecmascript-6">
    export default {
    
      name: "Child",
      
      // 接收父亲传递过来的信息,告诉了我现在父亲有多少钱
      props: ["money"],
    };
    </script>
    
    
第三次(有效果)等同于第二次简写
  • 父亲 (使用sync修饰符)

    
    <Child :money.sync="moneyFather"></Child>
    
    
  • 儿子 (和第二次一样) 每次单击爸爸的钱就减少100 并且告诉爸爸 (通过$emit),并且传递 金钱-100的 值 给父亲

    <template>
      <div style="background: #ccc; height: 50px">
        <span>小明每次花100</span>
    
        <!-- 每次单击爸爸的钱少100 并且告诉爸爸 $emit,并且传递  金钱-100的值  给父亲-->
        <!-- update:money 为自定义事件名称 -->
        <button @click="$emit('update:money', money - 100)">花钱</button>
    
        <!-- 显示爸爸剩余多少钱 -->
        爸爸还剩 {{ money }}</div>
    </template>
    
    <script type="text/ecmascript-6">
    export default {
    
      name: "Child",
      
      // 接收父亲传递过来的信息,告诉了我现在父亲有多少钱
      props: ["money"],
    };
    </script>
    
    

v-model的使用在数据同步的使用

  • 父亲依旧是通过:value向子传递 $event依旧是子通过$emit传递过来的数据

    • 自定义组件$event返回的都是$emit传递过来的数据)
    <Child :value="moneyFather" @input="moneyFather = $event"></Child>
    
  • 儿子

    <template>
      <div style="background: #ccc; height: 50px">
        <span>小明每次花100</span>
    
        <!-- 每次单击爸爸的钱少100 并且告诉爸爸 $emit,并且传递  金钱-100的值  给父亲-->
          
        <button @click="$emit('input', value - 100)">花钱</button>
    
        <!-- 显示爸爸剩余多少钱 -->
        爸爸还剩 {{ value }}</div>
    </template>
    
    <script type="text/ecmascript-6">
    export default {
    
      name: "Child",
      
      // 接收父亲传递过来的信息,告诉了我现在父亲有多少钱
      props: ["value"],
    };
    </script>
    
    

.sync和v-model在数据同步使用区别

  • v-model和.sync都可以实现父子组件数据同步,下面是约定成俗的规定
    • v-model 是当子组件当中有表单类元素的时候使用
    • .sync 是当子组件当中不是表单类元素的时候使用

自定义带hover提示的el-button和$attrs和$listeners的使用

  • 前置知识
    • el-button
      • 如果想带图标,那么添加icon属性可以,注意: icon属性里面的值都是以el-icon-xxx形式出现的
      • element-ui的icon库
  • 原来的el-button组件并没有鼠标悬停上去就出现提示的功能,我们可以通过对el-button进行再次包装

简易的包装(但是不能达到自己去传入配置设置的要求)

  • 如图 MyButton.vue对el-button进行包装

    <template>
    	<a title="这个是提示框">
        	<el-button></el-button>
        </a>
    </template>
    
  • 包装后的使用

    <template>
    	<div>
            <h2>自定义带Hover提示的按钮</h2>
            <!-- 使用二次封装后的 -->
            <MyButton></MyButton>
        </div>
    </template>
    <script>
        <!-- 引入二次封装后的el-button组件 -->
    	import MyButton from "./myButton.vue"
    	export default {
            name:"AttrsListenersTest",
            <!-- 注册使用自定义组件 -->
            componets:{
                MyButton
            }
        }
    </script>
    
  • 效果图

使用$attrs和$listeners进行复杂包装(可自定义参数效果)

  • 前面要知道的

    • 同等效果
      • 传递数据给组件,可以使用 :key="value" 或者 直接省略 : ,直接写 key= “value” 也是可以的,不过有冒号的 :key="value" value为js代码,没有冒号的 key=“value” value值为字符串!!
    <MyButton aa="10"></MyButton>
    <!-- 上一行和下一行是同等效果 -->
    <MyButton aa="10"></MyButton>
    
    • 不同等效果

      <!-- 传递字符串 "b" -->
      <MyButton aa="b"></MyButton>  
      
      <!-- 传递变量b的值,即为10 -->
      <MyButton aa="b"></MyButton>
      
      <script>
          <!-- 引入二次封装后的el-button组件 -->
      	import MyButton from "./myButton.vue"
      	export default {
              name:"AttrsListenersTest",
      		data(){
                return {
                    b:10
                }  
              },     
              <!-- 注册使用自定义组件 -->
              componets:{
                  MyButton
              }
          }
      </script>
      
      
  • $attrs 获取传递给组件的所有属性,它会排除 props已经声明接收的属性 以及class,style这二个样式

    • 如图

  • 排除props接收到了的

    • 如图

  • $listeners 获取父组件传递给子组件的所有自定义事件监听组成的对象

    • 如图

  • $attrs$listeners一键绑定在组件上

    • 可以通过v-bind一次性把父组件传递过来的属性添加给子组件(v-bind不可以简写为:)
    • 可以通过v-on 一次性把父组件传递过来的事件监听添加给子组件(v-on不可以简写@)
    • 如图

$children和$parent和$refs的使用

  • this.$refs放在HTML和组件标签身上的区别
    • this.$refs.名称 放在html标签身上拿到的就是这个DOM元素
    • this.$refs放在组件标签身上拿到的就是组件对象本身

this.$refs妙用

  • 可以直接通过this.$refs.名称来获取组件,并且在组件当中去操作这个获取到的组件里面的数据

    如图所示(父亲) 父亲直接通过this.$refs.son.money就操控了儿子和女儿的钱

$children 和 $parent的妙用

$parent

  • 前提:

    • 必须只有一个父亲才可以使用!如果这个组件有多个父亲,那么就不可以用!(为什么有多个父亲,因为存在组件复用的情况!)
  • 如图,儿子通过 this.$parent.money 来获取父亲的钱并且修改

$children

  • 获取当前组件的所有的子组件,返回子组件的数组,(无顺序,不能说[0]一定就是儿子,[1]就一定是女儿)

  • 如图

本案例当中,均在配置对象当中书写了data数据

mixin混入的基本使用

  • @官方API:混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。

  • 说通俗点就是混入就是将别人的东东变为自己的东东,这里的混入只说一些基本的使用

  • 先来看示例吧

mixin/test.js文件的代码

const mixins = {
  data(){
    return {
      sex:"男",
      age:"18",
    }
  },
  methods:{
    sayHello(){
      console.log("你好,世界");
    }
  }
};
export default mixins;

App.vue

使用mixin/test.js的混入

<template>
  <div>
    <div>姓名:{{name}}</div>
    <div>年龄:{{sex}}</div>
    <div>性别:{{age}}</div>
    <button @click="sayHello">单击我 - 说hello</button>
    <button @click="sayThankyou">单击我 - 说谢谢</button>
  </div>
</template>

<script>
// 引入混入
import myMixin from "@/mixin/test";
export default {
  name: "",
    //使用混入
  mixins:[myMixin],
  data() {
    return {
      name:"李白",
    }
  },
  methods:{
    sayThankyou(){
      console.log("谢谢你");
    }
  }

};
</script>

功能测试是否正常,可以看到,可以正常显示和调用函数

  • 当然了,还有很多情况,比如说混入的时候,当mixin/test.js里面的数据或者方法和App.vue当中的数据或者方法冲突的时候要怎么解决之类的,具体看官网吧~ @官网

之前做的一个混入的图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

未成年梦想

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值