Vue脚手架Ⅲ(浏览器本地存储,Vue中的自定义事件,全局事件总线,消息订阅与发布(pubsub),nextTick,Vue封装的过度与动画)

9 篇文章 0 订阅

脚手架

3.10 浏览器本地存储

js 就有这个功能,没必要在.vue里面分析,不用脚手架,直接在htnl文件。

webStorage

sessionStorage 和 localStorage 统称为 webStorage

  1. 存储内容大小一般支持5MB左右(不同浏览器可能还不一样)

  2. 浏览器端通过 Window.sessionStorage 和 Window.localStorage 属性来实现本地存储机制。(可以对比游戏存档,如果想关闭后第二天接着之前的玩就是localStorage)

  3. 相关API:

    1. xxxxxStorage.setItem('key', 'value');
      该方法接受一个键和值作为参数,会把键值对添加到存储中,如果键名存在,则更新其对应的值。(设置)

    2. xxxxxStorage.getItem('person');

      ​ 该方法接受一个键名作为参数,返回键名对应的值。(读取)

    3. xxxxxStorage.removeItem('key');

      ​ 该方法接受一个键名作为参数,并把该键名从存储中删除。

    4. xxxxxStorage.clear()

      ​ 该方法会清空存储中的所有数据。

  4. 备注:

    1. SessionStorage存储的内容会随着浏览器窗口关闭而消失。(Session 会话控制 这里就是 会话结束了就关闭消失了)
    2. LocalStorage存储的内容,需要手动清除才会消失。(浏览器关闭了数据也不会消失)
    3. xxxxxStorage.getItem(xxx)如果xxx对应的value获取不到,那么getItem的返回值是null。
    4. JSON.parse(null)的结果依然是null。

例:搜索里面搜东西时,下面就会出现之前搜索过的

在这里插入图片描述

案例:
localStorage.html

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>localStorage</title>
	</head>
	<body>
		<h2>localStorage</h2>
		<button onclick="saveData()">点我保存一个数据</button>
		<button onclick="readData()">点我读取一个数据</button>
		<button onclick="deleteData()">点我删除一个数据</button>
		<button onclick="deleteAllData()">点我清空一个数据</button>

		<script type="text/javascript" >
			let p = {name:'张三',age:18}

			function saveData(){
				localStorage.setItem('msg','hello!!!')
				// 这个666显示的是黑色的,是字符(数字型转换成了字符型)(蓝色的显示是字符)
				localStorage.setItem('msg2',666)
				// 把对象变成字符串
				localStorage.setItem('person',JSON.stringify(p))
			}
			function readData(){
				console.log(localStorage.getItem('msg'))
				console.log(localStorage.getItem('msg2'))

				const result = localStorage.getItem('person')
				console.log(JSON.parse(result))

				// console.log(localStorage.getItem('msg3'))
			}
			function deleteData(){
				localStorage.removeItem('msg2')
			}
			function deleteAllData(){
				localStorage.clear()
			}
		</script>
	</body>
</html>

操作显示:

在这里插入图片描述

SessionStorage.html

把上面的代码中,搜索localStorage全部换成SessionStorage

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>sessionStorage</title>
	</head>
	<body>
		<h2>sessionStorage</h2>
		<button onclick="saveData()">点我保存一个数据</button>
		<button onclick="readData()">点我读取一个数据</button>
		<button onclick="deleteData()">点我删除一个数据</button>
		<button onclick="deleteAllData()">点我清空一个数据</button>

		<script type="text/javascript" >
			let p = {name:'张三',age:18}

			function saveData(){
				sessionStorage.setItem('msg','hello!!!')
				sessionStorage.setItem('msg2',666)
				sessionStorage.setItem('person',JSON.stringify(p))
			}
			function readData(){
				console.log(sessionStorage.getItem('msg'))
				console.log(sessionStorage.getItem('msg2'))

				const result = sessionStorage.getItem('person')
				console.log(JSON.parse(result))

				// console.log(sessionStorage.getItem('msg3'))
			}
			function deleteData(){
				sessionStorage.removeItem('msg2')
			}
			function deleteAllData(){
				sessionStorage.clear()
			}
		</script>
	</body>
</html>

显示:

在这里插入图片描述

3.11 Vue中的自定义事件

  1. 一种组件间通信的方式,适用于:子组件 ===> 父组件

  2. 使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中)。

  3. 绑定自定义事件:

    1. 第一种方式,在父组件中:<Demo @atguigu="test"/><Demo v-on:atguigu="test"/>

    2. 第二种方式,在父组件中:

      <Demo ref="demo"/>
      ......
      mounted(){
         this.$refs.xxx.$on('atguigu',this.test)
      }
      
    3. 若想让自定义事件只能触发一次,可以使用once修饰符,或$once方法。

  4. 触发自定义事件:this.$emit('atguigu',数据)

  5. 解绑自定义事件this.$off('atguigu')

  6. 组件上也可以绑定原生DOM事件,需要使用native修饰符。

  7. 注意:通过this.$refs.xxx.$on('atguigu',回调)绑定自定义事件时,回调要么配置在methods中,要么用箭头函数,否则this指向会出问题!

