Vue基础13之浏览器本地存储、TodoList本地存储、组件自定义事件

news2024/11/15 18:48:15

Vue基础13

  • 浏览器本地存储
    • localStorage 本地存储
    • sessionStorage 会话存储
    • 总结
  • TodoList本地存储
    • App.vue
  • 组件自定义事件
    • 子组件给父组件传值使用props方法
      • App.vue
      • School.vue
    • 子组件给父组件传值使用组件自定义事件——绑定
      • 第一种写法:使用v-on或@
        • App.vue
        • Student.vue
      • 第二种写法
        • App.vue
        • Teacher.vue
    • 解绑
      • 解绑一个自定义事件
        • App.vue
        • Student.vue
        • School.vue
      • 解绑多个自定义事件
        • App.vue
        • Student.vue
        • 解绑所有事件
          • 第一种方法
            • App.vue
            • Student.vue
          • 第二种方法(销毁)
            • App.vue
            • Student.vue
            • App.vue
            • Student.vue
            • School.vue
            • main.js
    • 总结
      • 两个点
        • 子组件传值给父组件在页面上显示
          • @sName场景,ref场景
          • App.vue
          • Student.vue
          • School.vue
          • 在ref中,使用内置函数传值有问题,因为this是Student的实例对象,不是App的实例对象
          • App.vue
          • Student.vue
          • School.vue
          • 所以,如果想在ref绑定时候就写函数,则使用箭头函数,因为箭头函数没有this对象,只会向外层找
          • App.vue
        • 给子组件绑定常规事件(click等)
          • App.vue
      • 总结组件自定义事件

浏览器本地存储

localStorage 本地存储

关闭浏览器之后重新打开,数据仍还在,除非自行清除内存数据

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>浏览器本地存储</title>
</head>
<body>
<h1>localStorage</h1>
<button onclick="saveData()">点我保存一个数据</button>
<button onclick="readData()">点我读取一个数据</button>
<button onclick="deleteData()">点我删除一个数据</button>
<button onclick="clearData()">点我清空所有</button>
<hr>
<script>
    function saveData(){
        localStorage.setItem('msg','hello~你好啊,你看到我了嘛?')
        localStorage.setItem('msg2',666)
        const p={name:'张三',age:20}
        localStorage.setItem('person',JSON.stringify(p))
    }
    function readData(){
        console.log(localStorage.getItem('msg'));
        console.log(localStorage.getItem('msg2'));
        const p=localStorage.getItem('person')
        console.log(JSON.parse(p));
        console.log("-------------------------------------------")
    }
    function deleteData(){
        localStorage.removeItem('msg2')
    }
    function clearData(){
        localStorage.clear()
    }

</script>
</body>
</html>

请添加图片描述

sessionStorage 会话存储

会话存储只能在一次会话中保存数据,浏览器关闭标志着一次会话的结束,所以,关闭浏览器后,保存的数据就不在了

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>sessionStorage</title>
</head>
<body>
<h1>sessionStorage</h1>
<button onclick="saveData()">点我保存一个数据</button>
<button onclick="readData()">点我读取一个数据</button>
<button onclick="deleteData()">删除一个数据</button>
<button onclick="clearData()">清空所有数据</button>
<script>
    function saveData(){
        sessionStorage.setItem('message','今天天气真不错')
        sessionStorage.setItem('msg',123456887)
        const person={name:'李四',sex:'男'}
        sessionStorage.setItem('person',JSON.stringify(person))
    }
    function readData(){
        console.log(sessionStorage.getItem('message'));
        console.log(sessionStorage.getItem('msg'));
        const p=sessionStorage.getItem('person')
        console.log(JSON.parse(p));
        console.log("-----------------------------------------")
    }
    function deleteData(){
        sessionStorage.removeItem('msg')
    }
    function clearData(){
        sessionStorage.clear()
    }
</script>
</body>
</html>

请添加图片描述

总结

  1. 存储内容大小一般支持5MB左右(不同浏览器可能还不一样)
  2. 浏览器端通过Window.sessionStorage和Window.localStorage属性来实现本地存储机制
  3. 相关API:
    (1)xxxxStorage.setItem('key','value');
    该方法接受一个键和值作为参数,会把键值对添加到存储中,如果键名存在,则更新其对应的值。
    (2)xxxxStorage.getItem('person')
    该方法接受一个键名作为参数,返回键名对应的值。
    (3)xxxxxxStorage.removeItem('key')
    该方法接受一个键名作为参数,并把该键名从存储中删除
    (4)xxxxxxStorage.clear()
    该方法会清空存储中的所有数据
  4. 备注:
    (1)SessionStorage存储的内容会随着浏览器窗口关闭而消失
    (2)LocalStorage存储的内容,需要手动清除才会消失
    (3)xxxxStorage.getItem(xxx)如果xxx对应的value获取不到,那么getItem的返回值是null
    (4)JSON.parse(null)的结果依然是null

