本地存储、自定义事件、全局事件总线、消息订阅与发布【Vue】

Vue

1.1 浏览器的本地存储

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

1.2 组件的自定义事件

  1. 一种组件间通信的方式,适用于:子组件 ===> 父组件
  2. 使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中
  3. 绑定自定义事件:
    (1)第一种方式,在父组件中:< Demo @zmy = "test"/ > 或
    (2)第二种方式,在父组件中:
<Demo ref="demo"/>
......
mounted(){
	this.$refs.xxx.$on('zmy', this.test)
}

(3) 若想让自定义事件只能触发一次,可以使用once修饰符,或$once方法
4. 触发自定义事件:this. $ emit('zmy', 数据)
5. 解绑自定义事件:this.$ off('zmy')
6. 组件上也可以绑定原生DOM事件,需要使用native修饰符
7. 注意:通过 this.$ refs.xxx.$ on('zmy', 回调) 绑定自定义事件时,回调要么配置在methods中,要么用箭头函数,否则this指向会出问题!

1.3 全局事件总线

1.3.1 理解

  1. 一种组件间通信的方式,适用于任意组件间通信
  2. Vue 原型对象上包含事件处理的方法
    (1) $on(eventName, listener): 绑定自定义事件监听
    (2) $emit(eventName, data): 分发自定义事件
    (3) $off(eventName): 解绑自定义事件监听
    (4) $once(eventName, listener): 绑定事件监听, 但只能处理一次
  3. 所有组件实例对象的原型对象的原型对象就是 Vue 的原型对象
    (1)所有组件对象都能看到 Vue 原型对象上的属性和方法
    (2) Vue.prototype.$bus = new Vue() ,所有的组件对象都能看到$bus 这个属性对象
  4. 全局事件总线
    (1)包含事件处理相关方法的对象(只有一个)
    (2)所有的组件都可以得到

1.3.2 指定事件总线对象

  1. 安装全局事件总线:
new Vue({
	......
	beforeCreate(){
		Vue.prototype.$bus = this//安装全局事件总线,$bus就是当前应用的vm
	},
	......
})
  1. 使用事件总线
    (1)接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身
methods(){
	demo(data){......}
}
......
mounted(){
	this,$bus.$on('xxx', this.demo)
}

(2)提供数据:this.$ bus.$ emit('xxx', 数据)

  1. 最好在 deforeDestroy 钩子中,用 $ off 去解绑当前组件所用到的事件

School.vue

<template>
    <div class="school">
      <h2>学校名称:{{ name }}</h2>
      <h2>学校地址:{{ address }}</h2>
    </div>
  </template>
  
  <script>
      export default {
          name: 'School',
          props: ['getSchoolName'],
          data(){
              return {
                  name: '西安文理',
                  address: '西安',
              }
          },
          mounted(){
            // console.log('School', this);
            this.$bus.$on('hello',(data) => {
              console.log('我是School组件, 收到了数据', data);
            })
          },
          beforeDestroy(){
            this.$bus.$off('hello')
          }
      }
  </script>
  
  <style scoped>
    .school {
      background-color: skyblue;
      padding: 5px;
    }
  </style>

Student.vue

<template>
  <div class="student">
    <h2>学生名称:{{ name }}</h2>
    <h2>学生性别:{{ sex }}</h2>
    <button @click="sendStudentName">把学生名给School组件</button>
  </div>
</template>

<script>
    export default {
        name: 'Student',
        data(){
            return {
                name: '张三',
                sex: '男',
            }
        },
        methods: {
          sendStudentName(){
            this.$bus.$emit('hello', this.name)
          }
        }
    }
</script>
<style lang="less" scoped>
  .student {
    background-color: orange;
    padding: 5px;
    margin-top: 30px;
  }
</style>

App.vue

<template>
    <div class="app">
        <h1>{{ msg }}</h1>
        <School/>
        <Student/>
    </div>
  </template>
  
  <script>
      import Student from './components/Student.vue'
      import School from './components/School.vue'
      export default {
          name: 'App',
          components: {School, Student},
          data(){
            return {
                msg: '你好啊',
                studentName:''
            }
          },
        }
  </script>

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

main.js

//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
//关闭Vue的生产提示
Vue.config.productionTip = false

/* const demo = Vue.extend({})
const d = new demo()           */                            


//创建vm
new Vue({
    el: '#app',
    render: h => h(App),
    beforeCreate(){
        Vue.prototype.$bus = this //安装全局事件总线
    }
})

本地存储、自定义事件、全局事件总线、消息订阅与发布【Vue】_第1张图片

1.4 消息的订阅与发布

  1. 一组组件间通信的方式,适用于任意组件通信
  2. 使用步骤:
    (1)安装 pubsub:npm i pubsub-js
    (2)引入:import pubsub from 'pubsub-js'
    (3)接收数据:A组件想接收数据,则在A组件中订阅消息,订阅回调留在A组件自身
