Vue2学习文档2

12. 内置指令

P40 v-text

……

P41 v-html

v-html比起v-text来说可以解析html标签

image-20210818170229065

PS:这一节还讲到一个很有趣的东东,xss攻击,具体看视频吧

P42 v-cloak

需要配合css使用,v-cloak是只有Vm加载时才会消失,所以配合display:none 可以实现js堵塞时,不会出现混乱 的html内容

image-20210818171356017

P43 v-once

只进行初始化渲染,后面就变成静态内容

P44 v-pre

跳过节点编译过程,提高性能

12a.自定义指令

P45 函数式

image-20210824184131587

p:这里改变了元素的内容

P46 对象式

首先补充下原生dom操作

<title>Document</title>

<style>
	.demo{
		background-color: orange;
	}
</style>

<script type="text/javascript" >
	const btn = document.getElementById('btn')
	btn.onclick = ()=>{
		const input = document.createElement('input')
		//以下操作可以放元素加载(插入页面)之前
		input.className = 'demo'  
		input.value = 99
		input.onclick = ()=>{alert(1)} 
		//元素插入页面
		document.body.appendChild(input)
		//必须要在元素插入后,进行focus方法
		input.focus()
	}
</script>

正文

<body>
	<div id="root">
		<h2>当前的n值是:<span v-text="n"></span> </h2>
		<h2>放大10倍后的n值是:<span v-big="n"></span> </h2> /P:绑定了big自定义事件
		<button @click="n++">点我n+1</button>
		<hr/>
		<input type="text" v-fbind:value="n"> //P:绑定了fbind自定义事件
	</div>
</body>

<script type="text/javascript">
	new Vue({
        data:{
			n:1
		},
		directives:{
			big(element,binding){
				console.log('big',this) //注意此处的this是window
				element.innerText = binding.value * 10
			},
			fbind:{ 
                //P:以下操作可以顺序可以参考上面的dom操作
				//指令与元素成功绑定时(一上来)
				bind(element,binding){ //P:element是可以操作的原生dom
					element.value = binding.value
				},
				//指令所在元素被插入页面时
				inserted(element,binding){
					element.focus()
				},
				//指令所在的模板被重新解析时
				update(element,binding){
					element.value = binding.value
				}
			}
		}
	})
	
</script>

P47 总结

对上面两节的总结和一些其他补充

需求1:定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍。

需求2:定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的input元素默认获取焦点。

自定义指令总结

​ 一、定义语

​ (1).局部指令

​ new Vue({ new Vue({

​ directives:{指令名:配置对象} 或 directives{指令名:回调函数}

​ }) })

​ (2).全局指令:

​ Vue.directive(指令名,配置对象) 或 Vue.directive(指令名,回调函数)

​ 二、配置对象中常用的3个回调:p:就是完整的写法

​ (1).bind:指令与元素成功绑定时调用。

​ (2).inserted:指令所在元素被插入页面时调用。

​ (3).update:指令所在模板结构被重新解析时调用。

​ 三、备注:

​ 1.指令定义时不加v-,但使用时要加v-;

​ 2.指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名。

//这里只展示补充的,完整代码要结合上两节
<div id="root">
	<h2>当前的n值是:<span v-text="n"></span> </h2>
	<h2>放大10倍后的n值是:<span v-big-number="n"></span> </h2> 
    //多个单词指令名要采用kebab-case方式
	<button @click="n++">点我n+1</button>
	<hr/>
	<input type="text" v-fbind:value="n">
</div>
    
<script type="text/javascript">
	//定义全局指令
	 Vue.directive('fbind',{
		//指令与元素成功绑定时(一上来)
		bind(element,binding){
			element.value = binding.value
		},
		//指令所在元素被插入页面时
		inserted(element,binding){
			element.focus()
		},
		//指令所在的模板被重新解析时
		update(element,binding){
			element.value = binding.value
		}
	}) 

	new Vue({
		data:{
			n:1
		},
		directives:{
		    'big-number':(element,binding){ //P:冒号可以加可以不加,不知道为什么可以不加?
				element.innerText = binding.value * 10
			}, 
		}
	})
</script>    

13. 生命周期

P48 周期介绍

生命周期就是组件的”一生"

后P内容也需参考下图

image-20210819145636862

P49 挂载流程

具体内容看流程图和视频

这节主要讲了两个点可以了解下:Vue.template和vm.$mount

