113.【Vue-细刷-04】(二)

简介: 113.【Vue-细刷-04】

(二十五)、自定义事件 (父子组件)

1.A组件想让B组件给自己传递数据,那么就要给B组件绑定自定义事件。

2.自定义回调放在哪里,哪里就能够接收数据。非$emit()是自定义回调函数

1.儿子传递数据给父亲 (原始)

App.vue

<template>
  <div class="app">
    <h2>我是App组件</h2>
    <!-- 2. 父亲传递给儿子 -->
    <Demo :receive_son="receive_one"/>
    <h2>{{username}}</h2>
  </div>
</template>
<script>
import Demo from "./components/Demo.vue";
export default {
  name: "App",
  components: {
    Demo,
  },
  data() {
    return {
        username:'111'
    }
  },
  // TODO: 1.父亲创建一个接受儿子传递过来的方法
  methods: {
    receive_one(data_one){
        this.username=data_one;
    }
  }
};
</script>
<style>
.app{
    background-color: brown;
    padding: 10px;
}
</style>

Demo.vue 儿子

<template>
  <div class="demo">
    <h2 >我是Demo2组件</h2>
    <button @click="send_data">点我向父类传送数据</button>
  </div>
</template>
<script>
export default {
  name: "Demo",
  data() {
    return {
        name:'ckqn'
    }
  },
//  TODO: 1.儿子接受数据
    props:['receive_son'],
// TODO: 2.儿子创建方法传递给父亲
    methods:{
        send_data(){
            this.receive_son(this.name)
        }
    }
};
</script>
<style>
    .demo{
        background-color: antiquewhite;
    }
</style>

2.儿子传递数据给父亲 (自定义事件 $emit) ⭐

  • (适用于父子组件、不适用兄弟组件):

一般自定义事件都会放在组件上

1.给子组件自定义事件:自定义事件会放在子组件的vc上
<Demo @jsxs="test"/>
methods: {
    test(data_one){
        this.username = data_one
    }
  },

App.vue

<template>
  <div class="app">
    <h2>我是App组件</h2>
    <!-- 
        如下代码是给Demo的组件实列对象定义一个jsxs事件,只要Demo组件实列对象触发了jsxs事件,那么就调用test函数
        组件->一般添加的是自定义事件
     -->
    <Demo @jsxs="test"/>
    <h2>{{username}}</h2>
  </div>
</template>
<script>
import Demo from "./components/Demo.vue";
export default {
  name: "App",
  components: {
    Demo,
  },
  data() {
    return {
        username:'111'
    }
  },
  methods: {
    test(data_one){
        this.username = data_one
    }
  },
};
</script>
<style>
.app{
    background-color: brown;
    padding: 10px;
}
</style>

Demo.vue

2.子组件通过$emit向父亲传递数据 : 第一个参数是自定义事件名,后面的是参数无限制
    methods:{
        send_data(){
        // 当jsxs这个自定义的事件被触发的时候会像父App.vue传递一个数据
            this.$emit('jsxs',this.name) //把子类的参数传递给父类
        }
    }
<template>
  <div class="demo">
    <h2 >我是Demo2组件</h2>
    <button @click="send_data">点我</button>
  </div>
</template>
<script>
export default {
  name: "Demo",
  data() {
    return {
        name:'ckqn'
    }
  },
    methods:{
        send_data(){
            this.$emit('jsxs',this.name) //把子类的参数传递给父类
        }
    }
};
</script>
<style>
    .demo{
        background-color: antiquewhite;
    }
</style>

3.儿子传递数据给父亲 (ref 自定义事件实现)

1.给子组件设置ref。 在组件上设置ref就是获取的组件的实列对象
<Demo ref="demoA"/>
2.利用mounted进行挂载实现自定义
  mounted() {
    this.$refs.demoA.$on('jsxs',this.test)  //第一个参数是自定义自定义事件名和子组件emit对应,第二个是父App.vue绑定的函数
  },

App.vue

