Vue3 - Vuex的简单用法和vue-router路由的简单使用和原理

一. Vuex 的简单使用

Vuex 用来集中式存储管理应用的所有组件的状态。一般用于存储一些公共的变量。例如多语言翻译数据。接下来我们写一个简单的Vuex案例。首先记得安装一下Vuex依赖:

npm install vuex@next

我们一般会在项目src目录下创建一个store文件夹,专门用来放Vuex相关的文件,我们创建一个index.ts文件:

import { createStore } from 'vuex'

const store = createStore({
  state () {
    return {
      count: 666
    }
  },
  mutations: {
    add (state) {
      state.count++
    }
  }
})

export default store

接着我们在入口处声明这个store数据管理:

import router from './router/index'
import { createApp } from 'vue'
createApp(App)
    .use(store)
    .mount('#app')

最后我们就可以在各个组件中,直接使用Vuex管理的数据了:

<template>
<div @click="add">
    {{count}}
</div>
</template>

<script setup>
import { computed } from 'vue'
import {useStore} from 'vuex'
let store = useStore()
let count = computed(()=>store.state.count)

function add(){
    store.commit('add')
}
</script>

效果如下:
在这里插入图片描述
这里我们需要总结这么几个使用点:

Store定义方面:

  • 我们需要使用来自vuex包下的createStore创建一个数据存储Store
  • 创建出的state变量名称为state
  • 一般我们在mutations属性下,定义一些操作state变量的动作。而 mutation 内部的函数会把 state 作为参数。

Store使用方面:

  • 首先入口处需要引用我们自定义的Store数据存储。createApp(App).use(store)
  • 这样外部组件中,即可直接引用。通过useStore()获得全局的store对象。
  • 外部组件如何修改全局的变量?store.commit('add'),这里的add则是在Store文件中,mutation属性下定义的函数。

二. vue-router 路由原理

首先说下前端的路由,为了提高页面的交互体验,我们希望用户在跳转不同页面的时候,并不会使整个页面进行刷新。这样就会导致等待时间较长,让交互体验下降。因此目前推出了一种路由模式:

  1. 用户无论用什么URL来访问路由。统一渲染一个前端的入口文件 index.html
  2. 然后因为 index.html 文件中加载了页面所需的 JS
  3. 这样程序就可以获取当前的页面地址,以及判断当前路由匹配的组件,再去动态渲染当前页面。这样就避免了页面的整体刷新操作。如图:
    在这里插入图片描述

上面这个流程,也就是所谓的单页应用。它的实现离不开前端路由的运作。因此在这个环节,我们来说下vue-router路由。我在Vue3的特性介绍以及项目的简单创建这篇文章里面,也简单示例了一下如何使用vue-router路由。这里挑出几个重点部分来说。

  1. 我们需要使用createRouter()函数来创建路由。
  2. 区分路由的方式有两种。一种是 hash 模式,通过 URL# 后面的内容做区分,我们称之为 hash-router。使用createWebHashHistory()函数来声明。
  3. 另外一个方式就是 history 模式,在这种方式下,路由看起来和正常的 URL 完全一致。使用createWebHistory()函数来声明。

而我们之前案例中使用的就是哈希路由:
在这里插入图片描述
点击页面,URL为:http://localhost:5173/#/about
在这里插入图片描述
如果我们改为createWebHistory(),那么路由就变成:http://localhost:5173/about
在这里插入图片描述

两者的实现区别如图:
在这里插入图片描述

先说下Hash模式的设计:

  1. Hash模式下,有一个很突出的特点,就是页面在进行跳转的时候,会在URL上带上一个 #
  2. 然后在设计上,hash 值(即URL的改变)的变化并不会导致浏览器页面的刷新,只是会触发 hashchange 事件,这样我们就可以在事件监听中做出对应的动作,触发组件渲染。

再来说下History模式的设计:

  1. 浏览器中含有两个 API:pushStatereplaceState。通过这两个 API 我们可以改变 URL 地址,并且浏览器不会向后端发送请求,我们就能用另外一种方式实现前端路由 。
  2. 监听 popstate 事件,然后通过 pushState 修改路由的变化。

2.1 手写 vue-router 下 Hash 模式的实现

首先我们在router目录下,创建一个myRouter目录,定义一些关键的函数,想一想,我们自定义一个Hash路由,我们需要哪些函数?

  • 能够创建一个Router实例,对应的是createRouter函数。
  • 我们还需要指定路由的方式,对应的就是createWebHashHistory函数。
  • 想一下,我们在使用Store的时候,有两个函数的功能是对应的,创建/使用:createStore/useStore。同理,我们有createRouter,也需要有useRouter。这一部分其实用在了vue-router中注册好的两个内置组件中:router-viewrouter-link

这俩组件的作用,我们再来回顾一下:

  • router-view:用来渲染指定路由对应的组件内容。
  • router-link:用来指定路由地址的。

那么我们就可以开始编码了。

2.1.1 路由核心代码


import { ref, inject } from 'vue'
const ROUTER_KEY = '__router__'
/**
 * 创建路由的函数,介绍一个配置对象
 * export default createRouter({
        history: createWebHistory(),
        routes
    }) 
 */