这两个点会影响周期的过程和挂载内容(具体看视频)

image-20210819145636862

这节讲到初始化过程为止(mouted之前)

P50 更新流程

数据更新了触发,对新旧虚拟DOM比较,更新页面

beforeUpdate数据页面尚未同步

Upated数据页面同步

如图:

image-20210819161619871

P51 销毁流程

vm.$destroy触发

官网这里所写的事件监听器是指自定义的事件,不包括像onclick这样的dom原生事件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q2cZjZE7-1652603393459)(Images/image-20210819161236275.png)]

在beforeDestroy()中修改数据,虽然改了但不会更新到页面的,直接进入destroy()

销毁钩子:

image-20210819161517781

P52 总结

如图

image-20210819163903920

14. 组件

P53 对组件的理解

组件的定义:实现应用中局部功能代码(HTML\JS\CSS)和资源(MP3\IMG\FONT)的集合

作用:复用js,简化js的编写,提高js运行效率

名词解释

  • 模块化

当应用中的js都以模块来编写,那这个应用就是一个模块化的应用

  • 组件化

当应用中功能都是多组件的方式来编写的,这个应用就是一个模块化的应用

image-20210819170645359

如上图可以看出组件化是包括模块化的(毕竟js文件是包括在组件里的)

P54 非单文件组件

非单文件和单文件区别

image-20210819173515044

单文件组件

image-20210819173330866

P55 组件注意点

可以使用name配置项指定组件在开发者工具中呈现的名字(如果没有指定,就按注册名来 )

在开发大型组件和第三方库是可以用到name,感觉主要还是为了语义化

image-20210819175559241

P56 组件嵌套

例子

image-20210819190901958

Root是vm之下,万件之上的“宰相”

P57 VueComponent

如图

image-20210819192956920

P58 Vue实例与组件实例

vc和vm虽然很像,但还是有些点不同

  1. vm里的el,vc没有,
  2. vm能写data:{},vc不能写
image-20220515093136794

P59 内置关系(js补充)

首先要明白JS原型链

image-20210820105501182

内置关系

image-20210820105143818

P60 单文件组件

name最好还是加上,不然调试工具里的名字会按,import的name来展示

image-20210820135201566

Main.js中import App组件不用脚手架不行,因为浏览器不支持es6模块化语法。

这节简单过了一遍脚手架的基本解析流程,整理了main.js\html\app.vue\others.vue间的关系

15. 脚手架

P61 创建脚手架

npm install -g @vue/cli ##全局安装vuecli
vue create xxxx ##创建项目-切换到创建项目的目录
npm run serve ##启动项目-

补充

  • 下载缓慢解决

配置npm淘宝镜像:npm config set registry https://registry.npm.taobao.org

5:35 淘宝镜像

old note

babel文件的作用是把es6转成es5

package-lock.json的功能是锁定包管理版本

P62 分析脚手架

<%= BASE_URL %>就是指从public文件夹下找(防止写./…/这些时出现各种问题,用这个保险hh)

image-20210820151928099

基础脚手架的内容除了render都介绍了

P63 render函数

main.js

如图:这节讲到一些node_modules-vue里内容

image-20210820155247600

App.vue

组件里的template则有这个框架解析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Mw020MYb-1652603393460)(Images/image-20210820155525758.png)]

P64 修改默认配置

vue.config.js(修改配置,可选)

webpack基于Nodejs,node用的就是commonjs暴露方法,所以 vue.config.js用的是module.export

vue.config.js修改了一定要重启

语法检查(公司没规定可以关闭,不然影响编程效率)

在配置文件中加这段可以取消“烦人”的语法检查

image-20210820162250024

16. 组件配置项

P65 ref属性

本来用document.getElementid() 就能实现,但如果要获取的是完整Vue组件的话,就需要使用ref

image-20210820172114521

P66 props配置

vue组件属性值必须要加(key-‘value’)[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g0xDKnwo-1652603393461)(Images/image-20210820185309566.png)]

加了v-bind才能写数值,因为这里是表达式[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6mPUbpZF-1652603393462)(Images/image-20210820185532122.png)]

三种写法如图:

image-20210820193708201

P67 mixin混入

PS:混合就是公用vue配置,用js文件来写对象(一般都是统一或者部分暴露)

image-20210821113032876

P68 插件