<template>
  <div class="app">
    <h2>我是App组件</h2>
    <!-- 
        如下代码是给Demo的组件实列对象定义一个jsxs事件,只要Demo组件实列对象触发了jsxs事件,那么就调用test函数
        组件->一般添加的是自定义事件
     -->
    <Demo ref="demoA"/>
    <h2>{{username}}</h2>
  </div>
</template>
<script>
import Demo from "./components/Demo.vue";
export default {
  name: "App",
  components: {
    Demo,
  },
  data() {
    return {
        username:'111'
    }
  },
  methods: {
    test(data_one){
        this.username = data_one
    }
  },
  mounted() {
    this.$refs.demoA.$on('jsxs',this.test)
  },
};
</script>
<style>
.app{
    background-color: brown;
    padding: 10px;
}
</style>

Demo.vue 不变

<template>
  <div class="demo">
    <h2 >我是Demo2组件</h2>
    <button @click="send_data">点我</button>
  </div>
</template>
<script>
export default {
  name: "Demo",
  data() {
    return {
        name:'ckqn'
    }
  },
    methods:{
        send_data(){
            this.$emit('jsxs',this.name) //把子类的参数传递给父类
        }
    }
};
</script>
<style>
    .demo{
        background-color: antiquewhite;
    }
</style>

4.todoList更换为自定义事件

App.vue

<!-- 1.头部 将父APP.VUE的addFather方法传递给子组件-->
      <Header @addFatherA="addFather"/>
<template>
  <div>
   <div class="todo-container">
    <div class="todo-wrap">
      <!-- 1.头部 将父APP.VUE的addFather方法传递给子组件-->
      <Header @addFatherA="addFather"/>
      <!-- 2.列表 : 将父APP.VUE的todos数组传递给子组件-->
      <list 
      :todosA="todos" 
      :updateFatherA="updateFather"
      :deleteFatherA="deleteFather"
      />
      <!-- 3.底部导航 -->
      <Footer 
      :FooterTodos="todos"
      :updateAllFatherA="updateAllFather"
      :clearAllDoneFatherA="clearAllDoneFather"
      />
    </div>
  </div>
  </div>
</template>
<script>
  // 1.引入组件
  import Header from './components/Header.vue'
  import List from './components/List.vue'
  import Footer from './components/Footer.vue'
export default {
  name:'App', // 目的是在浏览器VUE插件中的名字都是App不会被改变。
  // 2.注册组件
  components:{
    Header,
    List,
    Footer
  },
  data() {
    return {
      todos:[]
    }
  },
  methods: {
    addFather(todoObj){
      // 这个方法是对todos这个数组的尾部追加对象todoObj
      this.todos.unshift(todoObj)
    },
  // 更新
    updateFather(index,doneA){
      this.todos[index].done=doneA
    },
    // 删除
    deleteFather(index){
    // 根据坐标删除数据
    this.todos.splice(index,1)
  },
  // 全选或者不选
  updateAllFather(doneOption){
    // map():创建一个新数组,这个新数组由原数组中的每个元素都调用一次提供的函数后的返回值组成。
      this.todos=this.todos.map((value)=>{  // 这个参数是遍历的单个对象
        return {...value,done:doneOption} // 返回将done属性改编为doneOption的完整对象
      })
  },
   // 清除已经已经勾选的
   clearAllDoneFather(){
    this.todos=this.todos.filter((value)=>{
      // 假如说done值为false就不用过滤-保留,否则就需要过滤-不保留
      return value.done===false
    })
   }
  },
  watch:{// 我们初步设想的是利用,mounted目的是一上来就挂载上去。但是webStorage数据不会随着新增能新增...
  todos:{
    immediate: true,  // 若immediate为true则handle会在初始化时就会调用一次,以后就看firstName的改变了
    deep: true, //开启深度监视
    handler(newValue,oldValue){  //假如data是方法旧值获取不到(旧址也是新值),假如data是对象就能获取到旧值
        localStorage.setItem('arr_Object',JSON.stringify(newValue)); // 这里一定要转换为JSON字符串
      }
    }
  }
}
</script>
<style>
  /*base*/
  body {
    background: #fff;
  }
  .btn {
    display: inline-block;
    padding: 4px 12px;
    margin-bottom: 0;
    font-size: 14px;
    line-height: 20px;
    text-align: center;
    vertical-align: middle;
    cursor: pointer;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
    border-radius: 4px;
  }
  .btn-danger {
    color: #fff;
    background-color: #da4f49;
    border: 1px solid #bd362f;
  }
  .btn-danger:hover {
    color: #fff;
    background-color: #bd362f;
  }
  .btn:focus {
    outline: none;
  }
  .todo-container {
    width: 600px;
    margin: 0 auto;
  }
  .todo-container .todo-wrap {
    padding: 10px;
    border: 1px solid #ddd;
    border-radius: 5px;
  }
