【VUE3】保姆级基础讲解(四): vue-router,vuex

目录

后端路由的映射方案

 SPA:single page web application

url的hash

 vue-router

基础使用

 路由默认url

异步打包

动态路由匹配

notfound

嵌套路由

动态路由

添加路由

添加嵌套路由

 删除路由

路由导航守卫

全局前置守卫beforeEach

Vuex状态管理

状态管理概念

vuex基础使用

安装

 创建store对象

main.js调用 

组件使用store 

state状态映射到组件

options api  computed 属性方案

setup方案

直接解构(推荐)

getters

基础使用

getters函数同时调用getters

getters函数返回函数

getter函数映射到组件

Mutation

基本使用

映射使用

重要原则


后端路由的映射方案

浏览器向服务器通过url申请页面,然后服务器通过url映射到具体的html页面,再将html页面传递给服务器,这就是后端路由的映射方式,url 对应了一个具体的 html页面

 SPA:single page web application

之前的后端方案是一个 url 对应了一个具体的 html页面

而现在的许多网站的方式不是这样,拿网易云网站举例

在点击导航栏时,例如点击  我的音乐

页面的url会发生改变,但是导航栏是没有变化的,而只变化了下面的界面

这说明这种方式,url发生变化时不会渲染整个页面,而只更新一部分

即url与组件一一对应,这就是SPA模式

 其实也就是前端路由

url的hash

 vue-router

基础使用

1、创建路由

 先下载插件  npm i vue-router

一般会建立一个js文件,用来创建路由并保持映射关系(其实就是保存url和组件的对应关系)

//引入路由函数
import { createRouter,createWebHashHistory} from 'vue-router'

//引入组件
import page from '../components/page.vue'
import nav from '../components/navitem.vue'

//创建路由
const router = createRouter({
//确定映射模式:hash模式
    history:createWebHashHistory(),
//确定映射关系
    routes:[
        {path:'/page',component:page},
        {path:'/nav',component:nav}
    ]
})

//导出路由
export default router

每个对应关系是可以有独一无二的name属性的,以便后续使用

        {
            name: "nav",
            path: '/nav',
            component: nav
        },

2、让路由生效

在main.js中引入路由并运用

import { createApp } from 'vue'
import App from './App.vue'
//引用路由
import router from './router/index'

const app = createApp(App)

//运用路由
app.use(router)

app.mount('#app')

3、router-view占位

在APP.vue或者其他组件中使用 router-view占位,以告诉页面当我切换url时,组件渲染在什么地方

4、router-link进行路由的切换

其实就是类似于a元素,点击时就可以切换url,使用 to属性

<template>
<router-view></router-view>
<router-link to="/page" class="link">page</router-link>
<router-link to="/nav" class="link">nav</router-link>
</template>

router-link自带class:router-link-active

选中哪个router-link,哪个router-link就会加入这个class,且具有排他作用

  当然也可以自己定义按钮函数:点击按钮触发jump函数,跳转到page

  const route = useRouter()
  let jump = ()=>{
    route.push('/page')
  }

 路由默认url

在初始时可以设定默认的跳转url

const router = createRouter({
    history:createWebHashHistory(),
    routes:[
//默认
        {path:'/',redirect:'/page'},

        {path:'/page',component:page},
        {path:'/nav',component:nav}
    ]
})

异步打包

【VUE3】保姆级基础讲解(三)非父子组件通讯,$refs,动态组件,keep-alive,Composition API_独憩的博客-CSDN博客

const page = ()=>import(/* webpackChunkName: 'page' */'../components/page.vue')
const nav = ()=>import(/* webpackChunkName: 'nav' */'../components/navitem.vue')

这样在打包的时候就会单独创造js文件

注释是固定写法,既魔法注释,会告知打包时的js文件名称

动态路由匹配

对于用户或者商品数据,往往的url是  商品\商品编号  组成,例如  good\111

那么我们希望,即使url变成这个样子,也要渲染good组件,只是穿进去的id是111

用到了动态路由匹配

    routes:[
        {path:'/',redirect:'/page'},
        {path:'/page',component:page},
        {path:'/nav',component:nav},
        {path:'/good/:id',component:good}
    ]

那么就定义了  id  用来传导编号

在使用时直接

<router-link to="/good/111" class="link">good1</router-link>
<router-link to="/good/222" class="link">good2</router-link>

在url转换成 good\111或者good\222时也能匹配到 good 组件

在good.vue中,如果想使用这个id:

<template>
    <h1>{{$route.params.id}}</h1>
</template>
<script setup>
    import { useRoute } from 'vue-router'
    const route = useRoute()
    console.log(route.params);
</script>
<style scoped>
</style>

在组件中  使用 $route.params.id

在js代码中,使用useRoute()获取路由

js代码中还可以使用 route.forward()或 route.back()跳转后一个和前一个界面 

如果想在切换 id时能持续获取params,需要用到onBeforeRouteUpdate

<template>
    <h1>{{$route.params.id}}</h1>
</template>
<script setup>
    import { useRoute , onBeforeRouteUpdate} from 'vue-router'
    const route = useRoute()
    onBeforeRouteUpdate((to,from)=>{
        console.log(to.params);
        console.log(from.params);
    })
    console.log(route.params);
</script>
<style scoped>
</style>

notfound

当传入的url是没经过匹配时,这时可以设定显示一个  notfound 组件

{path:'/:pathMatch(.*)',component:notfound}

嵌套路由

<template>
<h1>page</h1>
<router-view></router-view>
</template>

一些应用程序的 UI 由多层嵌套的组件组成。在这种情况下,URL 的片段通常对应于特定的嵌套组件结构,例如:

/page/profile                         /page/posts
+------------------+                  +-----------------+
| page             |                  | page            |
| +--------------+ |                  | +-------------+ |
| | Profile      | |  +------------>  | | Posts       | |
| |              | |                  | |             | |
| +--------------+ |                  | +-------------+ |
+------------------+                  +-----------------+

也就是说在 组件中再次使用 router-view占位

page.vue:

<template>
<h1>page</h1>
<router-view></router-view>
</template>

那么在配置routes时,应该加入children属性

        {path:'/page',
        component:page,
        children:[
            {
                path:'profile',
                component:()=>import('../components/profile.vue')
            }
        ]},

动态路由

添加路由

使用addRoute函数直接添加根路由

router.addRoute({
            name: "nav",
            path: '/nav',
            component: nav
})

添加嵌套路由

要将嵌套路由添加到现有的路由中,可以将路由的 name 作为第一个参数传递给 router.addRoute(),这将有效地添加路由,就像通过 children 添加的一样:

router.addRoute("page", {
    path: 'profile',
    component: () => import('../components/profile.vue')
}
)

通过这种方式给page路由添加了children

 删除路由

有几个不同的方法来删除现有的路由:

  • 通过添加一个名称冲突的路由。如果添加与现有途径名称相同的途径,会先删除路由,再添加路由:
    router.addRoute({ path: '/about', name: 'about', component: About })
    // 这将会删除之前已经添加的路由,因为他们具有相同的名字且名字必须是唯一的
    router.addRoute({ path: '/other', name: 'about', component: Other })
    
  • 通过调用 router.addRoute() 返回的回调:
    const removeRoute = router.addRoute(routeRecord)
    removeRoute() // 删除路由如果存在的话
    
    当路由没有名称时,这很有用。
  • 通过使用 router.removeRoute() 按名称删除路由:
    router.addRoute({ path: '/about', name: 'about', component: About })
    // 删除路由
    router.removeRoute('about')
    
    需要注意的是,如果你想使用这个功能,但又想避免名字的冲突,可以在路由中使用 Symbol 作为名字。

当路由被删除时,所有的别名和子路由也会被同时删除

路由导航守卫

在进行路由跳转时,可以进行回调函数,既 守卫

有一种使用场景是:在点击跳转时,先判断是否登陆,如果登陆了就跳转到对应的路由,如果没有登陆就跳转到登陆路由

全局前置守卫beforeEach

router.beforeEach((to, from) => {
    if(to.path !== "/login"){
        return "/login"
    }
  })

 其他守卫:导航守卫 | Vue Router

Vuex状态管理

状态管理概念

在一个项目中存在着很多状态,其实这个状态就是我们一直使用的变量,例如网易云音乐这个项目,播放状态(暂停or播放),现在播放的歌曲名称,播放到哪一句....都是其状态,对于这些数据的管理我们就称之为是状态管理。


在前面我们是如何管理自己的状态呢?
在Vue开发中,我们使用组件化的开发方式;

  • 而在组件中我们定义data或者在setup中返回使用的数据,这些数据我们称之为state;
  • 在模块template中我们可以使用这些数据,模块最终会被渲染成DOM,我们称之为View;
  • 在模块中我们会产生一些行为事件,处理这些行为事件时,有可能会修改state,这些行为事件我们称之为actions;
     