以Vue构造函数为参数,可以实现全局属性的集合(过滤器、指令、混入 ……)

具体如图:

image-20210821140219788

P69 scoped样式

Vue cli 用的webpack版本是4.x[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Po3m62RW-1652603393463)(Images/image-20210821142131581.png)],而有些插件(less-loader)的最新版本是针对webpack5.x的,[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aWKeug6y-1652603393464)(Images/image-20210821142425822.png)]安装会报错,所以需要安装这些版本webpack4.x旧版(less-loader7.x)[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kBYSHNnk-1652603393467)(Images/image-20210821142336348.png)]

image-20210821142630567

17. TodoList案例

P70 静态

把传统html项目改为vue项目和拆分组件

P71 初始化列表

声明了一些state,并通过props传参

P73 添加

实现了添加方法,主要用到兄弟间通信最基础实现(状态提升)

补充

不使用v-model,用原生dom操作实现双向绑定

<input type="text" placeholder="请输入你的任务名称,按回车键确认" @keyup.enter="add"/> 
//这里使用了最原生的dom操作实现

props:['addTodo'],
methods: {
	add(e){
		const todoObj = {id:nanoid(),title:e.target.value,done:false
        //:e.target.value-获取到页面输入值
		this.addTodo(todoObj) 
		e.target.value = '' //这里直接赋值可以修改input-value,说实话没想到
	}
},

nanoid插件比uuid插件更轻量级

import {nanoid} from 'nanoid'
export default {
	methods: {
		add(){
			const todoObj = {id:nanoid(),title:this.title,done:false} 
            //数组对象的id需要保证为唯一值,不然b可能会
		}
	},
}

P74 删除

核心

deleteTode(id){
	this.todos =this.todos.filter(todo=>todo.id!==id) //filter不改变原数组
}
  • 原生确认框
handleDelete(id){
	if(confirm("确定删除吗?"){ //confirm是原生的对话框
		console.log(id)
	})
}

P75 底部统计

核心

donetotal(){
//使用reduce来统计已选项数
	const x =this.todos.reduce((pre,current)=>{ 
        //最后循环的return作为整个reduce()的return
		console.log("@",pre,current)
		return pre+(current.done?1:0) //return作为下次循环的pre
	},0)
    
//精简版
    return this.todos.reduce((pre,current)=>pre+(current.done?1:0),0)
}

P76 底部交互

code

1.MyFooter.vue
<template>
<label>
	<!-- <input type="checkbox" :checked="isAll" @change="checkAll"/> --> 
    <!-- 对于输入类型的节点:这两个方法可以用v-model简化--> 
	<input type="checkbox" v-model="isAll"/>
</label>
</template>
computed: {
	//总数
	total(){
		return this.todos.length
	},
	//已完成数
	doneTotal(){
		return this.todos.reduce((pre,todo)=> pre + (todo.done ? 1 : 0) ,0)
	},
	//控制全选框
	isAll:{ //配置v-model实现输入类型方法简写化
		get(){ 
			return this.doneTotal === this.total && this.total > 0 //计算属性套娃
		},
		set(value){
			this.checkAllTodo(value)
		}
	}
}

2.App.vue
todos:[
	{id:'001',title:'抽烟',done:true},
	{id:'002',title:'喝酒',done:false},
]
//清除所有已经完成的todo
clearAllTodo(){
	this.todos = this.todos.filter((todo)=>{ 
        //使用filter过滤-最优解
		return !todo.done
	})
}

P77 总结

正文

  • 文档
  1. props适用于:父子间通信
  2. v-model绑定的值不能props传过来的值,因为props是不可以修改的!??
  3. props传过来的若是对象类型的值,修改对象中的属性时Vue不会报错,但不推荐这样做。??

others

  • open in external app

可以让我们在vscode中右键直接打开md文件image-20220202121540883image-20220202121632658

注:但是试了下,没反应

P89 编辑 <-

code

1.MyItem.vue
<input 
	:value="todo.title" 
	@blur="handleBlur(todo,$event)" 
	//$event是关键词吗?有别的随便写的变量不同吗
	//P:随便查了下:说是可以获取到该事件的事件对象-应该是vue做处理过
	ref="inputTitle"
>   
//js
props:['todo'],
handleEdit(todo){ //编辑任务
	if(todo.hasOwnProperty('isEdit')){
        //注:这里没有用todo.isEdit,因为结果为空和”布尔值为假“都可以为false
        //hasOwnProperty-对象自身是否具有指定的属性
		todo.isEdit = true
	}else{
        //todo.isEdit = true-这写法数据能改变但Vue不会响应
		this.$set(todo,'isEdit',true) //添加对象属性的正确写法
        //P:有人可能会问为什么要怎么麻烦,直接一开始写好属性值不行吗?	
        //如果data传入数据有isEdit最好,没有的话还是要用到这种方法添加属性
	}
}
//失去焦点回调-真正执行修改逻辑
handleBlur(todo,e){
	todo.isEdit = false
	if(!e.target.value.trim()) //trim()-去除字符串的头尾空格
        return alert('输入不能为空!')
	this.$bus.$emit('updateTodo',todo.id,e.target.value)
}

P90 $nextTick <-

code

<span v-show="!todo.isEdit">{{todo.title}}</spa>n>
<input  v-show="todo.isEdit" ref="inputTitle">
<button @click="handleEdit(todo)">编辑</button>

handleEdit(todo){
	……
    //this.$refs.inputTitle.focus()-失效,因为Vue的处理逻辑是先执行方法再重新编译
    //虽然todo.isEdit已经是true了,但是模板还没有编译,页面还没"v-show"<input\>元素
    
	this.$nextTick(function(){ //nextTick能让其回调函数在DOM更新后执行
		this.$refs.inputTitle.focus()//获取input焦点
	})
},

正文

  • 文档
  1. 作用:在下一次 DOM 更新后执行其指定的回调
  2. 什么时候用:当改变数据后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行。(感觉就是看当前语句执行要不要依赖”基于之前语句更新后"的dom

18. 本地存储

P78 浏览器本地存储

code

<!-- localStorage和sessionStorage的api相同-只是生命周期不一样--> 
<!DOCTYPE html>
<html>
    <body>
		<h2>localStorage</h2>
		<button onclick="saveData()">点我保存一个数据</button>
         <!-- html文件里的标签绑定事件不能省略“()”--> 
		<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!!!')//修改和新增数据
                //这里还省略了windows-应该是html是默认从window上找方法
				localStorage.setItem('msg2',666)
                //如果不是String类型,浏览器也会自动进行String转换
				localStorage.setItem('person',JSON.stringify(p))
                //注:这个要stringify转换下,不然浏览器把对象类型自动String转换-value会变为[Object Object]
			}
			function readData(){
				console.log(localStorage.getItem('msg'))//获取数据
				console.log(localStorage.getItem('msg2'))
				const result = localStorage.getItem('person')
                //const result2 = localStorage.getItem('person2')
 				//如果person2对应的value获取不到,那么getItem的返回值是null。
				console.log(JSON.parse(result))
                //console.log(JSON.parse(person2))
                //JSON.parse(null)的结果依然是null。
			}
			function deleteData(){
				localStorage.removeItem('msg2')//删除数据
			}
			function deleteAllData(){
				localStorage.clear()//清空数据
			}
		</script>
	</body>
</html>

正文

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

  2. 浏览器端通过 Window.sessionStorage 和 Window.localStorage 属性来实现本地存储机制。

  3. 相关API:

    1. Storage.setItem('key', 'value');该方法接受一个键和值作为参数,会把键值对添加到存储中,如果键名存在,则更新其对应的值。
    2. Storage.getItem('person');该方法接受一个键名作为参数,返回键名对应的值。
    3. Storage.removeItem('key');该方法接受一个键名作为参数,并把该键名从存储中删除。
    4. Storage.clear()该方法会清空存储中的所有数据。
  4. 备注:

    1. SessionStorage存储的内容会随着浏览器窗口关闭而消失。
    2. LocalStorage存储的内容,需要手动清除才会消失。(浏览器设置or引导用户点击删除按钮)

others

  • 控制台storage几个常用操作
image-20220202134632428

P79 本地存储

code

<div class="todo-wrap">
	<MyHeader :addTodo="addTodo"/>
	<MyList :todos="todos" ……/>
	<MyFooter :todos="todos" ……/>
</div>
export default {
	data() {
		return {
			todos:JSON.parse(localStorage.getItem('todos')) || [] //对于没有数据的情况要给个初始值,不然容易报错-undefined
		}
	},
	watch: {
		todos:{ 
			deep:true,//这个的监听属性要使用完整写法来深度拷贝-否则不能更新到{{isDone:value}}的数据
			handler(value){
				localStorage.setItem('todos',JSON.stringify(value))
                //这里没可以省略window-??html\vue为什么能省略window
			}
		}
	},
}

19. 组件自定义事件

P80 绑定

code

子向父传参推荐使用自定义事件,代码更简洁,更符合模式

1.App.vue(父组件)
<h1>{msg}},学生姓名是:{{studentName}}</h1>
<School :getSchoolName="getSchoolName"/>
<!-- props实现 -->
<Student @atguigu="getStudentName" />
<!-- getStudentName是作为事件的回调??去使用 -->
<!-- 自定义事件实现-第一种写法 -->
<Student ref="student" @click.native="show"/>
<!-- 自定义事件实现-第二种写法,p:虽然写法复杂,但是更灵活如搞个定时器 -->
<script>
	export defaul t {
		studentName:''
        //methods
		getSchoolName(name){
            	this.studentName = name //School.vue
			},
		getStudentName(name,...params){
				//...params是es6-把后面的参数都放在一个数组[x,y,]
				this.studentName = name //Student.vue
			},
		show(){
				alert(123)
			}
		mounted() {			
           setTimeout(()=>{
               this.$refs.student.$on('atguigu',this.getStudentName) 
            //用$refs绑定自定义事件-如果是$once则为一次性事件
		},
           },3000 )
	}