TodoList本地存储

使用watch对todos进行监视,并将每次修改都存放在localStorage中

App.vue

<template>
  <div class="bg">
    <div class="todoList">
      <h2 class="title">待办事项</h2>
      <MyHeader :addTodo="addTodo"/>
      <div class="listItem" v-show="todos.length">
        <MyList :todos="todos" :deleteTodo="deleteTodo" :checkTodo="checkTodo"/>
        <MyFooter :todos="todos" :clearAllTodo="clearAllTodo" :checkAllTodo="checkAllTodo"/>
      </div>
    </div>
  </div>
</template>

<script>
import MyHeader from "@/components/MyHeader";
import MyList from '@/components/MyList';
import MyFooter from '@/components/MyFooter'
export default {
  name: "App",
  components:{MyHeader, MyList, MyFooter},
  data(){
    return{
      todos:JSON.parse(localStorage.getItem('todos'))||[]
    }
  },
  methods:{
    //添加一个todo
    addTodo(todoObj){
      this.todos.unshift(todoObj)
    },
    //删除一个todo
    deleteTodo(id){
      this.todos=this.todos.filter(todo=>todo.id!==id)
    },
    //勾选or取消勾选一个todo
    checkTodo(id){
      this.todos.forEach((todo)=>{
        if(todo.id===id){
          todo.done=!todo.done
        }
      })
    },
    //清除已完成任务
    clearAllTodo() {
      this.todos=this.todos.filter(todo=>!todo.done)
    },
    //全选or取消全选
    checkAllTodo(done){
      this.todos.forEach(todo=>todo.done=done)
    }
  },
  watch:{
    todos:{
      //开启深度监视
      deep:true,
      handler(value){
        localStorage.setItem('todos',JSON.stringify(value))
      }
    }
  }
}
</script>

<style lang="less">
*{
  padding: 0;
  margin: 0;
}
.bg{
  background-color: #333;
  height: 937px;
  padding-top: 100px;
  box-sizing: border-box;
  .todoList{
    background-color: #fff;
    width: 50%;
    height: 90%;
    margin: 0 auto;
    //box-shadow: 5px 5px 10px 3px rgba(147, 221, 255, 0.5),-5px -5px 10px 3px rgba(147, 221, 255, 0.5);  蓝色阴影
    box-shadow: 5px 5px 10px 3px rgba(0, 0, 0, 0.5),-5px -5px 10px 3px rgba(0, 0, 0, 0.5);
    padding-top: 20px;
    box-sizing: border-box;
    .title{
      text-align: center;
      font-size: 30px;
      font-weight: 300;
      color: #00a4ff;
    }
    .listItem{
      width: 90%;
      //height: 200px;
      margin: auto;
      /*background-color: pink;*/
      list-style: none;
      border-radius: 0 0 5px 5px;
      box-shadow: 1px 1px 5px 1px rgba(0,0,0,0.1),-1px -1px 5px 1px rgba(0,0,0,0.1);
      padding: 20px 0;
      box-sizing: border-box;
    }
  }
}
</style>

请添加图片描述

组件自定义事件

子组件给父组件传值使用props方法

App.vue

<template>
  <div class="main">
    <h1>{{msg}}</h1>
    <h2 v-show="schoolName">App收到了学校名:{{schoolName}}</h2>
    <!--   通过父组件给子组件传递函数类型的props实现:子给父传递数据-->
    <School :getSchoolName="getSchoolName"></School>
  </div>
</template>

<script>
import School from "@/components/School";
export default {
  name: "App",
  data(){
    return{
      msg:"你好啊!",
      schoolName:"",
    }
  },
  components:{School},
  methods:{
    getSchoolName(name){
      this.schoolName=name
    },
}
</script>

<style scoped>
.main{
  background-color: grey;
  padding: 5px;
}
</style>

School.vue

<template>
  <div class="school">
    <h1>学校名称:{{name}}</h1>
    <h1>学校地址:{{address}}</h1>
    <button @click="sendSchoolName">点我将学校名字给App</button>
  </div>
</template>

<script>
  export default {
      name: "School",
      data(){
        return{
          name:"幸福中学",
          address:"重庆市渝北区"
        }
      },
    props:['getSchoolName'],
    methods:{
      sendSchoolName(){
        this.getSchoolName(this.name)
      }
    }
  }
</script>

<style scoped>
.school{
  background-color: skyblue;
}
</style>

请添加图片描述

子组件给父组件传值使用组件自定义事件——绑定

第一种写法:使用v-on或@

App.vue

<template>
  <div class="main">
    <h1>{{msg}}</h1>
    <h2 v-show="schoolName">App收到了学校名:{{schoolName}}</h2>
    <h2 v-show="studentName">App收到了学生名:{{studentName}}</h2>
    <!--   通过父组件给子组件传递函数类型的props实现:子给父传递数据-->
    <School :getSchoolName="getSchoolName"></School>
    <!--        通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第一种写法:使用v-on或@)-->
    <Student v-on:showN="getStudentName"></Student>
  </div>