在之前的例子中,都是在组件中用变量直接控制的,但是这样存在弊端:

  1. 当项目组件十分庞大,状态很多,会使得组件十分臃肿,不好维护
  2. 虽然我们有props和emits等数据传递方法,但是当组件很多,且组件之间不是父子关系时,数据的传递会变得十分复杂

那么就需要创建一个状态库 store来管理这些状态:

  •  第一幅图表示所有的组件都可以和store内部的状态进行交互
  • 第二幅图表示,组件可以直接拿到数据state,但是如果想修改,必须走 actions---mutations---state流程,具体在下文阐述

vuex的基本元素为:state ,getters,mutation,actions,modules 

vuex基础使用

安装

npm i vuex

 创建store对象

与路由类似,一般会在src文件夹下创建store文件夹,下面创建一个index.js文件:

import {createStore} from  'vuex'
const store = createStore({
    state:()=>{
        return{
            counter:100
        }
    },
})
export default store

这里创建了一个store实例,然后定义了内部的state,采用的是函数式编程

使用createStore创建store对象,默认内部的状态是响应式的

main.js调用 

main.js中:

import { createApp } from 'vue'
import App from './App.vue'
import router from './router/index'
import store from './store/index'

const app = createApp(App)

app.use(router)
app.use(store)

app.mount('#app')

组件使用store 

然后在任何一个组件中就可以使用state的数据进行展示:

 <h1>{{$store.state.counter}}</h1>

在组件的js中获取数据方法:

  import {useStore} from 'vuex'
  const store = useStore()
  console.log(store.state);

 

state状态映射到组件

options api  computed 属性方案

当state里面的状态很多时,如果每个状态都采用  $store.state.xxx 的形式调用,会十分繁琐

那么我们希望将state状态整体映射到组件中

一般我们会使用  computed 属性,其属于options api

对于state:

import {createStore} from  'vuex'
const store = createStore({
    state:()=>{
        return{
            counter:100,
            name:'kobe',
            age:18
        }
    },

})
export default store

 在组件中可以引入mapState函数放置在computed属性中,这个函数前加 ... 表示其会返回多个函数,通过数组的形式将state中的状态映射进来,在模板中就可以直接使用了

<template>
  <h1>{{name}}</h1>
</template>
<script>
  import {mapState} from 'vuex'
    export default{
    computed:{
      ...mapState(['name','age','counte'])
    }
  }
</script>

setup方案

但是这个操作在setup里面写就很麻烦,一般不会这么用

  const store = useStore()
  const {name ,age,counter} =mapState(['name','age','counter'])
  const Cname = computed(name.bind({$store:store}))

从mapState中返回的是函数形式,要想使用必须放在computed属性中

但是在上述的方案中,其实底层调用store的逻辑还是    this.$store.state.xxx 

但是setup 中是不存在this的,所以要使用bind属性给其设置一个this指向

直接解构(推荐)

我们一般会使用setup编写逻辑,不希望还同时使用options api,所以上述方案都不太好

可以直接解构:

  import {toRefs} from 'vue'
  import {useStore} from 'vuex'

  const store = useStore()
  const{name,age,counter} = toRefs(store.state)

这样既映射成功,还保证了其响应式

getters

基础使用

类似于options api中的computed属性,当你想对state中的状态做一些操作时,可以使用getters

import {createStore} from  'vuex'
const store = createStore({
    state:()=>{
        return{
            counter:100,
        }
    },
    getters:{
        doubleCounter(state){
            return state.counter*2
        }
    }

})
export default store

使用方法和state类似 

<h1>{{$store.getters.doubleCounter}}</h1>

getters函数同时调用getters

getters中的函数可以相互调用

import {createStore} from  'vuex'
const store = createStore({
    state:()=>{
        return{
            counter:100,
            name:'lee',
        }
    },
    getters:{
        doubleCounter(state){
            return state.counter*2
        },
//相互调用
        message(state,getters){
            return `${state.name} need ${getters.doubleCounter} yuan`
        },
    }

})
export default store

getters函数返回函数

getters中的函数可以返回函数,在调用时可以传参:

import {createStore} from  'vuex'
const store = createStore({
    state:()=>{
        return{
            friends:[
                {name:"111",age:12},
                {name:"112",age:13},
                {name:"113",age:14},
            ]
        }
    },
    getters:{
        findfriend(state){
            return function(name){
                return state.friends.find(item=>item.name == name)
            }
        }
    }
})
export default store

 findfriend函数返回了一个函数,形参是name,这个函数又通过传入的name找到对应的friend信息返回