</script>

2.School.vue(子组件-使用prop)
<button @click="sendSchoolName">把学校名给App</button>
<script>
	export default {
		props:['getSchoolName'],//props方法需要接收
		name:'尚硅谷',
        //methods
		sendSchoolName(){
			this.getSchoolName(this.name)
		},
	}
</script>

3.Student.vue(子组件-使用自定义事件)
<h2>学生姓名:{{name}}</h2>
<button @click="sendStudentlName">把学生名给App</button>
<script>
	export default {
			name:'张三',
        	//methods
			sendStudentlName(){
				this.$emit('atguigu',this.name,666,888,900)
                //触发Student组件实例身上的atguigu事件
			},
	}
</script>

正文

  • 自定义和原生JS事件区别

一个给html元素,一个给组件image-20220202145017217

P81 解绑

code

//3.Student.vue-P80 code
<h2>学生姓名:{{name}}</h2>
<h2>当前求和为:{{number}}</h2>
<button @click="add">点我number++</button>
<button @click="unbind">解绑atguigu事件</button>
<button @click="death">销毁当前Student组件的实例(vc)</button>
<script>
	export default {
			name:'张三',
			number:0
        	//methods
			add(){ //组件销毁后原生dom事件依然能使用-只是没响应了??
				this.number++
			},
			unbind(){
				this.$off('atguigu') //解绑一个自定义事件
				// this.$off(['atguigu','demo'])-解绑多个
				// this.$off()-解绑所有
			},
			death(){
				this.$destroy() 
                //销毁了当前Student组件的实例-实例的自定义事件全都不奏效。     
			}
	}