</template>

<script>
import School from "@/components/School";
import Student from "@/components/Student";
export default {
  name: "App",
  data(){
    return{
      msg:"你好啊!",
      schoolName:"",
      studentName:"",
    }
  },
  components:{School,Student},
  methods:{
    getSchoolName(name){
      this.schoolName=name
    },
    getStudentName(name){
      this.studentName=name
    },
  },
}
</script>

<style scoped>
.main{
  background-color: grey;
  padding: 5px;
}
</style>

Student.vue

<template>
  <div class="student">
    <h1>学生姓名:{{name}}</h1>
    <h1>学生性别:{{sex}}</h1>
    <button @click="sendStudentName">点我将学生名字传递给App</button>
  </div>
</template>

<script>
    export default {
        name: "Student",
        data(){
          return{
            name:'李四',
            sex:'女'
          }
        },
      methods:{
        sendStudentName(){
          //触发Student组件实例对象身上的showN事件
          this.$emit('showN',this.name)
        }
      }
    }
</script>

<style scoped>
.student{
  background-color: pink;
}
</style>

请添加图片描述

第二种写法

App.vue

<template>
  <div class="main">
    <h1>{{msg}}</h1>
    <h2 v-show="schoolName">App收到了学校名:{{schoolName}}</h2>
    <h2 v-show="studentName">App收到了学生名:{{studentName}}</h2>
    <h2 v-show="teacher.name&&teacher.sex">App收到了老师名:{{teacher.name}},性别:{{teacher.sex}}</h2>
    <!--   通过父组件给子组件传递函数类型的props实现:子给父传递数据-->
    <School :getSchoolName="getSchoolName"></School>
    <!--        通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第一种写法:使用v-on或@)-->
    <Student v-on:showN="getStudentName"></Student>
    <!--      通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第二种写法:使用ref)  -->
    <Teacher ref="teacher"/>
  </div>
</template>

<script>
import School from "@/components/School";
import Student from "@/components/Student";
import Teacher from "@/components/Teacher";
export default {
  name: "App",
  data(){
    return{
      msg:"你好啊!",
      schoolName:"",
      studentName:"",
      teacher:{
        name:"",
        sex:""
      }
    }
  },
  components:{School,Student,Teacher},
  methods:{
    getSchoolName(name){
      this.schoolName=name
    },
    getStudentName(name){
      this.studentName=name
    },
    getTeacherName(name,...params){
      this.teacher.name=name
      this.teacher.sex=params[0]
    }
  },
  mounted() {
    this.$refs.teacher.$on('tName',this.getTeacherName)
  }
}
</script>

<style scoped>
.main{
  background-color: grey;
  padding: 5px;
}
</style>

Teacher.vue

<template>
  <div class="teacher">
    <h1>老师姓名:{{name}}</h1>
    <h1>老师性别:{{sex}}</h1>
    <button @click="sendTeacherName">点我将老师名字,性别传递给App</button>
  </div>
</template>

<script>
    export default {
      name: "Teacher",
      data(){
        return{
          name:'李四',
          sex:'女'
        }
      },
      methods:{
        sendTeacherName(){
          this.$emit('tName',this.name,this.sex)
        }
      }
    }
</script>

<style scoped>
.teacher{
  background-color: yellow;
}
</style>

请添加图片描述

解绑

解绑一个自定义事件

App.vue

<template>
  <div class="main">
    <h2>{{msg}}</h2>
    <School @sName="getSchoolName"></School>
    <Student ref="student"></Student>
  </div>
</template>

<script>
import School from "@/components/School"
import Student from "@/components/Student"
export default {
  name: "App",
  components: {School,Student},
  data(){
    return{
      msg:"欢迎光临~"
    }
  },
  methods:{
    getSchoolName(name){
      console.log("App收到了,",name)
    },
    getStudentName(name,...params) {
      console.log("App接收到了,",name,params)
    },
  },
  mounted() {
    this.$refs.student.$on("tName",this.getStudentName)
  }
}
</script>

<style scoped>
.main{
  background-color: grey;
  padding: 5px;
}
</style>

Student.vue

<template>
  <div class="student">
    <h2>学生姓名:{{name}}</h2>
    <h2>学生性别:{{sex}}</h2>
    <button @click="sendStudentName">点我将学生名字传给App</button>
    <button @click="upbind">解绑tName事件</button>
    <br>
  </div>
</template>

<script>
export default {
  name: "Student",
  data(){
    return{
      name:"张三",
      sex:"男"
    }
  },
  methods:{
    sendStudentName(){
      this.$emit("tName",this.name,999,666,888)
    },
    sendStudentNameSex(){
      this.$emit("tName",this.name)
      this.$emit("tSex",this.sex)
    },
    upbind(){
      this.$off("tName")  //解绑一个自定义事件
    },
  }
}
</script>

