易忘知识点整理(持续更新)——VUE使用

1. 复习组件中自定义v-model指令使用:

组件中v-model最基本的用法:在父组件给子组件绑定v-model的时候,相当于绑定了自定义事件@inputv-model=后面传递的值,是子组件在$emit('input', val)时父组件接受的val值,也是转递给子组件的值:

自定义v-model的用法:

子组件:

<script>
//在子组件定义model{ prop: 'fatherdata', event: 'custEventName' }
export default {
    model: {
        prop: 'fatherdata', // 对应 v-model=后面传递的值
        event: 'custEventName'//自定义事件名 即$emit时执行传入的事件名  默认为'input'
    },
	//prop参数为父组件传递的值,然后可以设置props接受参数配置
    props: {
        fatherdata: String,
        default() {
            return ''
        }
    }
}
//子组件调用:this.$emit('custEventName', val);
</script>

父组件:

<template>
    <div>
    	<!-- 接收子组件调用:this.$emit('custEventName', val)中的val值;并且双向绑定至data中的name值,并且也是传递给子组件的fatherdata值-->
        <CustomVModel v-model="name"/>
    </div>
</template>

<script>
import CustomVModel from './CustomVModel'
export default {
    components: {
        CustomVModel
    },
    data() {
        return {
            name: '',
       	}
    }
}
</script>

遗留问题:

① v-model的双向绑定底层原理是什么?





2.refs 最基本最简单的使用

实现dom的查找:在元素上绑定ref属性ref="dom1"),使用this.$refs.dom1来找到该节点。





3.slot最基本使用


①匿名插槽:main


子组件

<!-- CustSlot组件 -->
<template> 
     <div>
          <main>
          		<!-- 默认被插的位置 -->
               <slot> 我是默认内容 </slot> <!-- slot中也可以自定义默认内容 -->
          </main>
     </div>
</template>

父组件

<!-- 父组件使用CustSlot组件 -->
<CustSlot>
	<template> 
	     <p>需要插入的内容</p><!-- 会被默认插到 main slot中 -->
	</template>
</CustSlot>

②具名插槽:v-slotname

子组件

<!-- CustSlot组件 -->
<template> 
     <div>
     	<slot name="part1"></slot> 
     	<slot name="part2"></slot> 
     </div>
</template>

父组件

<!-- 父组件使用CustSlot组件 -->
<CustSlot>
	<template v-slot:part1> 
	     <p>***内容***</p><!-- 会被默认插到name="part1" 的slot中 -->
	</template>
	<template v-slot:part2> 
	     <p>***内容***</p><!-- 会被默认插到name="part2" 的slot中 -->
	</template>
</CustSlot>

③有关slot中的数据传递: v-slot、作用域插槽

备注:这里slotData、slotProps均可以自定义名称


子组件

<!-- ScopedSlotDemo组件 -->
<template>
       <slot :slotData="website"><!-- website为子组件传递给父组件的值 -->
            <div>{{website.subTitle}}</div> <!-- 默认值显示 subTitle ,即父组件不传内容时,数据为自身组件data中的数据 -->
       </slot>
</template>

<script>
export default {
    data() {
        return {
            website: {
                url: 'https://blog.csdn.net/banzhangshenlin?spm=1011.2124.3001.5343',
                title: '半藏森林',
                subTitle: '易忘知识点整理(持续更新)——VUE'
            }
        }
    }
}
</script>

父组件

<!-- 父组件使用ScopedSlotDemo组件 -->
<ScopedSlotDemo>
     <template v-slot="slotProps"><!-- slotProps为接受子组件上绑定的属性们 -->
         {{slotProps.slotData.title}}<!-- slotProps.slotData为接受子组件的属性slotData的属性值,即数据website。这里会显示:半藏森林-->
     </template>
</ScopedSlotDemo>

4.动态组件简单使用

例:父组件中使用Dynamic组件:<Dynamic/> 相当于 <component :is="customName"/>:is后面为动态绑定的组件名称

