组件 与 路由
组件传值
父 => 子
子组件:使用 props 接受父组件传过来的值
<script> export default{ props:{ user:{ default:0, type:Number, required:true } } } </script>
- props 是 自定义属性,允许使用者通过自定义属性,为当前组件制定初始值
- props 是 只读的,不要直接修改 props 的值,否则会报错!简写:props:[‘user’]
- default 设置默认值
- type 设置值的类型
- required 是必须校验
父组件:将要传的数据绑定到子组件标签上
<div> <Left :user='userinfo'></Left> </div>
- 使用子组件中的自定义属性,将父组件中的数据绑定到这个自定义组件上
子组件:在需要使用数据的地方直接用自定义属性调用
<p>user的值是:{{ user }}</p>
子 => 父
子组件:使用自定义事件
export default { data(){ return{count:0} }, methods:{ add(){ this.count += 1 this.$emit('numchange',this.count) } } }
- 使用 $emit() 触发自定义事件
- 里面的两个参数,第一个参数是: 触发事件的名字 第二个参数是:要传的新值
父组件:使用子组件传过来的自定义事件
<Son @numchange='getNewCount'></Son> export default{ data(){ return{ countFromSon:0 } }, methods:{ getNewCount(val){ this.countFromSon = val } } }
- 使用子组件传过来的自定义事件,绑定一个方法
- 将自定义事件传的第二个参数接收过来,让父组件中定义的值等于传过来的值
组件共享 (事件总线)
- 创建 eventBus.js 文件,用于中转
import Vue from 'vue' // 向外共享 Vue 的实例对象 export default new Vue()
- 数据发送方
import bus from './eventBus.js' export default { data(){ return{ msg:'hellow' } } methods:{ sendMsg(){ bus.$emit('share',this.msg) } } }
- 先导入 eventBus.js 文件
- 使用 bus.$emit() 自定义事件,用来传值
- 数据接受方
import bus from './eventBus.js' export default{ data(){ return{ msgFromA:'' } }, created(){ bus.$on('share',val=>{ this.msgFromA = val }) } }
- 导入 eventBus.js 文件
- 在 data 中备份数据
- 在 created 实例创建完成里调用 bus.$on() 方法
- bus.$on() 方法可以传两个参数
- 第一个参数: 数据发送方 传过来的 自定义事件
- 第二个参数: 数据发送方 穿过来的 值
ref 和 $nextTick
标签使用 ref (操作DOM)
给标签添加 ref 属性
<div ref='change'>好好学习vue</div> <button @click='changeDiv'>点我修改 div 颜色</button>
在方法中使用 $refs 来操作 DOM
methods:{ changeDiv(){ this.$refs.change.style.color = 'red' } }
组件使用 ref
- 给标签添加 ref 属性
<Lift ref='myLift'>好好学习vue</Lift> <button @click='resetMyDiv'>重置组件数据</button>
- 在方法中使用 $refs 来修改组件数据
methods:{ resetMyDiv(){ this.$refs.myLift.resetCount() // resetCount() 这个是子组件里面的方法,直接调用 this.$refs.myLift.count = 0 // count 是组件中的数据,直接修改子组件的数据 } }
$nextTick( )
$nextTick() 方法,表示在DOM加载完成之后,执行里面的命令
<imput type='text' v-if='inputVisible' @blur='showButton' ref:'iptRef' /> <button v-else @click='showInput'>展示输入框</button> <script> methods:{ showInput(){ this.inputVisible = true // 此阶段触发了数据更新,但是还没有更新完 DOM this.$nextTick(()=>{ this.$refs.iptRef.focus }) }, showButton(){ this.inputVisible = false } } </script>
- @blur 当元素失去焦点是触发事件
- $nextTick() 做的事情就是等一会,等 DOM 加载完成再执行里面代码
- $nexTick() 里面传的事一个回调函数
为什么卸载 updated 中不行呢?因为数据更新后就会触发 beforeUpdata 和 updated 第一次显示输入框的时候没有问题,但是在隐藏的时候就会触发第二次数据更新,这时候写在 updated 中的获取 input 是根本获取不到的,所以会报错
动态组件和组件缓存
<keep-alive include='left , right'>
<component :is='Left'></component>
</keep-alive>
- 组件默认是没有缓存机制的,每次创建都会循环创建和销毁
- include 设置需要缓存的组件
- exclude 设置不需要缓存的组件
- component 标签是 vue 内置的,作用:组件的占位符
- is 属性的值,表示要渲染的组件的名字
- 使用 keep-alive 标签包裹的组件会有缓存
插槽
基本插槽
在组件标签上使用插槽
<Left> <template #default> <p>这是 Left 组件内容区域</p> </template> </Left>
- 在使用组件的时候,提供的内容都会被填充到名字为 default 的插槽之中
- 如果需要渲染内容到指定区域,需要使用 v-slot: 这个指定
- v-slot: 后面要跟上插槽的名字、必须写在 template 标签上,不能写在元素身上
- v-slot: 简写是 #
组件内使用 slot 标签占位
<slot name:'default'> <h1>插槽内容</h1> </slot>
- 插槽必须要有 name 属性,如果没有 name 属性,会生成一个默认名称,default
具名插槽
- 在组件标签上使用插槽
<Left> <template #title> <p>这是 Left 组件头部区域</p> </template> <template #content> <p>这是 Left 组件内容区域</p> </template> <template #author> <p>这是 Left 组件作者区域</p> </template> </Left>
- 在组件内使用具名插槽 slot
<template> <div> <div> <slot name='title'></slot> </div> <div> <slot name='content'></slot> </div> <div> <slot name='author'></slot> </div> </div> </template>
- 插槽名字在组件中一一对应即可
作用域插槽
- 在组件标签上使用插槽
<Left> <template #author='scope' > <p>这是 Left 组件作者区域</p> <p>{{ scope.msg }}</p> </template> </Left>
- 父组件用具名插槽接收子组件传过来数据并排版页面渲染回子组件
- 数据返回的是对象类型
在组件内使用具名插槽并传值
<div> <slot name='content' mas='hellow vue'></slot> </div>
- 在插槽内绑定数据传给父组件
组件传入是对象数据
在组件标签上使用插槽
<Left> <template #author='{ user }' > <p>这是 Left 组件作者区域</p> <p>{{ user.name }}</p> </template> </Left>
- 因为在父组件内接收到的是对象类型,所以我们可以使用 解构
在组件内使用具名插槽并传值
<div> <slot name='content' :user='userinfo'></slot> </div> data(){ return{ userinfo:{ name:'张三', age:18 } } }
- 传值类型为对象,需要动态绑定数据
路由
$route
- this.$route.params 路劲参数
- this.$route.query 查询参数
- this.$route.path 当前部分路劲
- this.$route.fullpath 当前完整路劲
编程式导航
- this.$touter.push(‘hash地址’) 有历史记录,可前进后退
- this.$touter.replace(‘hash地址’) 没有历史记录
- this.$touter.go(‘hash地址) 可以设置前进几 或后退几
- this.$touter.back() 后退到上一个页面
- this.$touter.forward() 前进到下一个页面
动态路由
在路由规则内配置开启 props 传参
routes:[ { path:'/Movie/:id', component:()=>impot('../views/Movie.vue'), props:true } ]
- path 设置路径名
- props 为路由规则开启 props 传参,方便拿到动态参数
在组件内接收
props:['id']
- 接收的是路由 path 后面 : 设置的名称
导航守卫
- 创建路由实例对象
const router = new VueRouter({...}) // 创建路由实例对象 router.beforeEach((to,from,next)=>{}) // 全局前置守卫
- 先创建路由实例对象
- 全局前置守卫
- to 是将要访问的路由的信息对象
- from 是将要离开的路由的信息对象
- next 是一个函数,调用 next() 表示放行,允许这次路由导航