<style scoped>
.student{
  background-color: skyblue;
}
</style>

School.vue

<template>
  <div class="school">
    <h2>学校姓名:{{name}}</h2>
    <h2>学校地址:{{address}}</h2>
    <button @click="sendSchoolName">点我将学校名传给App</button>
  </div>
</template>

<script>
    export default {
        name: "School",
      data(){
          return{
            name:"幸福中学",
            address:"北京市海淀区"
          }
      },
      methods:{
        sendSchoolName(){
          this.$emit("sName",this.name)
        }
      }
    }
</script>

<style scoped>
.school{
  background-color: pink;
}
</style>

请添加图片描述

解绑多个自定义事件

App.vue

<template>
  <div class="main">
    <h2>{{msg}}</h2>
    <School @sName="getSchoolName"></School>
    <Student ref="student" @tSex="getStudentSex"></Student>
  </div>
</template>

<script>
import School from "@/components/School"
import Student from "@/components/Student"
export default {
  name: "App",
  components: {School,Student},
  data(){
    return{
      msg:"欢迎光临~"
    }
  },
  methods:{
    getSchoolName(name){
      console.log("App收到了,",name)
    },
    getStudentName(name,...params) {
      console.log("App接收到了,",name,params)
    },
    getStudentSex(sex){
      console.log("App收到了学生姓名,性别,",sex)
    }
  },
  mounted() {
    this.$refs.student.$on("tName",this.getStudentName)
  }
}
</script>

<style scoped>
.main{
  background-color: grey;
  padding: 5px;
}
</style>

Student.vue

<template>
  <div class="student">
    <h2>学生姓名:{{name}}</h2>
    <h2>学生性别:{{sex}}</h2>
    <button @click="sendStudentNameSex">点我将学生姓名,性别传给App</button>
    <button @click="upbind2">解绑tName,tSex事件</button>
  </div>
</template>

<script>
export default {
  name: "Student",
  data(){
    return{
      name:"张三",
      sex:"男"
    }
  },
  methods:{
    sendStudentNameSex(){
      this.$emit("tName",this.name)
      this.$emit("tSex",this.sex)
    },
    upbind2(){
      this.$off(["tName","tSex"])  //解绑多个自定义事件
    },
  }
}
</script>

<style scoped>
.student{
  background-color: skyblue;
}
</style>

请添加图片描述

解绑所有事件

第一种方法
App.vue
<template>
  <div class="main">
    <h2>{{msg}}</h2>
    <School @sName="getSchoolName"></School>
    <Student ref="student" @tSex="getStudentSex"></Student>
  </div>
</template>

<script>
import School from "@/components/School"
import Student from "@/components/Student"
export default {
  name: "App",
  components: {School,Student},
  data(){
    return{
      msg:"欢迎光临~"
    }
  },
  methods:{
    getSchoolName(name){
      console.log("App收到了,",name)
    },
    getStudentName(name,...params) {
      console.log("App接收到了,",name,params)
    },
    getStudentSex(sex){
      console.log("App收到了学生姓名,性别,",sex)
    }
  },
  mounted() {
    this.$refs.student.$on("tName",this.getStudentName)
  }
}
</script>

<style scoped>
.main{
  background-color: grey;
  padding: 5px;
}
</style>

Student.vue
<template>
  <div class="student">
    <h2>学生姓名:{{name}}</h2>
    <h2>学生性别:{{sex}}</h2>
    <button @click="sendStudentName">点我将学生名字传给App</button>
    <button @click="sendStudentNameSex">点我将学生姓名,性别传给App</button>
    <button @click="upbind3">解绑所有自定义事件</button>
  </div>
</template>

<script>
export default {
  name: "Student",
  data(){
    return{
      name:"张三",
      sex:"男"
    }
  },
  methods:{
    sendStudentName(){
      this.$emit("tName",this.name,999,666,888)
    },
    sendStudentNameSex(){
      this.$emit("tName",this.name)
      this.$emit("tSex",this.sex)
    },
    upbind3(){
      this.$off()  //解绑所有自定义事件
    },
  }
}
</script>

<style scoped>
.student{
  background-color: skyblue;
}
</style>

请添加图片描述

第二种方法(销毁)

在Student上销毁

App.vue
<template>
  <div class="main">
    <h2>{{msg}}</h2>
    <School @sName="getSchoolName"></School>
    <Student ref="student" @tSex="getStudentSex"></Student>
  </div>
</template>

<script>
import School from "@/components/School"
import Student from "@/components/Student"
export default {
  name: "App",
  components: {School,Student},
  data(){
    return{
      msg:"欢迎光临~"
    }
  },
  methods:{
    getSchoolName(name){
      console.log("App收到了,",name)
    },
    getStudentName(name,...params) {
      console.log("App接收到了,",name,params)
    },
    getStudentSex(sex){
      console.log("App收到了学生姓名,性别,",sex)
    }
  },
  mounted() {
    this.$refs.student.$on("tName",this.getStudentName)
  }
}
</script>