const createRouter = (options: any) => {
    return new Router(options)
}

// 获取路由实例
const useRouter = () => {
    return inject(ROUTER_KEY)
}

const createWebHashHistory = () => {
    // 监听 hashchange 事件
    function bindEvents(fn: any) {
        window.addEventListener('hashchange', fn)
    }
    return {
        bindEvents,
        url: window.location.hash.slice(1) || '/'
    }
}

class Router {
    // 路由模式
    private history;
    // 路由配置数组
    private routes: any[];
    // 当前路由
    private currentPath;
    constructor(options: any) {
        this.history = options.history
        this.routes = options.routes
        // ref 用来将当前地址的值封装为响应式
        this.currentPath = ref(this.history.url)

        this.history.bindEvents(() => {
            this.currentPath.value = window.location.hash.slice(1)
        })
    }
    install(app: any) {
        app.provide(ROUTER_KEY, this)
    }
}

export { createRouter, createWebHashHistory, useRouter }

2.1.2 自定义 router-view

根据上文的用处介绍,我们这样设计这个组件RouterVIew

  1. 通过 useRouter 获取当前路由的实例,这样就可以拿到当前的路由了,也就是 router.currentPath.value 的值。
  2. 在用户路由配置 route 中计算出匹配的组件resultComponent,在 template 内部使用:is来指定 component 组件动态渲染。

代码如下:

<template>
  <component :is="resultComponent"></component>
</template>
<script setup>
import { computed } from "vue";
// 引入自定义的组件
import { useRouter } from "../router/myRouter/index";
// 获取自定义的路由实例,希望通过它获得当前路由 currentPath
let router = useRouter();
const resultComponent= computed(() => {
  const route = router.routes.find(
    (route) => route.path === router.currentPath.value
  );
  return route?.component ?? null;
});
</script>

备注:看下我们外部对于routes数组的定义,这样结合上面代码来看就会容易理解很多。
在这里插入图片描述

2.1.3 自定义 router-link

根据上文的用处介绍,我们这样设计这个组件RouterLink

  1. 根据案例的使用,我们知道router-link组件一般会传入一个属性:to,用于指定路由值。
  2. 我们改变URL的时候,会在URL上拼接一个 # ,因此我们这个组件的核心功能点就是两个。一个是接收父组件传入的值,传给a标签,一个是完成 # 的拼接。

代码实现如下:

<template>
  <a :href="'#' + props.to">
    <slot />
  </a>
</template>

<script setup>
let props = defineProps({
  to: { type: String, required: true },
});
</script>

最后,我们还需要把自定义的两个属性注册到全局组件中,我们在入口main.ts中增加组件的注册:

import RouterLink from './components/RouterLink.vue'
import RouterView from './components/RouterView.vue'

createApp(App)
    .component('MyComponent', MyComponent)
    .component('myRouter-link', RouterLink)
    .component('myRouter-view', RouterView)
    .use(router)
    .use(store)
    .mount('#app')

那么我们首页就可以这么改:

<template>
  <div>
    <myRouter-link to="/">首页</myRouter-link> |     
    <myRouter-link to="/about">关于</myRouter-link>
  </div>
  <myRouter-view></myRouter-view>
</template>

效果如下:(记得关注URL的改变)
在这里插入图片描述
这样我们在改变路由的时候,就会根据绑定的事件,动态的改变响应式数据currentPath
在这里插入图片描述
这样一个简单的vue-routerHash模式)组件就完成了。主要还是依赖于这两个API

  • API:location.hash
  • Event:hashchange
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Vue 3中,使用Vue Router进行由拆分可以帮助你更好地组织和管理你的由配置。以下是一些步骤来实现由拆分: 1. 安装Vue Router:首先,确保你的项目中已经安装了Vue Router。可以通过以下命令进行安装: ``` npm install vue-router@next ``` 2. 创建由模块:创建一个新的模块来定义和配置你的由。可以创建一个名为`router.js`的文件,并在其中导入VueVue Router: ```javascript import { createRouter, createWebHistory } from 'vue-router'; const routes = [ // 定义你的由配置 ]; const router = createRouter({ history: createWebHistory(), routes, }); export default router; ``` 3. 定义由配置:在由模块中,通过`routes`数组来定义你的由配置。每个由对象应该包含一个`path`属性和一个`component`属性,分别指定由的径和对应的组件。 ```javascript import Home from './components/Home.vue'; import About from './components/About.vue'; const routes = [ { path: '/', component: Home, }, { path: '/about', component: About, }, // 更多由配置... ]; ``` 4. 在主应用程序中使用由:在你的主应用程序中,导入并使用创建的由实例。你可以在`main.js`文件中完成这个步骤: ```javascript import { createApp } from 'vue'; import App from './App.vue'; import router from './router'; const app = createApp(App); app.use(router); app.mount('#app'); ``` 现在,你已经成功拆分了你的由配置。你可以在每个组件中使用`<router-link>`和`<router-view>`来进行导航和渲染由组件。 注意:以上只是一个简单的示例,你可以根据你的项目需求进行更复杂的由配置和组织方式。不过,以上步骤应该可以帮助你开始使用Vue Router进行由拆分。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zong_0915

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值