</style>

Header.vue

$emit -> 属于vue实列的, vc是继承了vm
 add(){
        if(this.textA!==null){
           // 根据用户的输入生成一个todo对象
        const todo={id:Date.now(),name:this.textA,done:false}
        // 通知父App.vue添加这个数据
        this.$emit('addFatherA',todo)
        }
        this.textA=''
      }
<template>
  <div>
          <!-- 1.头部 -->
      <div class="todo-header">
        <input type="text" placeholder="请输入你的任务名称,按回车键确认" v-model="textA" @keyup.enter="add"/>
      </div>
  </div>
</template>
<script>
export default {
    name:'Header',
    data() {
      return {
        textA:''
      }
    },
    methods: {
      add(){
        if(this.textA!==null){
           // 根据用户的输入生成一个todo对象
        const todo={id:Date.now(),name:this.textA,done:false}
        // 通知父App.vue添加这个数据
        this.$emit('addFatherA',todo)
        }
        this.textA=''
      }
    },
}
</script>
<style scoped>
  /*header*/
  .todo-header input {
    width: 560px;
    height: 28px;
    font-size: 14px;
    border: 1px solid #ccc;
    border-radius: 4px;
    padding: 4px 7px;
  }
  .todo-header input:focus {
    outline: none;
    border-color: rgba(82, 168, 236, 0.8);
    box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
  }
</style>

相关文章
|
3天前
|
缓存 监控 JavaScript
探讨优化Vue应用性能和加载速度的策略
【5月更文挑战第17天】本文探讨了优化Vue应用性能和加载速度的策略:1) 精简代码和组件拆分以减少冗余;2) 使用计算属性和侦听器、懒加载、预加载和预获取优化路由;3) 数据懒加载和防抖节流处理高频事件;4) 图片压缩和选择合适格式,使用CDN加速资源加载;5) 利用浏览器缓存和组件缓存提高效率;6) 使用Vue Devtools和性能分析工具监控及调试。通过这些方法,可提升用户在复杂应用中的体验。
10 0
|
3天前
|
JavaScript 前端开发
vue(1),小白看完都会了
vue(1),小白看完都会了
|
3天前
|
JavaScript 数据库
ant design vue日期组件怎么清空 取消默认当天日期
ant design vue日期组件怎么清空 取消默认当天日期
|
3天前
|
JavaScript C++
vue高亮显示组件--转载
vue高亮显示组件--转载
8 0
|
3天前
|
JavaScript 前端开发 数据安全/隐私保护
揭秘Vue中v-model的内部工作机制
揭秘Vue中v-model的内部工作机制
|
2天前
|
JavaScript 开发工具 git
Vue 入门系列:.env 环境变量
Vue 入门系列:.env 环境变量
9 1
|
3天前
|
JavaScript
vue知识点
vue知识点
11 0
|
3天前
|
JavaScript 前端开发 定位技术
Vue使用地图以及实现轨迹回放 附完整代码
Vue使用地图以及实现轨迹回放 附完整代码
Vue使用地图以及实现轨迹回放 附完整代码
|
3天前
|
JavaScript
Vue中避免滥用this去读取data中数据
Vue中避免滥用this去读取data中数据
|
3天前
|
JavaScript
vue中使用pinia及持久化
vue中使用pinia及持久化
6 0