<script>
import CustomVModel from './CustomVModel'
import NextTick from './NextTick'
import SlotDemo from './SlotDemo'
import ScopedSlotDemo from './ScopedSlotDemo'
import KeepAlive from './KeepAlive'
import Dynamic from './Dynamic'

export default {
    components: {
        NextTick,
        Dynamic,
        KeepAlive,
        ScopedSlotDemo,
        SlotDemo,
        CustomVModel
    },
    data() {
        return {
            customName: "Dynamic",
        }
    }
}
</script>

5.简单的异步组件加载

加载的时候不像其他同步组件直接import ,而是通过该方式:当通过标签访问到该组件时,才会执行后面的箭头函数,从而加载该组件。之后组件可以使用v-if来按需加载。<FormDemo v-if="showFormDemo"/>

components: {
        FormDemo: () => import('../BaseUse/FormDemo'),
 },

6.缓存组件使用 keep-alive

不用keep-alive包住的话,每次切换子组件都会重新destroymounte;(让然也可以不用keep-alive,使用v-show,比较低级)

<keep-alive> <!-- tab 切换 -->
       <KeepAliveStageA v-if="state === 'A'"/> <!-- 不是v-show,vue内部切换渲染 -->
       <KeepAliveStageB v-if="state === 'B'"/>
       <KeepAliveStageC v-if="state === 'C'"/>
</keep-alive>

7.mixin的使用

  • 使用场景: 多个组件有相同的逻辑,抽离出来,一般用来简化代码或抽离共用的变量和方法
  • 问题: 变量来源不明确,不利于阅读;多mixin可能会造成命名冲突;mixin和组件可能出现多对多的关系,复杂度较高
  • 解决: 2.x只能避免,3.0提出Composition API旨在解决这些问题

使用:

<template>
    <div>
        <p>{{name}} {{major}} {{city}}</p>
        <button @click="showName">显示姓名</button>
    </div>
</template>

<script>
import myMixin from './mixin'

export default {
    mixins: [myMixin], // 可以添加多个,会自动合并起来
    data() {
        return {
            city2: '绍兴',
        }
    },
    methods: {
    
    },
    mounted() {
        
    }
}
</script>

mixin.js:

export default {
    data() {
        return {
            city1: '杭州'//抽离的变量city1
        }
    },
    methods: {
        showName() {//抽离的方法
            console.log(this.city2)
        }
    },
    mounted() {
        console.log('mixin mounted', this.city2)
    }
}

8.关于Vuex的使用 看注释

https://vuex.vuejs.org/zh

安装: npm install vuex --save (脚手架、npm)