案例:
(思路书写顺序在代码中)

App.vue

<template>
	<div class="app">
		<h1>{{msg}},学生姓名是:{{studentName}}</h1>
		<!--方法1:通过父组件给子组件传递函数类型的props实现:子给父传递数据

			使用props把子传给父 自定义事件 :getSchoolName( 1 事件的绑定在绑定的组件里面去执行) 调用回调函数getSchoolName( 2 调用的回调函数在当前组件执行)-->
		<School :getSchoolName="getSchoolName"/>

		<!-- 方法2:通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第一种写法,使用@或v-on) 
		1 给Student绑定一个自定义事件(使用@自定义名="回调函数")
		2 去子组件Student里面对atguigu告知一个这个事件是干嘛的(通过点击事件执行sendStudentName从而执行atguigu)
		3 在sendStudentName里面去触发Student组件实例身上的atguigu事件(通过$emit),里面的参数会传给atguigu到父组件
		4 最后父组件App里面就会收到传给atguigu的参数,执行此时的回调函数getStudentName
		-->
		<!-- <Student @atguigu="getStudentName"/> -->

		<!-- 方法3:通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第二种写法,使用ref) 
		1 先用ref定位到当前Student(相当于js里面id dom)
		2 在当前组件里面使用挂起,绑定自定义事件
		3 子组件里面依然使用上面方法2里面的后面方法  触发Student组件实例身上的atguigu事件
		-->
		<Student ref="student"/>
	</div>
</template>

<script> 
	import School from './components/School'
	import Student from './components/Student'
	export default {
		name: 'App',
		components:{School,Student},
		data() {
			return {
				msg:'你好啊!',
				studentName:''
			}
		},
		methods: {
			getSchoolName(name){
				console.log('App收到了学校名:',name)
			},
			// 第一个参数作为name形参接收 其他的参数全部整理到params数组身上(es6内容)
			getStudentName(name,...params){
				console.log('App收到了学生名:',name,params)
				this.studentName = name;
			},
		},
		mounted() {
			this.$refs.student.$on('atguigu',this.getStudentName) //绑定自定义事件
			// this.$refs.student.$once('atguigu',this.getStudentName) //绑定自定义事件(一次性)
		},
	}
</script>

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

Student.vue

<template>
    	<div class="student">
			<h2>学生姓名:{{name}}</h2>
			<h2>学生性别:{{sex}}</h2>
			<h2>当前求和为:{{number}}</h2>
			<button @click="add">点我加1</button>
            <!-- 通过点击事件执行sendStudentName从而去执行atguigu -->
            <button @click="sendStudentName">把学生名给App</button>
            <button @click="unbind">解绑atguigu事件</button>
            <button @click="death">销毁当前Student组件的实例(vc)</button>
		</div>
</template>

<script>
export default {
    name: 'Student',
    data(){
        return {
            name:'张三',
            sex:'男',
            number: 0,
        }
    },
    methods:{
        add(){
            console.log("add回调被调用了");
            this.number++; // 要拿到data里面的number,要用this,不然会报错显示number未定义
        },
        sendStudentName(){
            this.$emit('atguigu',this.name,666,777,888);
        },
        unbind(){
            // 解绑atguigu事件
            this.$off('atguigu');
        },
        death(){
            this.$destroy();
        }
    }
}
</script>

<style lang="less" scoped>
	.student{
		background-color: pink;
		padding: 5px;
		margin-top: 30px;
	}
</style>

School.vue

<template>
    <div class="school">
		<h2>学校名称:{{name}}</h2>
		<h2>学校地址:{{address}}</h2>
        <!-- 通过点击事件执行sendSchoolName去执行getSchoolName事件,再把getSchoolName执行的结果参数传回到父组件 -->
		<button @click="sendSchoolName">把学校名给App</button>

	</div>
</template>

<script>
export default {
    name:'School',
    // 子传父  传一个参数给getSchoolName
	props:['getSchoolName'],
	data() {
		return {
			name:'尚硅谷',
			address:'北京',
		}
	},
    methods:{
        sendSchoolName(){
            this.getSchoolName(this.name);
        }
    }
	
}
</script>

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

效果
在这里插入图片描述

3.12 全局事件总线

任意组件间通信

  1. 一种组件间通信的方式,适用于任意组件间通信。

  2. 安装全局事件总线:

bus 有总线的意思