<style scoped>
.main{
  background-color: grey;
  padding: 5px;
}
</style>

Student.vue
<template>
  <div class="student">
    <h2>学生姓名:{{name}}</h2>
    <h2>学生性别:{{sex}}</h2>
    <button @click="sendStudentName">点我将学生名字传给App</button>
    <button @click="sendStudentNameSex">点我将学生姓名,性别传给App</button>
    <button @click="death">销毁当前Student组件的实例(vc)</button>
  </div>
</template>

<script>
export default {
  name: "Student",
  data(){
    return{
      name:"张三",
      sex:"男"
    }
  },
  methods:{
    sendStudentName(){
      this.$emit("tName",this.name,999,666,888)
    },
    sendStudentNameSex(){
      this.$emit("tName",this.name)
      this.$emit("tSex",this.sex)
    },
    death(){
      this.$destroy()  //销毁了当前Student组件的实例,销毁后所有Student的实例的自定义事件全都不奏效
    }
  }
}
</script>

<style scoped>
.student{
  background-color: skyblue;
}
</style>

请添加图片描述
在App上可以绑定销毁,销毁了所有组件的实例,销毁后所有组件实例的自定义事件全都不奏效
在main.js里设置定时器,在3秒后自动销毁,之后所有组件的自定义事件不奏效了

App.vue
<template>
  <div class="main">
    <h2>{{msg}}</h2>
    <School @sName="getSchoolName"></School>
    <Student ref="student" @tSex="getStudentSex"></Student>
  </div>
</template>

<script>
import School from "@/components/School"
import Student from "@/components/Student"
export default {
  name: "App",
  components: {School,Student},
  data(){
    return{
      msg:"欢迎光临~"
    }
  },
  methods:{
    getSchoolName(name){
      console.log("App收到了,",name)
    },
    getStudentName(name,...params) {
      console.log("App接收到了,",name,params)
    },
    getStudentSex(sex){
      console.log("App收到了学生姓名,性别,",sex)
    }
  },
  mounted() {
    this.$refs.student.$on("tName",this.getStudentName)
  }
}
</script>

<style scoped>
.main{
  background-color: grey;
  padding: 5px;
}
</style>

Student.vue
<template>
  <div class="student">
    <h2>学生姓名:{{name}}</h2>
    <h2>学生性别:{{sex}}</h2>
    <button @click="sendStudentName">点我将学生名字传给App</button>
    <button @click="sendStudentNameSex">点我将学生姓名,性别传给App</button>
  </div>
</template>

<script>
export default {
  name: "Student",
  data(){
    return{
      name:"张三",
      sex:"男"
    }
  },
  methods:{
    sendStudentName(){
      this.$emit("tName",this.name,999,666,888)
    },
    sendStudentNameSex(){
      this.$emit("tName",this.name)
      this.$emit("tSex",this.sex)
    },
  }
}
</script>

<style scoped>
.student{
  background-color: skyblue;
}
</style>

School.vue
<template>
  <div class="school">
    <h2>学校姓名:{{name}}</h2>
    <h2>学校地址:{{address}}</h2>
    <button @click="sendSchoolName">点我将学校名传给App</button>
  </div>
</template>

<script>
    export default {
        name: "School",
      data(){
          return{
            name:"幸福中学",
            address:"北京市海淀区"
          }
      },
      methods:{
        sendSchoolName(){
          this.$emit("sName",this.name)
        }
      }
    }
</script>

<style scoped>
.school{
  background-color: pink;
}
</style>

main.js
import Vue from 'vue'

import App from './App'

Vue.config.productionTip=false

new Vue({
    el:"#app",
    render:h=>h(App),
    mounted() {
        setTimeout(()=>{
            this.$destroy()
        },3000)
    }
})

请添加图片描述

总结

两个点

子组件传值给父组件在页面上显示

@sName场景,ref场景
App.vue
<template>
  <div class="main">
    <h2>{{msg}},学校名称是:{{schoolName}},学生姓名是:{{studentName}}</h2>
    <School @sName="getSchoolName"></School>
    <Student ref="student"></Student>
  </div>
</template>

<script>
import School from "@/components/School"
import Student from "@/components/Student"
export default {
  name: "App",
  components: {School,Student},
  data(){
    return{
      msg:"欢迎光临~",
      schoolName:"",
      studentName:"",
    }
  },
  methods:{
    getSchoolName(name){
      console.log("App收到了,",name)
      this.schoolName=name
    },
    getStudentName(name,...params) {
      console.log("App接收到了,",name,params)
      this.studentName=name
    },
  },
  mounted() {
    this.$refs.student.$on("tName",this.getStudentName)
  }
}
</script>

<style scoped>
.main{
  background-color: grey;
  padding: 5px;
}
</style>