创建一个store.js (这里不用module,太复杂,不易阅读)

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
	//存储公共数据
    state:{
        name1:'helloVueX1',
        name2: 'hellowVuex2',
        name3: 'hellowVuex3',
    },
    //getters类似于computed,可以将state中的数据处理后返回,具有缓存特性,state数据变化,相关的getters中的属性值也会跟着变化
    getters: {
        NewName1(state, getters){//会将state以形参传入,也可以将getters作为第二个参数传入
            if(!getters) {
                return state + 'this is NewName1'
            } else {
				return getters.NewName2 + '和' + getters.NewName3;
			}
        },
        NewName2(state, getters){
            if(!getters) {
                return state + 'this is NewName2'
            } 
        },
        NewName3(state, getters){
            if(!getters) {
                return state + 'this is NewName2'
            }
        },
    },
    //mutations只能进行同步任务,改变state中的值只能在这进行
    mutations:{
        edit1(state, payload){//会将state以形参传入,也可将载荷作为第二个参数传入
            state.name1 = payload.name;
        },
        edit2(state, payload){
            state.name2 = payload.name;
        },
        edit3(state, payload){
            state.name3 = payload.name;
        }
    },
    //将有关的异步任务放在这里执行,但是不能在这直接更改state的值,通过commit来调用mutations中的方法,来改变state中的值。
    actions: {
        edit1Sync({commit, state}, payload) {//接受一个与 store 实例具有相同方法和属性的 context 对象(如果是子模块则为子模块对象实例,所以context不是store 实例本身)。
        	//因此可以调用 context.commit,context.dispatch以及访问context.state 和 context.getters。
        	//也可以传入第二个参数载荷payload
        	//这里使用ES6语法糖,将commit, state从context结构了出来
            return new Promise((resolve) => {//可以封装成promise并返回,可以调用之后.then和.catch
                setTimeout(() => {
                    console.log(state.name1,payload.amount, '执行了 edit1Sync');
                    commit('edit1', {
                        name: 'edit1Sync',
                    })
                    resolve();
                    console.log(state.name1, '执行了 edit1Sync');
                }, 1000);
            });
        },
        edit2Sync({commit, state}) {
            return new Promise((resolve) => {
                setTimeout(() => {
                    console.log(state.name2, '执行了 edit2Sync');
                    commit('edit2', {
                        name: 'edit2Sync',
                    })
                    console.log(state.name2, '执行了 edit2Sync');
                    resolve();
                }, 1000);
            });
        },
        //也可以使用async await语法  官网的例子
        //假设 getData() 和 getOtherData() 返回的是 Promise
        async actionA ({ commit }) {
    		commit('gotData', await getData())
  		},
  		async actionB ({ dispatch, commit }) {
    		await dispatch('actionA') // 等待 actionA 完成  这里说明,action中的方法可以组合使用
    		commit('gotOtherData', await getOtherData())
  		}
    }
})

export default store

子实例代码:(不使用map辅助函数)

<template>
	<!-- 读取state中的数据 name1 -->
    <div>
        <span>{{$store.state.name1}}</span><span>{{name1}}</span><!-- 看computed -->
    </div>
    <!-- 读取getter中处理后的数据(具有缓存)-->
    <div>
        {{$store.getters.NewName1}}
    </div><!-- 后面可以使用mapGetters辅助函数优化代码 -->
</template>

<script>
export default {
    data() {
        return {
            
        }
    },
    computed: {
        name1() {
			return this.$store.state.name1//后面可以使用mapState辅助函数优化代码
		}
    },
    methods: {
        
    },
    mounted() {
    	//调用store中的mutation中的方法
    	// 以载荷形式分发
         this.$store.commit('edit1', {
                 name: '《I love vuex》'
         });
         
		//以对象形式分发
         this.$store.commit({
             type:'edit1',
             name: '《I love vuex》',
         })
		//调用store中的actions中的方法
		// 以载荷形式分发
		this.$store.dispatch('edit1Sync', {
		  amount: 10
		})
		
		// 以对象形式分发
		this.$store.dispatch({
		  type: 'edit1Sync',
		  amount: 10
		});
		
    }
}
</script>

子实例代码:(使用map辅助函数)

<template>
	<!-- 读取state中的数据 name1 -->
    <div>
        <span>{{name1}}</span>
    </div>
    <!-- 读取getter中处理后的数据(具有缓存)-->
    <div>
        {{NewName1}}
    </div>
</template>

<script>
// 在单独构建的版本中辅助函数 先引入
import { mapGetters, mapState, mapMutations, mapActions } from 'vuex'
export default {
    data() {
        return {
            
        }
    },
    computed: {
    	//当映射的计算属性的名称与 state 的子节点名称相同时,可以给 mapState 传一个字符串数组
        ...mapState([//mapState(['name1', 'name2', 'name3']) 返回一个对象,里面每一个function都return state中对应的数据
        	//这里可以使用...对象展开运算符,将其打散至computed中。
            'name1',//映射 this.name1 为 this.$store.state.name1
            'name2',
            'name3'
        ]),
        ...mapGetters(['NewName1','NewName2','NewName3'])
    },
    methods: {
        ...mapMutations(['edit1','edit2','edit3']),
        ...mapActions(['edit1Sync'])
    },
    mounted() {
        //调用store中的mutation中的方法
		this.edit1({
                name: '《I love vuex1》',
        });
		//调用store中的actions中的方法
		this.edit1Sync({
			amount: 10
		});
    }
}
</script>