methods(){
	demo(data) {......}
}
......
mounted() {
	this.pid = pubsub.subscribe('xxx', this.demo)//订阅消息
}

(4)提供数据:pubsub.publish('xxx', 数据)
(5)最好在beforeDestroy钩子中,用PubSub.unsubscribe(pid)去取消订阅

本地存储、自定义事件、全局事件总线、消息订阅与发布【Vue】_第2张图片
本地存储、自定义事件、全局事件总线、消息订阅与发布【Vue】_第3张图片

1.5 使用 PubSubJS

  1. 在线文档: https://github.com/mroderick/PubSubJS
  2. 下载: npm install -S pubsub-js
  3. 相关语法
    (1) import PubSub from 'pubsub-js' // 引入
    (2) PubSub.subscribe(‘msgName’, functon(msgName, data){ })
    (3) PubSub.publish(‘msgName’, data): 发布消息, 触发订阅的回调函数调用
    (4) PubSub.unsubscribe(token): 取消消息的订阅

1.6 nextTick

  1. 语法:this.nextTick(回调函数)
  2. 作用:在下一次DOM更新结束后执行其指定的回调
  3. 什么时候用:当改变数据后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行。

1.7 Vue封装的过度与动画

  1. 作用:在插入、更新或移除DOM元素时,在合适的时候给元素添加样式类名

  2. 图示:
    本地存储、自定义事件、全局事件总线、消息订阅与发布【Vue】_第4张图片

  3. 写法:
    (1)准备好样式:

  • 元素进入的样式:
    1. v-enter:进入的起点
    2. v-enter-active:进入过程中
    3. v-enter-to:进入的终点
  • 元素离开的样式:
    1. v-leave:离开的起点
    2. v-leave-active:离开过程中
    3. v-leave-to:离开的终点
      (2)使用 < transition >包裹要过度的元素,并配置name属性:
<transition name="hello">
	<h1 v-show="isShow">你好啊!</h1>
</transition>
  1. 备注:若有多个元素需要过度,则需要使用:< transition-group >,且每个元素都要指定key

Tset.vue

<template>
  <div>
    <button @click="isShow = !isShow">显示/隐藏</button>
    <transition name="hello" appear>
        <h1 v-show="isShow">你好啊</h1>
    </transition>
  </div>
</template>

<script>
    export default {
        name: 'Test',
        data(){
            return {
                isShow: true
            }
        },

    }
</script>

<style scoped>
    h1{
        background-color: orange;
    }

    .hello-enter-active{
        animation: aaa 0.5s linear;
    }

    .hello-leave-active{
        animation: aaa 0.5s linear reverse;
    }

    @keyframes aaa {
        from{
            transform: translateX(-100%);
        }
        to{
            transform: translateX(0px);
        }
    }
</style>

Tset2.vue

<template>
  <div>
    <button @click="isShow = !isShow">显示/隐藏</button>
    <transition-group name="hello" appear>
        <h1 v-show="!isShow" key="1">你好啊</h1>
        <h1 v-show="isShow" key="2">aaa</h1>
    </transition-group>
  </div>
</template>

<script>
    export default {
        name: 'Test',
        data(){
            return {
                isShow: true
            }
        },

    }
</script>

<style scoped>
    h1{
        background-color: orange;
    }
    /* 进入的起点 离开的终点*/
    .hello-enter, .hello-leave-to{
        transform: translateX(-100%);
    }

    .hello-enter-active, .hello-leave-active{
        transition: 0.5s linear;

    }

    /* 进入的终点 离开的起点*/
    .hello-enter-to, .hello-leave{
        transform: translateX(0);
    }
</style>

Tset3.vue

<template>
  <div>
    <button @click="isShow = !isShow">显示/隐藏</button>
    <transition-group name="animate__animated animate__bounce" appear enter-active-class="animate__swing" leave-active-class="animate__backOutUp">
        <h1 v-show="!isShow" key="1">你好啊</h1>
        <h1 v-show="isShow" key="2">aaa</h1>
    </transition-group>
  </div>
</template>

<script>
    import 'animate.css'
    export default {
        name: 'Test',
        data(){
            return {
                isShow: true
            }
        },

    }
</script>

<style scoped>
    h1{
        background-color: orange;
    }
</style>

App.vue

<template>
    <div>
        <Test></Test>
        <Test2></Test2>
        <Test3></Test3>
    </div>
</template>
  
  <script>
      import Test from './components/Test.vue'
      import Test2 from './components/Test2.vue'
      import Test3 from './components/Test3.vue'


      export default {
          name: 'App',
          components: {Test, Test2, Test3},
        
      }
  </script>


main.js

//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
//关闭Vue的生产提示
Vue.config.productionTip = false

//创建vm
new Vue({
    el: '#app',
    render: h => h(App),
    beforeCreate(){
        Vue.prototype.$bus = this
    }
})

你可能感兴趣的:(vue.js,javascript,前端,前端框架)