100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > Vue学习笔记05 组件的自定义事件-组件通信-$nextTick-脚手架解决ajax跨域-插槽-过渡动画

Vue学习笔记05 组件的自定义事件-组件通信-$nextTick-脚手架解决ajax跨域-插槽-过渡动画

时间:2021-02-03 14:29:05

相关推荐

Vue学习笔记05 组件的自定义事件-组件通信-$nextTick-脚手架解决ajax跨域-插槽-过渡动画

文章目录

Vue学习笔记05父组件给子组件传值注意点子组件给父组件传值父组件接受子组件的传值 通过函数组件的自定义事件事件绑定的第一种写法 @或v-on事件绑定的第二种写法:使用ref + $on事件触发解绑 $emit $off组件绑定原生事件全局事件总线 任意组件间通讯消息订阅与发布 任意组件间通讯$nextTick(callback)动画效果 transitiontransition-group解决ajax跨域问题 配置代理代理服务器利用脚手架配置代理服务器方式1 不常用方式2 请求前缀插槽默认插槽具名插槽作用域插槽

Vue学习笔记05

父组件给子组件传值

props用于让组件接受外部传过来的值

//父组件传值 age传的是字符串"18"<Student name="李四" sex="女" age="18"/>//vbind动态绑定,绑定是引号里的js表达式的执行的结果,18<Student name="李四" sex="女" :age="18"/>//写法1:子组件接受值,简单接受props:['name','sex','age']//写法2:子组件接受值,设置希望类型props:{name:String,sex:String,age:Number}//写法3: 子组件接受值,完整写法props:{name:{type:String,required:true //是否必须},age:{type:Number,//类型default:99 //默认值}}

props是只读属性,子组件不可以修改传入的值。

如果想要修改可以使用中间变量

{{myAge}} //模板中使用data(){myAge:this.age //中间变量},props:['age'] //优先被设置在vc组件上

注意点

如果子组件不使用prop,子组件的$attrs里会存储传过来的属性,子组件的vc实例上不会存储

如果子组件使用prop,子组件的vc实例上会直接存储传过来的属性,子组件的$attr里不会存储

子组件给父组件传值

将自定义事件绑定在子组件的实例vc上,回调函数是在父组件中

1.1 在父组件中自定义事件@自定义事件=’事件回调'

1.2 在父组件中采用ref获取到子组件的实例,采用$on(‘事件名’,回调函数)绑定自定义事件子组件触发自定义事件this.$emit(‘事件名’,数据),子组件解绑自定义事件this.$off()

父组件接受子组件的传值 通过函数

v-model绑定的值不能是props传过来的值,因为props的值是不可以修改的

父组件给子组件传递函数,子组件调用传参,父组件获得子组件的参数值

//父组件<MyHeader :addTodo="addTodo"/>export default {name:'App',components:{MyHeader},methods: {//添加一个todoaddTodo(todoObj){this.todos.unshift(todoObj)}}//子组件<input type="text" placeholder="请输入你的任务名称,按回车键确认" v-model="title" @keyup.enter="add"/>export default {name:'MyHeader',props:['addTodo'],//接收从App传递过来的addTodomethods: {add(){const todoObj ={id:nanoid(),title:this.title,done:false}//通知App组件去添加一个todo对象this.addTodo(todoObj)}}}

组件的自定义事件

内置指令->HTML元素使用

自定义指令-> 组件使用

事件绑定的第一种写法 @或v-on

@或v-on 绑定在子组件的vc上

绑定事件:使用@或v-on:将回调函数绑定在子组件的vc上

触发事件:在子组件中触发,$emit(‘事件名’,参数1…,参数2…)