new Vue({
	......
	beforeCreate() {
		Vue.prototype.$bus = this //安装全局事件总线,$bus就是当前应用的vm  全局都能看到这个$bus 
	},
    ......
}) 
  1. 使用事件总线:

    1. 接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身。

      methods(){
        demo(data){......}
      }
      ......
      mounted() {
        this.$bus.$on('xxxx',this.demo)
      }
      
    2. 提供数据:this.$bus.$emit('xxxx',数据)

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

在这里插入图片描述

如上图,我们通过一个x作为中间商,我们需要的是:

  1. 要让其他的人都能看到x (在js里面定义,我们用$bus)

  2. 能调用到 $on $off $emit

案例:(Student组件 提供数据给 School组件)

思路分析

  1. 先安装全局事件总线在main.js
  2. 弄清楚谁收数据谁发数据
  3. 收数据的人去绑定事件总线(mount一挂载就绑定最合适)
    this.$bus找到全局事件总线this.$bus.$on给他绑定一个hello事件,如果有一天这个hello事件触发,就会调用后面的回调函数
    mounted() {
     		this.$bus.$on('hello',(data)=>{
     			console.log('我是School组件,收到了数据',data)
     		})
     	},
    
  4. 在组件即将销毁的时候解绑,在当前的组件使用beforeDestroy
  5. 收数据的写完之后,就去发数据的组件写。在发数据的人那里去触发这个事件,this.$bus找到这个人,this.$bus.$emit去触发这个hello事件,然后把后面的this.name带过去
    methods: {
     		sendStudentName(){
     			this.$bus.$emit('hello',this.name)
     		}
     	},
    

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 //安装全局事件总线
	},
})

School.vue

<template>
	<div class="school">
		<h2>学校名称:{{name}}</h2>
		<h2>学校地址:{{address}}</h2>
	</div>
</template>

<script>
	export default {
		name:'School',
		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:'男',
			}
		},
		mounted() {
			// console.log('Student',this.x)
		},
		methods: {
			sendStudentName(){
				this.$bus.$emit('hello',this.name)
			}
		},
	}
</script>

<style lang="less" scoped>
	.student{
		background-color: pink;
		padding: 5px;
		margin-top: 30px;
	}
</style>

beforeCreate生命周期钩子 最开头的 这个时候模板还没有解析,借助这个,把要做的做好了,原型放好了,模板就开始解析。其实等子组件School执行的时候,该放的东西也放好了

所有人都在用$bus 以后要是不用了,占用着不好,所以需要销毁 使用beforeDestroy

有$bus 想得数据得数据,想发数据发数据

父传子的时候我们还是用props比较方便

3.13 消息订阅与发布(pubsub)

需要数据的订阅消息,提供数据的发布消息。一般在vue里面用的很少,因为可以使用全局事件总线

pubsub — publish subscribe

  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)去取消订阅。

3.14 nextTick

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

3.15 Vue封装的过度与动画

案例:(左右隐藏显示效果)

在这里插入图片描述

3.15.1 动画效果

  1. 先写出普通结构效果

Test.vue

在这里插入图片描述

App.vue

在这里插入图片描述

目前实现的效果是简单的隐藏和显示,没有移动效果

  1. 写出动画效果

不用写两个动画,进入离开,写一个就行,写来,另外一个反着就行

Test.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: atguigu 0.5s linear;
	}
/* 离开时激活 */
	.hello-leave-active{
		animation: atguigu 0.5s linear reverse;
	}

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

3.15.2 过度效果

Test2.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">尚硅谷!</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>

3.15.3 多个元素过度

使用transition-group 和 key值

3.15.4 集成第三方动画

使用npm里面的库,搜索animate.css,这是一个成型库,开箱即用

在这里插入图片描述

在这里插入图片描述

往下翻之后,按照流程

在这里插入图片描述

使用

Test3.vue

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

效果

在这里插入图片描述

3.15.5 总结过度和动画

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

  2. 图示:

在这里插入图片描述

  1. 写法:

    1. 准备好样式:(自己写或者使用第三方库)

      • 元素进入的样式:
        1. v-enter:进入的起点
        2. v-enter-active:进入过程中
        3. v-enter-to:进入的终点
      • 元素离开的样式:
        4. v-leave:离开的起点
        5. v-leave-active:离开过程中
        6. v-leave-to:离开的终点
    2. 使用<transition>包裹要过度的元素,并配置name属性:

      <transition name="hello">
      	<h1 v-show="isShow">你好啊!</h1>
      </transition>
      
    3. 备注:若有多个元素需要过度,则需要使用:<transition-group>,且每个元素都要指定key值。

下一个笔记第四章了,有关Vue中的ajax
,加油加油码代码!!!!v🍜🍛🍚🍤🦪

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值