9.Vue Router 的使用

https://router.vuejs.org/zh/installation.html

起步:

①安装:

npm install vue-router(npm)
vue add router (Vue Cli)会覆盖原有App.vue

②基本模板:

router.js:

import Vue from 'vue'
import VueRouter from 'vue-router'//引入vue-router
Vue.use(VueRouter)//挂载
const routes = [
  {
    path: '/Cart/index',//路由地址
    name: 'Cart',//组件名称
    component: () => import(/* webpackChunkName: "about" */ '../components/Cart/index.vue')//这边为异步加载
  }
]
const router = new VueRouter({
  mode: 'history',//路由模式 设为history
  base: process.env.BASE_URL,
  routes
})
export default router

main.js引入router:

import router from './router'

new Vue({
  render: h => h(App),
  router,//将router 植入到 应用中
}).$mount('#app')

我们可以在任何组件内通过this.$router 访问路由器,也可以通过 this.$route 访问当前路由

基本使用:

①动态路由匹配

携带响应参数:比如参数id

const User = import('./components/user');

const router = new VueRouter({
  routes: [
    // 动态路径参数 以冒号开头
    { path: '/user/:id', component: User }
  ]
})

路径参数使用:标记,当匹配到一个路由时,参数值会被设置到this.$route.params,可以在每个组件内使用。

可设置多段“路径参数”,对应的值都会设置到$route.params,例如:

模式匹配路径$route.params
/user/:username/user/evan{ username: ‘evan’ }
/user/:username/post/:post_id/user/evan/post/123{ username: ‘evan’, post_id: ‘123’ }

备注:

1.如果用查询字符串传参,可以通过$route.query来访问。其他$route的属性可以查看API:

https://router.vuejs.org/zh/api/#%E8%B7%AF%E7%94%B1%E5%AF%B9%E8%B1%A1