Student.vue
<template>
  <div class="student">
    <h2>学生姓名:{{name}}</h2>
    <h2>学生性别:{{sex}}</h2>
    <button @click="sendStudentName">点我将学生名字传给App</button>
  </div>
</template>

<script>
export default {
  name: "Student",
  data(){
    return{
      name:"张三",
      sex:"男"
    }
  },
  methods:{
    sendStudentName(){
      this.$emit("tName",this.name,999,666,888)
    },
  }
}
</script>

<style scoped>
.student{
  background-color: skyblue;
}
</style>

School.vue
<template>
  <div class="school">
    <h2>学校姓名:{{name}}</h2>
    <h2>学校地址:{{address}}</h2>
    <button @click="sendSchoolName">点我将学校名传给App</button>
  </div>
</template>

<script>
    export default {
        name: "School",
      data(){
          return{
            name:"幸福中学",
            address:"北京市海淀区"
          }
      },
      methods:{
        sendSchoolName(){
          this.$emit("sName",this.name)
        }
      }
    }
</script>

<style scoped>
.school{
  background-color: pink;
}
</style>

请添加图片描述

在ref中,使用内置函数传值有问题,因为this是Student的实例对象,不是App的实例对象
App.vue
<template>
  <div class="main">
    <h2>{{msg}},学校名称是:{{schoolName}},学生姓名是:{{studentName}}</h2>
    <School @sName="getSchoolName"></School>
    <Student ref="student"></Student>
  </div>
</template>

<script>
import School from "@/components/School"
import Student from "@/components/Student"
export default {
  name: "App",
  components: {School,Student},
  data(){
    return{
      msg:"欢迎光临~",
      schoolName:"",
      studentName:"",
    }
  },
  methods:{
    getSchoolName(name){
      console.log("App收到了,",name)
      this.schoolName=name
    },
    getStudentName(name,...params) {
      console.log("App接收到了,",name,params)
      this.studentName=name
    },
  },
  mounted() {
    this.$refs.student.$on("tName",function(name){
      console.log("App收到了学生性别:",name)
      console.log("this",this)
      this.studentName=name
    })
  }
}
</script>

<style scoped>
.main{
  background-color: grey;
  padding: 5px;
}
</style>
Student.vue
<template>
  <div class="student">
    <h2>学生姓名:{{name}}</h2>
    <h2>学生性别:{{sex}}</h2>
    <button @click="sendStudentName">点我将学生名字传给App</button>
  </div>
</template>

<script>
export default {
  name: "Student",
  data(){
    return{
      name:"张三",
      sex:"男"
    }
  },
  methods:{
    sendStudentName(){
      this.$emit("tName",this.name,999,666,888)
    },
  }
}
</script>

<style scoped>
.student{
  background-color: skyblue;
}
</style>

School.vue
<template>
  <div class="school">
    <h2>学校姓名:{{name}}</h2>
    <h2>学校地址:{{address}}</h2>
    <button @click="sendSchoolName">点我将学校名传给App</button>
  </div>
</template>

<script>
    export default {
        name: "School",
      data(){
          return{
            name:"幸福中学",
            address:"北京市海淀区"
          }
      },
      methods:{
        sendSchoolName(){
          this.$emit("sName",this.name)
        }
      }
    }
</script>

<style scoped>
.school{
  background-color: pink;
}
</style>

请添加图片描述

所以,如果想在ref绑定时候就写函数,则使用箭头函数,因为箭头函数没有this对象,只会向外层找
App.vue
<template>
  <div class="main">
    <h2>{{msg}},学校名称是:{{schoolName}},学生姓名是:{{studentName}}</h2>
    <School @sName="getSchoolName"></School>
    <Student ref="student"></Student>
  </div>
</template>

<script>
import School from "@/components/School"
import Student from "@/components/Student"
export default {
  name: "App",
  components: {School,Student},
  data(){
    return{
      msg:"欢迎光临~",
      schoolName:"",
      studentName:"",
    }
  },
  methods:{
    getSchoolName(name){
      console.log("App收到了,",name)
      this.schoolName=name
    },
    getStudentName(name,...params) {
      console.log("App接收到了,",name,params)
      this.studentName=name
    },
  },
  mounted() {
    this.$refs.student.$on("tName",(name)=>{
      console.log("App收到了学生性别:",name)
      console.log("this",this)
      this.studentName=name
    })
  }
}
</script>

<style scoped>
.main{
  background-color: grey;
  padding: 5px;
}
</style>

请添加图片描述

给子组件绑定常规事件(click等)

必须加native,否则会被认为自定义事件

App.vue
<template>
  <div class="main">
    <h2>{{msg}},学校名称是:{{schoolName}},学生姓名是:{{studentName}}</h2>
    <School @sName="getSchoolName"></School>
    <Student ref="student" @click.native="show"></Student>
  </div>
</template>