<!-- 第一种写法,使用@或v-on 绑定在子组件的vc上 --> <Student @getName="getStudentName" @demo="m1"/> <!-- 一次性事件 --><Student @getName.once="getStudentName" @demo="m1"/>methods: {getSchoolName(name){console.log('App收到了学校名:',name)}<!--Studetn子组件传值--><button @click="sendStudentlName">把学生名给App</button>methods:{sendStudentlName(){//触发Student组件实例身上的getName事件this.$emit('getName',this.name)}}

事件绑定的第二种写法:使用ref + $on

this.$refs.xxx获取到组件的vc实例

更灵活,可以控制绑定时间

使用$on绑定在子组件上

$on('事件名',回调函数)给组件绑定自定义事件

<!-- 第二种写法,使用ref --><Student ref="student"/>//父组件挂载完毕时mounted(){this.$refs.student.$on('atguigu',this.getStudentName)//this.$refs.student.$once('atguigu',this.getStudentName)一次性事件}

需要注意回调函数的定义位置,定义在methods中,或者使用箭头函数,不然this的指向可以出问题。

事件触发解绑 $emit $off

触发事件:在绑定事件的组件中触发,$emit('事件名',参数1..,参数2..)

解绑一个事件: 在绑定事件的组件中触发,off('事件名')

解绑多个事件: 在绑定事件的组件中触发,$off(['事件名1','事件名2'...])

解绑所有事件: 在绑定事件的组件中触发,off()

组件绑定原生事件

自定义指令-> 组件使用,所以如果直接写原生事件名会被认为时自定义事件

//需要Student组件$emit触发click事件之后,show回调才会被调用<Student ref="student" @click="show"/>

修饰符native表明该事件是内置事件

//需要Student组件$emit触发click事件之后,show回调才会被调用<Student ref="student" @click.native="show"/>

全局事件总线 任意组件间通讯

全局事件总线的特点

1.所有组件都可以看见

2.需要有$on$off$emit

VueComponent.prototype.prototype.proto=== Vue.prototype

作用:让组件实例对象vc可以访问到Vue原型上的属性和方法

思路

1.事件总线需要在Vue显式原型上,这样所有的组件都可以看见

2.事件总线需要使用Vue显式原型里的$on$off$emit函数,所以事件总线需要能看见Vue显式原型,事件总线可以设置成Vue的实例

错误写法

import Vue from 'vue'const vm = new Vue({el:'#app',render:h=>h(App) //①})//报错Vue.prototype.$bus= vm;

上述写法报错的原因

①执行完后,App整个组件已经渲染到了页面上,此时组件中的$on绑定事件已经执行完毕,此时已经晚了。

正确写法

可以写在befoteCreate生命周期钩子里,befoteCreate的this指向Vue实例(new Vue())

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

组件中通过this.$bus.$onthis.$bus.$off`this.bus.bus.bus.emit 使用

全局事件总线所有组件都可以看见,所以要小心事件名重复。

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

消息订阅与发布 任意组件间通讯

消息订阅与发布

1.订阅消息:消息名 谁需要数据谁订阅

2.发布消息:消息内容 提供数据的发布消息

依赖消息订阅与发布库,这里选择pubsub-js

//谁需要谁引用import pubsub from 'pubsub.js'//订阅消息,每次订阅返回一个新的消息号,this.pubId = pubsub.subscribe('hello',(msgName,data)=>{console.log("订阅hello消息的回调函数,当hello消息被发布时调用")}//发布消息pubsub.publish('hello',666)//最好在beforeDestroy钩子中取消消息pubsub.unsubscribe(消息号);

事件总线区别

对于同名的消息,消息订阅和发布可以取消特定消息号的一个消息,但是事件总线取消同名的一类消息

$nextTick(callback)

$nextTick指定的回调函数callback会在DOM节点更新完毕之后再执行

使用场景

当改变数据后,要基于更新后的新DOM进行操作时,要在nextTick所指定的回调函数中执行。

动画效果 transition

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

<transition></transition>包裹需要动画的代码块,Vue解析时并不会生成真实的标签

通过CSS特定的选择器名字设置动画的执行时机

当有多个动画有不同的效果时,可以给transition标签添加name属性,那么对应的.v-enter-active等应该变成.hh-enter-active

<!--开始的时候isShow为真,但是开始并没有进入的动画,添加appear后初次渲染就有效果--><transition name="hh" appear><h1 v-show="isShow">你好啊!</h1></transition><style>/*进入时激活的样式*/.v-enter-active{animation: ranan 0.5s linear;}/*离开时激活的样式*/.v-leave-active{animation: ranan 0.5s linear reverse;}@keyframes ranan {from{transform: translateX(-100%);}to{transform: translateX(0px);}}</style>

可以不采用定义动画的方式实现上述效果,可以使用过渡实现

/*进入的过程中,离开的过程中*/.v-enter-active,.v-leave-active{transition:0.5s linear;}/*进入的起点样式*/.v-enter{transform: translateX(-100%);}/*进入的终点样式*/.v-enter-to{transform: translateX(0);}/*离开的起点样式*/.v-leave{transform: translateX(0);}/*进入的终点样式*/.v-leave-to{transform: translateX(-100%);}

transition-group

<transition></transition>里面只能有一个元素

<transition-group></transition-group>里面可以放多个元素,但是每个元素必须要绑定key属性

第三方动画库Animate.css,引入直接import'animate.css'

解决ajax跨域问题 配置代理

同源原则:协议名、主机名、端口号都一样

真正意义上的跨域cors

后端使用cors解决跨域,添加特殊的响应头,浏览器看见特殊的响应头,虽然跨域但是服务器同意把数据给客户端,浏览器就把数据给客户端

代理服务器

代理服务器和我们客户端同源,利用服务器与服务器之间没有同源策略的方法实现。(因为服务器之间不适用ajax通信)

利用脚手架配置代理服务器

方式1 不常用

修改vue.config.jsvue-cli配置文件

module.exports = {devServer:{proxy:'http:localhost:5000' //代理服务的端口会根据我们客服端的端口自动的配置,这里写需要代理的服务器的地址}}

说明

1.发送请求的时候,直接向代理服务器要数据

2.public目录就是代理服务器的根目录

3.代理服务器先会在自己的文件中查找,如果没有再转发给服务器

缺点

1.只能配置一个代理

2.不可以灵活转发,没办法控制走不走代理

方式2 请求前缀

请求前缀在端口号的后面

如:http:localhost:8080/student -> http:localhost:8080/xxx/student

如果这样直接给服务器,服务器收到的是http:localhost:8080/xxx/student,我们需要把/xxx去掉,需要重写路径

module.exports = {devServer:{proxy:{'/xxx':{//遇见xxx前缀的请求,走代理去服务器端获取target:'http:localhost:5000',pathRewrite:{'^/xxx':'']//重写path把开头的/xxx前缀删除//ws:true, 用于支持websocket//changeOrigin:true,是否告诉服务器请求源的真实信息,比如这是一台代理服务器端口号是8080。用于控制请求头中的host值},'/yyy':{target:'http:localhost:5001',pathRewrite:{'^/yyy':'']}}}}

插槽

作用:让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式,适用于父组件->子组件

父组件传的html结构会以虚拟节点的形式存储在子组件vc实例的$slots属性里

默认插槽

<!--解析到img标签后,img应该放在Category组件里的哪个位置呢?--><Category title="美食" ><img src="" alt=""></Category><!--Category组件里使用slot告诉img放在这里--><div><h1>Category组件</h1><slot>这段文字是默认值,当使用者没有传递具体结构时出现<slot></div>

具名插槽

使用<slot name="xxx">给插槽命名,使用slot="xxx"选择放入哪个插槽

h4和div都想放在footer插槽里面,但是不想再加一个div结构,就可以选择使用<template >标签

<template >标签有个独特的具名插槽写法<template v-slot:footer>,Vue3只支持这种具名插槽写法

<Category title="电影"><video slot="center" controls src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"></video><template v-slot:footer><!--<template slot="footer">--><div class="foot"><a href="">经典</a><a href="">热门</a><a href="">推荐</a></div><h4>欢迎前来观影</h4></template></Category><!--Category组件--><div><h1>Category组件</h1><slot name="center">这段文字是默认值,当使用者没有传递具体结构时出现<slot><slot name="footer">这段文字是默认值,当使用者没有传递具体结构时出现<slot></div>

作用域插槽

使用场景:数据在插槽位置,但是根据数据生成的结构需要父组件来决定

数据在子组件(作用域),结构由父组件传。

数据: 子 -> 父 结构:父 -> 子

1.<slot :xxxx="数据">将数据传给父组件

2.父组件(给插槽传结构的代码)外侧包裹<template scope="yyyy">标签,也可以写成<template slot-scope="yyyy">yyyy接收到的是插槽传过来的{xxxx:数据}

3.父组件接收的数据是一个对象,对象包含传过来的值。也就是说传过来的值外层包裹了一层对象,所以起名的时候yyy可以和xxx不一样。

<Category title="游戏"><template scope="ranan"><ul>{{ranan}} <!--接收到{game:['红色警戒','穿越火线','劲舞团','超级玛丽'],mag:"hello"}--></ul></template></Category><!--category组件--><template><div class="category"><slot :game="games">我是默认的一些内容</slot></div></template><script>export default {name:'Category',props:['title'],data() {return {games:['红色警戒','穿越火线','劲舞团','超级玛丽'],}},}</script>

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。