2.当使用路由参数时,例如:/user/10 导航到 /user/11,原来的组件实例会被复用。组件的生命周期钩子不会再被调用。(解决方法监听$route 或者 使用导航守卫:beforeRouteUpdate

②匹配模式

常规参数只会匹配被 /分隔的 URL 片段中的字符。如果想匹配任意路径,我们可以使用通配符 (*):
例:

{
  // 会匹配所有路径
  path: '*'
}
{
  // 会匹配以 `/user-` 开头的任意路径
  path: '/user-*'
}

含有通配符的路由应该放在最后。路由{ path: '*' }通常用于客户端 404 错误。

备注:
1.当使用一个通配符时,$route.params 内会自动添加一个名为 pathMatch 参数。它包含了 URL 通过通配符被匹配的部分:
例:

// 给出一个路由 { path: '/user-*' }
this.$router.push('/user-admin')
this.$route.params.pathMatch // 'admin'
// 给出一个路由 { path: '*' }
this.$router.push('/non-existing')
this.$route.params.pathMatch // '/non-existing'

2.高级匹配模式、匹配优先级

(详见文档:https://github.com/pillarjs/path-to-regexp/tree/v1.7.0#parameters)

③嵌套路由(一般项目使用路由嵌套或组件的引用来动态显示,而并非v-if v-else)

#app嵌套着<router-view></router-view>,同样,组件内也可以嵌套自己的路由组件。
例如:在Cart路由组件中添加一个<router-view></router-view>

Cart组件:

<template>
	<div id="ele1">..内容1..</div>
	<div id="ele2">..内容2..</div>
	<div id="ele3">
		<router-view></router-view>
	</div>
</template>

VueRouter JS文件使用children配置:

//假设已经引入了 UserProfile和 UserPosts组件
const router = new VueRouter({
  routes: [
    {
      path: '/cart/',
      component: Cart,
      children: [
        {
          // 当 /cart/profile 匹配成功,
          // UserProfile 会被渲染在 Cart 的 <router-view> 中
          path: 'profile',
          component: UserProfile
        },
        {
          // 当 /cart/posts 匹配成功
          // UserPosts 会被渲染在 Cart 的 <router-view> 中
          path: 'posts',
          component: UserPosts
        }
      ]
    }
  ]
})

如果没有匹配到子路由,但路由子组<router-view>件想要渲染点东西,以提供一个 空的 子路由:

const router = new VueRouter({
  routes: [
    {
      path: '/cart/',
      component: Cart,
      children: [
        // 当 /cart 匹配成功,
        // UserHome 会被渲染在 Cart 的 <router-view> 中
        { path: '', component: UserHome }
        // ...其他子路由
      ]
    }
  ]
})

④编程式导航 router.push(location, onComplete, onAbort)

onComplete, onAbort为3.2之后的回调入参,暂不做了解

声明式编程式
<router-link :to="...">router.push(...)
// 字符串 /home
router.push('home')

// 对象 /home
router.push({ path: 'home' })

// 命名的路由  跳转至名为user的路由,携带/123
router.push({ name: 'user', params: { userId: '123' }})

// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})

备注:!!
1.如果提供了 pathparams 会被忽略,但 query 并不属于这种情况。做法:提供路由的 name 或手写完整的带有参数的 path

2.如果目的地和当前路由相同,只有参数发生了改变 (比如从一个用户资料到另一个 /users/1 -> /users/2),需要使用 beforeRouteUpdate 来响应这个变化 (比如抓取用户信息)。

3.其他router方法:

方法使用声明式
router.replace(location, onComplete?, onAbort?)不会向 history 添加新记录,用法与router.push一样<router-link :to="..." replace>
router.go(n)类似于history.go(n)

⑤命名路由 及 命名视图

实际项目中,使用该方法动态显示组件
命名路由:创建 Router 实例的时候,在 routes 配置中给某个路由设置名称name属性
命名视图:(不常用)

一个路由地址,渲染多个路由组件
场景:如果访问某个路由地址,具有比较复杂的动态渲染视图,可以拆成多个<router-view></router-view>,并为其设置name名字。注意:vue-cli中需要更改app.vue

app.vue:

<template>
  <div id="app">
    <div id="nav">
      <router-view  class="view one"/><!-- 没有设置名字,那么默认为 default -->
      <router-view  class="view two" name="a"/>
    </div>
    <router-view  class="view three" name="b"/>
  </div>
</template>

router js:

//加入Foo,Bar, Baz组件已经import
const router = new VueRouter({
  routes: [
    {
      path: '/',
      components: {//components 配置 (带上 s)
        default: Foo,
        a: Bar,
        b: Baz
      }
    }
  ]
})

嵌套命名视图: (常用)

一个路由组件,渲染多个路由子组件。

例:路由组件 UserSettings

<template>
	<div>
	  <h1>User Settings</h1>
	  <NavBar/>
	  <!-- /settings/emails 渲染 CompA -->
	  <!-- /settings/profile 渲染 CompB -->
	  <router-view/>
	  <!-- /settings/emails 不渲染 -->
	  <!-- /settings/profile 渲染 CompC -->
	  <router-view name="helper"/>
	</div>
</template>

router js配置:children

//假设组件CompA、 CompB、CompC已经import
{
	path: '/settings',
  	// 你也可以在顶级路由就配置命名视图
	component: UserSettings,
	children: [
		{
			path: 'emails',
			component: CompA
		}, 
		{
			path: 'profile',
			components: {
				default: CompB,
				helper: CompC
			}
		}
	]
}

⑥重定向和别名

当用户访问 /a时,URL 将会被替换成 /b,然后匹配路由为 /b
重定向:redirect

1.目标为path

const router = new VueRouter({
  routes: [
    { path: '/a', redirect: '/b' }
  ]
})

2.目标为命名路由

const router = new VueRouter({
  routes: [
    { path: '/a', redirect: { name: 'foo' }}
  ]
})

3.作为方法,动态返回重定向目标

const router = new VueRouter({
  routes: [
    { path: '/a', redirect: to => {
      // 方法接收 目标路由 作为参数
      // return 重定向的 字符串路径/路径对象
    }}
  ]
})

别名:alias
/a 的别名是 /b,当用户访问 /a 或 /b时,匹配路由均为 /b

const router = new VueRouter({
  routes: [
    { path: '/a', component: A, alias: '/b' }
  ]
})

⑦路由组件传参

之前像访问路由“/user/:id”,组件内id只能通过this.$route.params.id来获取,现在可以使用props作为属性传给路由组件。

1.布尔模式

如果 props 被设置为 true,route.params 将会被设置为组件属性。

注意: 对于包含命名视图的路由,必须为每个命名视图添加 props 选项
router.js

//假设已经import了User和Sidebar路由组件
const router = new VueRouter({
  routes: [
    { path: '/user/:id', component: User, props: true },
    // 对于包含命名视图的路由,你必须分别为每个命名视图添加 `props` 选项:
    {
      path: '/user/:id',
      components: { default: User, sidebar: Sidebar },
      props: { default: true, sidebar: false }
    }
  ]
})

路由组件内:props: ['id']来接收id。

2.对象模式
如果 props 是一个对象,它会被按原样设置为组件属性。当 props 是静态的时候有用。

router.js

const router = new VueRouter({
  routes: [
    {
      path: '/promotion/from-newsletter',
      component: Promotion,
      props: { newsletterPopup: '参数值1' }
    }
  ]
})

路由组件内:props: ['newsletterPopup']来接收newsletterPopup

3.函数模式
创建一个函数返回 props。可以将参数转换成另一种类型,将静态值与基于路由的值结合等等

router.js

const router = new VueRouter({
  routes: [
    {
      path: '/search/:id',
      component: SearchUser,
      props: route => ({ query: route.query.q,  userId: route.params.id})
    }
  ]
})

路由组件内:props: ['query', 'userId']来接收$route.query.q$route.params.id

⑧导航守卫

不使用导航守卫的话,简单的业务场景可以使用watch监听$route对象来处理。
形参:
1.to 即将要进入的目标 路由对象
2.from 当前导航正要离开的路由
3.next 一定要调用该方法来resolve 这个钩子。

  • next() :进行管道中的下一个钩子.
  • next(false) :中断当前的导航。
  • next('/') 或者 next({ path: '/' }) : 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。
    -next(error) :导航会被终止且该错误会被传递给 router.onError() 注册过的回调。

1.全局前置守卫 router.beforeEach
(在进入对应路由之前触发)

const router = new VueRouter({ ... })

router.beforeEach((to, from, next) => {
  // ...
})

2.全局解析守卫 router.beforeResolve
(在所有组件内守卫和异步路由组件被解析之后触发)

const router = new VueRouter({ ... })

router.beforeResolve((to, from, next) => {
  // ...
})

3.全局后置钩子(不是守卫) router.afterEach
(在进入对应路由之后触发)
这些钩子不会接受 next 函数也不会改变导航本身

router.afterEach((to, from) => {
  // ...
})

4.路由独享的守卫
(在进入独享路由之前触发)
定义在routes路由配置项中,属性beforeEnter

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})