<script>
import School from "@/components/School"
import Student from "@/components/Student"
export default {
  name: "App",
  components: {School,Student},
  data(){
    return{
      msg:"欢迎光临~",
      schoolName:"",
      studentName:"",
    }
  },
  methods:{
    getSchoolName(name){
      console.log("App收到了,",name)
      this.schoolName=name
    },
    getStudentName(name,...params) {
      console.log("App接收到了,",name,params)
      this.studentName=name
    },
    show(){
      alert("hello~")
    }
  },
  mounted() {
    this.$refs.student.$on("tName",(name)=>{
      console.log("App收到了学生性别:",name)
      console.log("this",this)
      this.studentName=name
    })
  }
}
</script>

<style scoped>
.main{
  background-color: grey;
  padding: 5px;
}
</style>

请添加图片描述

总结组件自定义事件

  1. 一种组件间通信的方式,适用于:子组件 ===> 父组件
  2. 使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中)
  3. 绑定自定义事件:
    (1)第一种方式,在父组件中,<Demo @sName=“test”/><Demo v-on:sName=“test”/>
    (2)第二种方式,在父组件中:

<Demo ref=“demo” />

mounted(){
this.$refs.xxx.$on(‘sName’,this.test)
}

(3)若想让自定义事件只能触发一次,可以使用once修饰符,或 $once方法

  1. 触发自定义事件:this.$emit(‘sName’,数据)
  2. 解绑自定义事件:this.$off(‘sName’)
  3. 组件上也可以绑定原生DOM事件,需要用native修饰符
  4. 注意:通过 this.$refs.xxx.$on(‘sName’,回调) 绑定自定义事件时,回调要么配置在methods中,要么用箭头函数,否则this指向会出问题!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/351817.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

idea快捷编码:生成for循环、主函数、判空非空、生成单例方法、输出;自定义快捷表达式

前言 idea可根据输入的简单表达式进行识别&#xff0c;快速生成语句 常用的快捷编码&#xff1a;生成for循环、主函数、判空非空、生成单例方法、输出 自定义快捷表达式 博客地址&#xff1a;芒果橙的个人博客 【http://mangocheng.com】 一、idea默认的快捷表达式查看 Editor…

String对象的创建和比较

String类的概述 String类&#xff1a;代表字符串。 Java 程序中的所有字符串字面值&#xff08;如 “abc” &#xff09;都作 为此类的实例实现。 String是JDK中内置的一个类&#xff1a;java.lang.string 。 String表示字符串类型&#xff0c;属于引用数据类型&#xff0c;不…

饲养员喂养动物-课后程序(JAVA基础案例教程-黑马程序员编著-第四章-课后作业)

【案例4-2】饲养员喂养动物 记得 关注&#xff0c;收藏&#xff0c;评论哦&#xff0c;作者将持续更新。。。。 【案例目标】 案例描述 饲养员在给动物喂食时&#xff0c;给不同的动物喂不同的食物&#xff0c;而且在每次喂食时&#xff0c;动物都会发出欢快的叫声。例如&…

Native扩展开发的一般流程(类似开发一个插件)

文章目录大致开发流程1、编写对应的java类服务2、将jar包放到对应位置3、配置文件中进行服务配置4、在代码中调用5、如何查看服务调用成功大致开发流程 1、编写服务&#xff0c;打包为jar包2、将jar包放到指定的位置3、在配置文件中进行配置&#xff0c;调用对应的服务 1、编…

linux 之 ps命令介绍

哈喽&#xff0c;大家好&#xff0c;我是有勇气的牛排&#xff08;全网同名&#xff09;&#x1f42e; 有问题的小伙伴欢迎在文末评论&#xff0c;点赞、收藏是对我最大的支持&#xff01;&#xff01;&#xff01;。 前言 如过想实现对进程监控&#xff0c;就需要使用到ps命…

macOS 13.3 Beta (22E5219e)发布

系统介绍2 月 17 日消息&#xff0c;苹果今日向 Mac 电脑用户推送了 macOS 13.3 开发者预览版 Beta 更新&#xff08;内部版本号&#xff1a;22E5219e&#xff09;&#xff0c;本次更新距离上次发布隔了 37 天。macOS Ventura 带来了台前调度、连续互通相机、FaceTime 通话接力…

Vue3+Lodash:2023年了,我依然在使用Lodash

目录 前言&#xff1a; 为什么选择lodash? 看看lodash的地位 如何使用lodash&#xff1f; 1.安装lodash 2.引入lodash 我们到底还需不需要lodash&#xff1f; 再举一些例子 前言&#xff1a; 前两天&#xff0c;在水群的时候&#xff0c;发现居然有人不知lodash&#…

OpenCV-PyQT项目实战(6)项目案例02:滚动条应用

欢迎关注『OpenCV-PyQT项目实战 Youcans』系列&#xff0c;持续更新中 OpenCV-PyQT项目实战&#xff08;1&#xff09;安装与环境配置 OpenCV-PyQT项目实战&#xff08;2&#xff09;QtDesigner 和 PyUIC 快速入门 OpenCV-PyQT项目实战&#xff08;3&#xff09;信号与槽机制 …