调用时:

  <h1>{{$store.getters.findfriend(112)}}</h1>

 

getter函数映射到组件

跟state方法的方案类似,也会有三个方案,也会有mapGetters函数,这里不再赘述,只写一下最推荐的直接解构方案

  const{findfriend} = toRefs(store.getters)

Mutation

更改VUEX中状态的唯一方法是提交mutation(其实也能直接修改,但是vuex认为不规范)

基本使用

首先在store中定义mutation方法:

    mutations:{
        increment(state){
            state.counter++
        },
        changename(state){
            state.name = 'kobe'
        }
    }

在组件中使用,必须要使用.commit方法:

<template>
  <button @click="changeName">跳转到page</button>
  <h1>{{$store.state.name}}</h1>
</template>
<script>
  export default {
    methods: {
      changeName() {
        this.$store.commit('changename')
      }
    }
  }
</script>

当然也可以传入参数:

    mutations:{
        changename(state,newname){
            state.name = newname
        }
    }
<script>
  export default {
    methods: {
      changeName() {
        this.$store.commit('changename','lalla')
      }
    }
  }
</script>

映射使用

mutations也可以映射使用

同样使用  mapMutations 函数

<template>
  <button @click="changename('kobe')">跳转到page</button>
  <h1>{{$store.state.name}}</h1>
</template>
<script>
  import { useStore, mapMutations } from 'vuex'
  export default {
    methods: {
      ...mapMutations(['changename'])
    }
  }
</script>

重要原则

也就是说在mutations中不要进行异步操作,例如网络请求,如果要网络请求数据,需要用到actions

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 错误:[vue-router]路由配置中需要“path”。 这个错误通常是因为在Vue Router的路由配置中缺少了“path”属性。在路由配置中,每个路由都需要一个“path”属性来指定该路由的URL路径。请确保在路由配置中为每个路由指定了正确的“path”属性。 ### 回答2: Vue-RouterVue.js的一个官方插件,用于管理Vue应用中的路由。当在Vue-Router中进行路由配置时,如果没有指定'path'属性则会出现"error: [vue-router] "path" is required in a route configuration"的错误提示。 这个错误提示意味着在路由配置中每个路由的path属性是必须指定的,缺少这个属性会导致Vue-Router无法正确解析路由,因而无法正常运行。 要解决这个错误,我们需要在每个路由的配置中加上'path'属性的定义。'path'属性是用于指定该路由的 URL 地址,它应该是一个字符串类型的值。例如,如果我们想创建一个路由,该路由使用 '/home' 作为它的 URL 地址,我们需要这样配置: ``` const router = new VueRouter({ routes: [ { path: '/home', component: Home } ] }) ``` 在上面的代码中,我们在路由的配置中明确指定了路径,所以Vue-Router可以正确解析定义的路由,从而不会出现错误提示。 总之,在使用 Vue-Router 时,需要注意在路由配置中指定path属性,才能使Vue-Router正确解析路由,避免"error: [vue-router] "path" is required in a route configuration"的错误提示。 ### 回答3: 该错误通常出现在使用Vue.js的开发者使用Vue Router时,当配置路由信息时缺少了"path"属性时就会出现此错误提示。这个错误提示告诉我们 Vue.router不能正确解析我们定义的路由映射,因为缺少了必要的" path"属性。 那么如何解决这个问题呢? 要解决这个错误,我们需要重新检查我们的路由配置,并确保每一个路由定义都有一个"path"属性。在Vue Router中,每个路径应该对应一个唯一的‘path’,这是路由映射的必要部分。我们需要确保在我们的路由定义中包含‘path’属性,值为一个字符串类型,并且该字符串表示该路由的路径。 此外,我们还应该检查路由配置的其他属性和信息是否正确或缺失,例如组件路径,名称等。如果仍然无法解决问题,我们还可以尝试重新安装Vue Router,或者应该访问此处Vue Router官方文档以获得更多信息。 最后,我们还可以查看类似的问题和解决方法,比如在GitHub或其他开发社区的讨论区中,以解决我们的困惑。当我们遇到类似的错误时,我们不要惊慌,我们应该仔细分析问题,并寻求适当的帮助和解决方案,以使我们的Vue Router项目变得更加完美。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值