</script>

正文

  • $destroy销毁副作用

image-20220202155443647如图也能销毁绑定的自定义事件等等,并且销毁组件会联并销毁子组件

P82 总结

code

1.app.vue
<!--<Student ref="student" @click="show"/>-->
<!-- click是给html元素使用的,如果给组件绑定vue会处理为自定义事件 -->
<!-- 如果要触发这click方法只能用自定事件那套语法 -->
<Student ref="student" @click.native="show"/>
<!-- 加native才能让组件绑定原生事件 -->
show(){
	alert("show")
}

2.student.vue
<template>
	<div class="student">
	</div>
    <!--<div/>-->
    <!-- 不能有两个跟组件的部分原因-如果有两个跟组件像上面的click.native事件就不知道该绑定到哪个标签上了 -->
</template>    

正文

  • 自定义事件原则-给谁绑定事件就找谁触发事件

  • 文档

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

2.绑定自定义事件:

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

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

<Demo ref="demo"/>
......
mounted(){
   this.$refs.xxx.$on('atguigu',this.test)
}

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

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

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

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

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

//这是一种正确写法
this.$refs.student.$once('atguigu',(name,...params)=>{
    console.log('App收到了学生名:',name,params)
    this.studentName = name
})

P83 Todo案例

……

P:这些p看下来发现可能自定义事件props函数,写法都差不多呀,就是自定义事件的话可以不用**接收函数props:[‘fn1’]**这样。