5.组件内的守卫
beforeRouteEnter 无法访问this
(在进入组件路由之前触发)
beforeRouteUpdate
(在组件路由变化之后触发)
beforeRouteLeave
(在离开当前组件路由之前触发)

组件内代码:

export default {
	data() {
		return {

		}
	},
	beforeRouteEnter(to, from, next) {
    	// 在渲染该组件的对应路由被 confirm 前调用
    	// 不!能!获取组件实例 `this`
    	// 因为当守卫执行前,组件实例还没被创建
	},
	beforeRouteUpdate(to, from, next) {
		// 在当前路由改变,但是该组件被复用时调用
		// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
		// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
		// 可以访问组件实例 `this`
	},
	beforeRouteLeave(to, from, next) {
		// 导航离开该组件的对应路由时调用
		// 可以访问组件实例 `this`
	}
}

备注:
1.beforeRouteEnter无法访问this,解决:

beforeRouteEnter (to, from, next) {
  next(vm => {
    // 通过 `vm` 访问组件实例
  })
}

2.只有beforeRouteEnter支持next回调

6.完整的导航解析流程

1.导航被触发。
2.在失活的组件里调用 beforeRouteLeave 守卫。
3.调用全局的 beforeEach 守卫。
4.在重用的组件里调用 beforeRouteUpdate守卫 (2.2+)。
5.在路由配置里调用 beforeEnter
6.解析异步路由组件。
7.在被激活的组件里调用 beforeRouteEnter
8.调用全局的 beforeResolve 守卫 (2.5+)。
9.导航被确认。
10.调用全局的 afterEach 钩子。
11触发 DOM 更新
12调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。
如此循环