基于感知动作循环的层次推理用于视觉问答

title&#xff1a;Hierarchical Reasoning Based on Perception Action Cycle for Visual Question Answering 基于感知动作循环的层次推理用于视觉问答 文章目录title&#xff1a;[Hierarchical Reasoning Based on Perception Action Cycle for Visual Question Answering](…

机器学习技术:多任务学习综述!

Datawhale干货 作者&#xff1a;陈敬&#xff0c;中国移动云能力中心前言本文对多任务学习(multi-task learning, MTL)领域近期的综述文章进行整理&#xff0c;从模型结构和训练过程两个层面回顾了其发展变化&#xff0c;旨在提供一份 MTL 入门指南&#xff0c;帮助大家快速了解…

MySQL的锁机制详解

目录 一.概述 分类 锁的特性 二.MyISAM表锁 如何加表锁 读锁演示 写锁演示 三.InnoDB行锁 行锁特点 行锁模式 一.概述 锁是计算机协调多个进程或线程并发访问某一资源的机制&#xff08;避免争抢&#xff09;。 在数据库中&#xff0c;除传统的计算资源&#xff08;如…

常见的并发模型

介绍 常见解决并发的策略一般有两种&#xff1a;共享数据和消息传递 基于消息传递的实现有 CSP模型&#xff0c;典型的有Go语言中基于Channel的通讯Actor模型&#xff0c;典型的有Akka中的Actor模型 CSP模型和Actor模型的简单理解&#xff1a; Dont communicate by sharing…

如何使用MQTTX可视化工具

@ [TOC] 使用背景 最近在调试MQTT相关的程序,调试程序时使用的是MQTTX这个工具,它可以创建服务器连接,并且在连接后发布和订阅主题。在调试过程中总结了一些使用方法和技巧,在这里分享给大家。 MQTTX是EMQX公司推出的可视化MQTT调试工具,大家可以到官网下载使用,同时参…

技术实践干货:从零开始创建Node.js应用

作为一个程序员&#xff0c;我们常常会有很多想法和创意&#xff0c;然后用技术实现出来&#xff0c;这是一个很有成就感的事情。 在实践过程中&#xff0c;会发现很多想法都不能很好地落地&#xff0c;可能是技术、可能是团队氛围等等&#xff0c;于是就开始想着能够不能有一个…

类内默认函数

目录 前言&#xff1a; 1. 构造函数 1.1 概念 1.2 特性 1&#xff09; 2&#xff09; 2. 析构函数 2.1 概念 2.2 特性 3. 拷贝构造 3.1 概念 3.2 特征 4. 赋值运算符重载 4.1 运算符重载 4.2 赋值运算符重载 5.3 前置和后置的重载 前言&#xff1a; 问&#xf…

AI智能机器人,在这里也可以体验~

“大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂。”现在是&#xff1a;2023年2月17日00:14:42前言最近AI智能chatgpt特别的火&#xff0c;相信好多人都已经体验过了&#xff0c;之前我的群里也接入过&#xff0c;奈何总是收到警告和限制…

泛微发布内外协同的客服管理系统-睦客邻

客户服务是企业业务环节中的关键一环&#xff0c;也是确保客户最终满意度的关键一环。好的客户服务是一个组织能持续经营的有力保证。 如何让客服成为客户的好邻里&#xff0c;让客户真实地感受到全方位的服务&#xff0c;从而让组织的服务产生力量和价值。企业对客服有着系统…

LV8731V-TLM-H 带保护步进电机驱动器特性简述

LV8731V-TLM-H是一个2−通道H−桥驱动器IC&#xff0c;它可以切换步进电机驱动器和两个有刷电机驱动器&#xff0c;前者支持1/16−步进分辨率的微步进驱动&#xff0c;后者支持电机的前进、后退、制动和待机。它非常适合驱动办公室设备和娱乐应用中使用的刷直流电机和步进电机。…

Web--Maven

1.maven管理项目的区别 2. 安装后&#xff0c;conf目录下的setting文件中&#xff0c;对本地仓库的配置 此处可替换成自定义的本地仓库地址&#xff0c;默认为c:/user/17860/.m2/repository(我的电脑上的&#xff09; 3.maven项目的标准目录结构 4.项目的生命周期 5.Maven概…

内网渗透(三十七)之横向移动篇-Pass the Hash 哈希传递攻击(PTH)横向移动

系列文章第一章节之基础知识篇 内网渗透(一)之基础知识-内网渗透介绍和概述 内网渗透(二)之基础知识-工作组介绍 内网渗透(三)之基础知识-域环境的介绍和优点 内网渗透(四)之基础知识-搭建域环境 内网渗透(五)之基础知识-Active Directory活动目录介绍和使用 内网渗透(六)之基…