因为自定义函数实际上是给子组件绑定了一个自定义事件,真正起作用的是里面的回调函数,而且这个函数还是定义在父组件的。

others

  • 开发者工具看自定义事件
image-20220202212152787

20. 事件总线

P84 全局事件总线1

正文

  • 全局事件总线作用-任意组件间通信
image-20220204132722224
  • 全局事件总线实现前提

1.所有组件都能访问

2.能使用**$on、off、emit**

  • explore

想到使用window

//window.x={a:1,b:2}

这样不好一般来说没人会在window上面放东西

想到使用vc的原型对象VueComponents

//VueComponent.prototype.x={a:1,b:2}

这样写报错undefined,因为VueComponents构造函数是vue.extend生成的(不能直接使用,应该是vue自动调用了-在每一次创建组件时)

每次调用vue.extend,返回的都是一个的VueComponent

那直接在源码改呢?-执行力很强的杠精

//vue.runtime.esm.js-源码
var Sub=function VueComponent(options){
    this._init(options)
}
//Sub.prototype.x={a:1,b:2}

这样改是有效的,但是太离谱

发现一个重要的内置关系VueComponent.prototype._proto_===Vue.prototype??

这个关系可以让vc(组件实例对象)直接访问Vue原型上的属性和方法

image-20220204134837908
//正解
1.main.js
import Vue from 'vue'
Vue.prototype.x={a:1,b:2}

2.School.vue
mounted(){
    console.log("school",this.x)
}

P85 全局事件总线2

code

image-20220204144729489

1.main.js
import Vue from 'vue'
import App from './App.vue'

//使用vc实现
//const Demo =Vue.extend({})
//const demo=new Demo()
//Vue.prototype.x=demo-d就是vc

//使用vm-更标准更简化
new Vue({
	el:"#app",
    render:h=>h(App),
    beforeCreate(){ 
        //添加$bus需要在Vue构建函数中并用到beforeCreate
        Vue.prototype.$bus=this //安装全局事件总线
        //为什么叫总线-bus还有总线的意思
    }
})


2.school.vue
mounted(){
   this.$bus.$on('hello',data=>{
    console.log("定义了全局自定义事件hello",data)
	}) 
}
beforeDestroy(){
    this.$bus.$off('hello')  
    //注:这里必须要解绑-因为自定义事件是定义在vm上的、作用全局
}

3.student.vue
this.$bus.$emit('hello',{a:1}) //调用全局自定义事件并提供数据

P86 Todo案例

code

1.main.js
new Vue({
	el:'#app',
    render:h=>h(App),
    beforeCreate(){
        Vue.prototype.$bus=this //安装全局总线
    }
})

2.App.vue //定义和解绑事件 
mounted(){
    this.$bus.$on('checkTode',this.checkTode)
	this.$bus.$on('deleteTode',this.deleteTode)
}
beforeDestroy(){
    this.$bus.$off('checkTode')
    this.$bus.$off('deleteTode')
}  

3.MyItem.vue
handleCheck(id){
    this.$bus.$emit('checkTode',id)//触发事件
}

others

  • 控制台查看总线-一般是by**<Root>**
image-20220204153542090

21. 订阅与发布

P87 消息订阅与发布

5:20js原生不行用第三方库 10:20~订阅消息 11:09发布消息 - code 13:48>取消订阅 -文档 17:30总线和订阅选择

import pubsub from 'pubsub-js'
1.school.vue
this.pubId = pubsub.subscribe('hello',(msgName,data)=>{
 	console.log('有人发布了hello消息,hello消息的回调执行了',msgName,data)//msgName-订阅号名称
})//订阅消息
beforeDestroy() {
	pubsub.unsubscribe(this.pubId)//取消订阅-定时器一样有个id(pubId)
},

2.student.vue
sendStudentName(){
	pubsub.publish('hello',666) //发布消息
}

正文

  • 实现方式

原生比较难实现消息订阅与发布-需要用到第三方库 pubsub-js

  • 总线和订阅选择

禹神推荐使用总线,毕竟是vue2原生,实现写法和效果都大相径庭。

P:而且开发者工具监听$bus,订阅发布不行