⑨路由元信息

配置 meta 字段

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      meta: { yaodehai: '姚老板1' }
      children: [
        {
          path: 'bar',
          component: Bar,
          // a meta field
          meta: { yaodehai: '姚老板2' }
        }
      ]
    }
  ]
})

路由记录: routes 配置中的每个路由对象
访问meta: 一个路由匹配到的所有路由记录会暴露为 $route 对象 (还有在导航守卫中的路由对象) 的 $route.matched 数组。可以遍历 $route.matched来检查路由记录中的 meta 字段

⑩过渡动效

transition插件的使用: https://cn.vuejs.org/v2/guide/transitions.html

1.单个路由的过渡: 使用 <transition> 并设置 name

例:
路由组件Foo(通过路由访问该路由组件的时候,过渡特效显示)

<template>
	<transition name="slide">
      <div class="foo">..路由的html内容..</div>
    </transition>
</template>

2.基于路由的动态过渡
父路由组件内:

<template>
	<transition :name="transitionName">
      	<router-view></router-view>
    </transition>
    <transition :name="transitionName">
      	<router-view name="a"></router-view>
    </transition>
</template>
<script>
	export default {
		data() {
			return {
				transitionName: ''
			}
		},
		methed: {},
		watch: {
			'$route'(to, from) {
				const toDepth = to.path.split('/').length
    			const fromDepth = from.path.split('/').length
    			this.transitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left'
			}
		}
	}
</script>

①①滚动行为 scrollBehavior

return { x: number, y: number }

const router = new VueRouter({
  routes: [...],
  scrollBehavior (to, from, savedPosition) {//savedPosition 当且仅当 popstate 导航 (通过浏览器的 前进/后退 按钮触发) 时才可用。
    // return 期望滚动到哪个的位置 { x: number, y: number }
  }
})

对于所有路由导航,简单地让页面滚动到顶部。

scrollBehavior (to, from, savedPosition) {
  return { x: 0, y: 0 }
}

返回 savedPosition,在按下 后退/前进 按钮时,就会像浏览器的原生表现那样:

scrollBehavior (to, from, savedPosition) {
  if (savedPosition) {
    return savedPosition
  } else {
    return { x: 0, y: 0 }
  }
}

模拟“滚动到锚点”的行为:

scrollBehavior (to, from, savedPosition) {
  if (to.hash) {
    return {
      selector: to.hash
    }
  }
}

还可以利用路由元信息更细颗粒度地控制滚动。

异步滚动:

scrollBehavior (to, from, savedPosition) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({ x: 0, y: 0 })
    }, 500)
  })
}

平滑滚动: behavior选项

scrollBehavior (to, from, savedPosition) {
  if (to.hash) {
    return {
      selector: to.hash,
      behavior: 'smooth',
    }
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值