others

  • 订阅(subscribe)、发布(publish

P88 Todo案例

……

P89-90->

other

  • 对于不用的形参可以用_充当占位符

deleteTode(_,id){xxx}

22. 过度与动画

P91 动画效果-

P92 过度效果-

P93 多个元素过度-

code

<transition-group > 
    <!-- 标签包涵多个元素需要用group,并记得加Key -->
	<h1 v-show="!isShow" key="1">你好啊!</h1>
    <h1 v-show="isShow" key="2">尚硅谷!</h1>
</transition-group>
<transition name="hello" appear><!-- appear-初始化时就出现动画 -->
    <!-- P:<transition>的原理应该是vue会自动解析class名称,遇到关键动画class就动态添加 -->
	<h1 v-show="isShow">你好啊!</h1>
</transition>

<style scoped>
    1.动画
	.hello-enter-active{ 
        /* 如果上面没写name属性,就用v-enter-active(默认、全局) */
        /*enter-vShow为true,leave-vShow为false */
		animation: donghua 0.5s linear;
	}
	.hello-leave-active{
		animation: donghua 0.5s linear reverse; /*reverse-反向 */
	}
    /*css3动画-帧*/
	@keyframes donghua {
		from{
			transform: translateX(-100%);
		}
		to{
			transform: translateX(0px);
		}
	}
    
    2.过度(transition标签还是配合动画css好用)
    h1{
		background-color: orange;
       /* transition: 0.5s linear;-不用active的话transition也可以写在这 */
	}
	/* 进入的起点、离开的终点 */
	.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>

P:过度效果的原理逻辑目前不是很懂,有缘再看

正文

  • 使用控制台可见vue自动添加了一些class
image-20220204205206009

P94 集合第三方动画

<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>

<script>
	import 'animate.css' //在这里引入库-没有输出东西直接用
</script>

正文

P95 总结+Todo案例

code

<transition-group name="todo" appear>
	<MyItem 
		v-for="todoObj in todos"
		:key="todoObj.id" 
	/>
</transition-group>
<style scoped>
	.todo-enter-active{ /*注:使用特殊名称来区分实现、配合动画css实现更佳(也可以用过度哈)*/
		animation: donghua 0.5s linear;
	}
	.todo-leave-active{
		animation: donghua 0.5s linear reverse;
	}
	@keyframes donghua {
		from{
			transform: translateX(100%);
		}
		to{
			transform: translateX(0px);
		}
	}
</style>

正文

  • 文档
  1. 作用:在插入、更新或移除 DOM元素时,在合适的时候给元素添加样式类名
  2. 图示:image-20220204222613354
  3. 写法:
    1. 准备好样式
      • 元素进入的样式:v-enter、v-enter-active、v-enter-to
      • 元素离开的样式:v-leave、v-leave-active、v-leave-to
    2. 使用<transition>包裹要过度的元素,并配置name属性:
    3. 注:若有多个元素需要过度,则需要使用:<transition-group>,且每个元素都要指定key值。

固定写法-官网有写
enter-active-class=“animate__swing” //这些动效可以去官网看
leave-active-class=“animate__backOutUp”

	<h1 v-show="!isShow" key="1">你好啊!</h1>
	<h1 v-show="isShow" key="2">尚硅谷!</h1>

`正文`

- [animate.css官网](https://www.npmjs.com/package/animate.css)

### P95 总结+Todo案例

`code`

```vue
<transition-group name="todo" appear>
	<MyItem 
		v-for="todoObj in todos"
		:key="todoObj.id" 
	/>
</transition-group>
<style scoped>
	.todo-enter-active{ /*注:使用特殊名称来区分实现、配合动画css实现更佳(也可以用过度哈)*/
		animation: donghua 0.5s linear;
	}
	.todo-leave-active{
		animation: donghua 0.5s linear reverse;
	}
	@keyframes donghua {
		from{
			transform: translateX(100%);
		}
		to{
			transform: translateX(0px);
		}
	}
</style>

正文

  • 文档
  1. 作用:在插入、更新或移除 DOM元素时,在合适的时候给元素添加样式类名
  2. 图示:image-20220204222613354
  3. 写法:
    1. 准备好样式
      • 元素进入的样式:v-enter、v-enter-active、v-enter-to
      • 元素离开的样式:v-leave、v-leave-active、v-leave-to
    2. 使用<transition>包裹要过度的元素,并配置name属性:
    3. 注:若有多个元素需要过度,则需要使用:<transition-group>,且每个元素都要指定key值。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值