精华内容
下载资源
问答
  • 2021-12-05 15:00:01

    jQuery 以及之前的时候,前端工程师并不需要了解路由的概念。对于每次的页面跳转,都由后端开发人员来负责重新渲染模板。前端依赖后端,并且前端不需要负责路由的这种开发方式,这样开发速度会很快、后端也可以承担部分前端任务等。当然,这种开发方式也有很多缺点,比如前后端项目无法分离、页面跳转由于需要重新刷新整个页面、等待时间较长等等,所以也会让交互体验下降。
    为了提高页面的交互体验,很多前端工程师做了不同的尝试。在这个过程中,前端的开发模式发生了变化,项目的结构也发生了变化:由原先的
    访问路由 -> 后端匹配路由 -> 匹配前端模板 -> 加载JS、CSS
    变成了
    访问路由 -> 前端入口 ->加载JS、CSS -> JS根据路由匹配渲染的组件 -> 渲染路由组件

    可以看到:用户访问路由后,无论是什么 URL 地址,都直接渲染一个前端的入口文件 index.html,然后就会在index.html 文件中加载 JS 和 CSS。之后,JavaScript 获取当前的页面地址,以及当前路由匹配的组件,再去动态渲染当前页面即可。用户在页面上进行点击操作时,也不需要刷新页面,而是直接通过 JS 重新计算出匹配的路由渲染即可。前端获得了路由的控制权,在 JavaScript 中控制路由系统。也因此,页面跳转的时候就不需要刷新页面,网页的浏览体验也得到了提高。这种所有路由都渲染一个前端入口文件的方式,是单页面应用程序(SPA,single page application)应用的雏形。

    通过 JavaScript 动态控制数据去提高用户体验的方式并不新奇,在html5时代浏览器路由的变化可以通过 pushState 来操作。之后,这种开发模式在 MVVM 框架的时代大放异彩,现在大部分使用 Vue/React/Angular 的应用都是这种架构。SPA 应用相比于模板的开发方式,对前端更加友好

    前端路由实现原理

    通过 URL 区分路由的机制,有两种实现方式,
    一种是 hash 模式,通过 URL 中 # 后面的内容做区分,我们称之为 hash-router
    另外一个方式就是 history 模式,在这种方式下,路由看起来和正常的 URL 完全一致。

    这两个不同的原理,在 vue-router 中对应两个函数,分别是 createWebHashHistorycreateWebHistory

    在vue3之前更为简单,是通过mode值 historyhash来区分的。

    hash 模式

    单页应用在页面交互、页面跳转上都是无刷新的,这极大地提高了用户访问网页的体验。为了实现单页应用,前端路由的需求也变得重要了起来。类似于服务端路由,前端路由实现起来其实也很简单,就是匹配不同的 URL 路径,进行解析,然后动态地渲染出区域 HTML 内容。但是整体 URL 每次变化都会造成页面的刷新。解决这一问题的思路便是在改变 URL 的情况下,保证页面的不刷新 —— 也就是只改变#后面的东西。在进行页面跳转的操作时,hash 值的变化并不会导致浏览器页面的刷新,只是会触发 hashchange 事件。在下面的代码中,通过对 hashchange 事件的监听,我们就可以在 fn 函数内部进行动态地页面切换

    window.addEventListener('hashchange',fn)
    

    这种方式在现在的微前端webview中使用尤为广泛

    history 模式

    2014 年之后,因为 HTML5 标准发布,浏览器多了两个 API:pushStatereplaceState。通过这两个 API ,我们可以改变 URL 地址,并且浏览器不会向后端发送请求,同时还会触发 popstate 事件(会增加location下history的长度)。通过这两个 API 和 popstate 事件,我们就能用另外一种方式实现前端路由。在下面的代码中,我们监听了 popstate 事件,可以监听到通过 pushState 修改路由的变化。并且在 fn 函数中,我们实现了页面的更新操作

    window.addEventListener('popstate', fn)
    

    实现一个极其简单的hash版vue-router

    我们首先要实现 Router 类去管理路由,并且,我们使用 createWebHashHistory 来返回 hash 模式相关的监听代码,以及返回当前 URL 和监听 hashchange 事件的方法;然后,我们通过 Router 类的 install 方法注册了 Router 的实例,并对外暴露 createRouter 方法去创建 Router 实例;最后还要暴露 useRouter 方法,去获取路由实例。

    import {ref,inject} from 'vue'
    import RouterLink from './RouterLink.vue'
    import RouterView from './RouterView.vue'
    
    const ROUTER_KEY = '__router__'
    
    function createRouter(options){
        return new Router(options)
    }
    
    function useRouter(){
        return inject(ROUTER_KEY) // 接收到当前的实例,这对使用的时候有大用
    }
    function createWebHashHistory(){
        function bindEvents(fn){
            window.addEventListener('hashchange',fn)
        }
        return {
            bindEvents,
            url:window.location.hash.slice(1) || '/'
        }
    }
    class Router{
        constructor(options){
            this.history = options.history
            this.routes = options.routes
            this.current = ref(this.history.url)
    
            this.history.bindEvents(()=>{
                this.current.value = window.location.hash.slice(1)
            })
        }
        install(app){
            app.provide(ROUTER_KEY,this) // 传递实例到router中
            app.component("router-link",RouterLink)
            app.component("router-view",RouterView)
        }
    }
    
    export {createRouter,createWebHashHistory,useRouter}
    

    有了上面这段代码,我们回到 src/router/index.js 中,可以看到下面代码的使用方式,我们使用 createWebHashHistory 作为 history 参数,使用 routes 作为页面的参数传递给 createRouter 函数

    import {
        createRouter,
        createWebHashHistory,
    } from '手写的router存放的文件'
    const router = createRouter({
      history: createWebHashHistory(),
      routes
    })
    

    上面router实现中我们还看到了两个最重要的内置组件挂载 —— router-viewrouter-link
    createRouter 函数 创建的 Router 实例上,current 返回当前的路由地址,并且使用 ref 包裹成响应式的数据。
    router-view 组件的功能,就是 current 发生变化的时候,去匹配 current 地址对应的组件,然后动态渲染到 router-view 就可以了。
    我们在router相同目录下新建 RouterView.vue,写出下面的代码。在代码中,我们首先使用 useRouter 获取当前路由的实例;然后通过当前的路由,也就是 router.current.value 的值,在用户路由配置 route 中计算出匹配的组件;最后通过计算属性返回 comp 变量,在 template 内部使用 component 组件动态渲染。

    <template>
        <component :is="comp"></component>
    </template>
    <script setup>
    
    import {computed } from 'vue'
    import { useRouter } from '手写router的文件'
    
    let router = useRouter()
    
    const comp = computed(()=>{
        const route = router.routes.find(
            (route) => route.path === router.current.value
        )
        return route?route.component : null
    })
    </script>
    

    有了 RouterView 组件后,我们再来实现 router-link 组件。我们在 router相同文件夹 下面新建文件 RouterILink.vue,并写入下面的代码。代码中的 template 依然是渲染一个 a 标签,只是把 a 标签的 href 属性前面加了个一个 #, 就实现了 hash 的修改。

    <template>
        <a :href="'#'+props.to">
            <slot />
        </a>
    </template>
    
    <script setup>
    import {defineProps} from 'vue'
    let props = defineProps({ // 获取调用组件时传的值
        to:{type:String,required:true}
    })
    
    </script>
    

    这样,一个 hash 模式的迷你 vue-router 就算实现了。

    “回顾”

    什么?install方法在哪里使用?
    你知道在app.vue同级的index.js中,为什么要写

    app.use(xxx)
    

    么?这里面又有什么故事?

    简单的说,use 方法 执行的就是第三方库/插件中的 install 方法!

    更多相关内容
  • vue-router.js 3.0.1 版本

    2018-04-17 09:57:50
    vue-router 3.0.1 版本 , 2018-04-05 最新版本 .
  • React-Router Demo

    2017-11-15 23:56:41
    React-Router DemoReact-Router DemoReact-Router DemoReact-Router DemoReact-Router DemoReact-Router DemoReact-Router DemoReact-Router DemoReact-Router DemoReact-Router DemoReact-Router DemoReact-Router ...
  • MySQL Router 8 详解

    万次阅读 2019-09-03 15:35:32
    目录 一、功能介绍 1. 透明路由 2. 元数据缓存 3. 简单重定向 4. MySQL Router 8.0的新特性 ... MySQL Router最早是作为MySQL-Proxy的替代方案出现的。作为一个轻量级中间件,MySQL Router可在应用...

    目录

    一、功能介绍

    1. 透明路由

    2. 元数据缓存

    3. 简单重定向

    4. MySQL Router 8.0的新特性

    二、安装与启动

    1. 安装

    2. 启动

    三、配置

    1. 配置文件位置

    2. 配置文件语法

    3. 配置文件示例


            MySQL Router最早是作为MySQL-Proxy的替代方案出现的。作为一个轻量级中间件,MySQL Router可在应用程序和后端MySQL服务器之间提供透明路由和负载均衡,从而有效提高MySQL数据库服务的高可用性与可伸缩行。

            MySQL Router 2.0是其初始版本,适用于MySQL Fabric用户,但已被弃用,不再支持。MySQL Router 2.1为支持MySQL InnoDB Cluster而引入,MySQL Router 8.0则是MySQL Router 2.1上的扩展,版本号与MySQL服务器版本号保持一致。即Router 2.1.5作为Router 8.0.3(以及MySQL Server 8.0.3)发布,2.1.x分支被8.0.x取代。这两个分支完全兼容。当前最新版本为8.0.17,MySQL强烈建议使用Router 8与MySQL Server 8和5.7一起使用。

    一、功能介绍

    1. 透明路由

            MySQL Router通过智能地将客户端连接路由到MySQL服务器来简化应用程序开发。MySQL使用组复制在多个服务器之间复制数据,当服务器发生故障时执行自动故障转移,基于paxos协议在剩余实例中选举一个新的主库。这里存在一个问题,如果应用程序直连主库,当发生主库切换时可用的数据库IP地址发生变化,客户端应用程序必须自行修改它的连接配置。这种方案极不现实,因为需要应用程序了解组复制的拓扑结构并知道哪个MySQL实例是主库,对于应用程序显然是强人所难,这些处理逻辑本应对应用透明。

            而这正是MySQL Router的用武之地。当与InnoDB Cluster一起使用时,MySQL Router充当代理,向应用程序隐藏网络上的多个MySQL实例,并将数据请求映射到其中一个集群实例。只要有足够的在线副本并且组件之间的通信完好无损,客户端就能够连接其中一个实例,保持对外服务的连续性。应用程序要做的只是连接到Router,而不是直连MySQL数据库实例,其它的交给Router处理即可。

            MySQL Router的推荐部署模型是与InnoDB Cluster集成,其中Router与应用程序最好位于同一主机上。

    2. 元数据缓存

            MySQL Router处于应用程序和MySQL服务器之间。当应用程序连接到Router时,Router从其候选池中选择合适的MySQL服务器连接,此后Router转发应用程序和MySQL之间的所有往返网络流量。

            MySQL Router保留在线MySQL服务器的缓存列表,或配置的InnoDB Cluster的拓扑和状态。Router启动时,列表从Router的配置文件加载。当使用--bootstrap选项引导Router时,此列表由InnoDB群集服务器生成。为了更新缓存,Router元数据缓存组件与包含元数据的InnoDB Cluster服务器之一保持连接,通过从该MySQL实例的performance_schema库表查询元数据和实时状态信息来实现。每当修改InnoDB集群时都会更改集群元数据,并且只要检测到集群状态更改,就会通过MySQL服务器的Group Replication插件实时更新performance_schema库表。

            当Router检测到连接的MySQL服务器关闭时,它会尝试连接到不同的MySQL服务器以从新的服务器获取元数据和InnoDB Cluster状态。关闭的MySQL服务器的应用程序连接会自动关闭。应用程序必须重新连接到Router,这要求应用程序实现重连机制。Router将它们重定向到在线MySQL服务器。

    3. 简单重定向

            Router将MySQL连接重定向到可用的MySQL服务器,这意味着数据包是在未经检查的情况下整体路由的。如果连接失败,应用程序须要重试连接,MySQL Router在尝试连接失败后选择新的MySQL服务器。这被称为简单重定向连接路由,因为它需要应用程序重试连接。也就是说,如果从MySQL Router到MySQL服务器的连接中断,则应用程序会遇到连接失败,但新的连接尝试会触发Router查找并连接到另一台MySQL服务器。路由连接的服务器和路由策略在配置文件中定义。

            使用MySQL Router不需要特定的库或接口,与不使用Router相比,应用程序所感知的唯一区别是如何建立与MySQL服务器的连接。因为MySQL Router在尝试连接时只是单纯重定向,并不读取数据包或执行分析,所以应用程序需要捕获连接错误并重试连接到Router。

            使用MySQL Router的工作流程如下:

    1. MySQL客户端连接到MySQL Router。
    2. Router检查可用的MySQL服务器。
    3. Router打开一个适用MySQL服务器的连接。
    4. Router在应用程序和MySQL服务器之间来回转发数据包
    5. 如果连接的MySQL服务器出现故障, Router将断开连接。当应用程序重试连接到Router时,Router选择另一个可用MySQL服务器。

            部署MySQL Router时建议但不强制遵循两点:

    • 在与应用程序相同的主机上安装并运行MySQL Router。
    • 使用配置文件中的bind_port = 127.0.0.1:<port>将 Router绑定到localhost,或者禁用TCP连接(--conf-skip-tcp)并将其限制为仅使用Unix套接字连接(--conf-use-sockets)。

            建议主要出于性能考虑。每当在网络中引入通信组件时,都会产生一定的开销,并且会受到工作负载的严重影响。幸运的是,MySQL Router的性能影响非常小。官方文档显示,当前版本的简单重定向连接路由,其速度与直连数据库相比仅慢约1%。

    4. MySQL Router 8.0的新特性

            较之以前2.x版本,MySQL Router 8.0新增了如下主要功能:

    • 添加了可选的routing_strategy配置选项。可用值为first-available、next-available、round-robin和round-robin-with-fallback。以前版本中,这些策略对应mode选项中的调度模式,其中read-write对应first-available,而read-only对应round-robin。它们保留了这些模式的先前行为。
    • 添加了--ssl-key和--ssl-cert命令行选项,指定客户端证书和私钥以方便客户端身份验证。用于使用REQUIRE X509创建root帐户时。
    • 添加了connect_timeout和read_timeout元数据配置文件选项。它们在[DEFAULT]命名空间下定义,并影响元数据服务器连接等内部操作。
    • Bootstrap接受InnoDB Cluster的任何成员,并自动查找并重新连接到可写服务器。以前只接受主库。
    • Bootstrap接受--config选项并读取[logger]级别选项的定义。
    • 最大并发客户端连接数从500增加到5000。
    • 添加了一个新的mysqlrouter_plugin_info实用程序来帮助调试MySQL Router插件。

    二、安装与启动

    1. 安装

            MySQL Router的安装过程依赖于所使用的操作系统和安装介质,二进制包的安装通常非常简单,而源码包则需要先编译再安装。例如在Linux上的安装最新的MySQL Router二进制包,只需要用mysql用户执行一条解压命令就完成了:

    tar -Jxvf mysql-router-8.0.17-linux-glibc2.12-x86_64.tar.xz

            解压后生成如下目录:

    [mysql@hdp1~]$ll mysql-router-8.0.17-linux-glibc2.12-x86_64
    total 108
    drwxrwxr-x 2 mysql mysql    126 Sep  2 15:26 bin
    drwxrwxr-x 3 mysql mysql   4096 Sep  2 15:26 lib
    -rw-r--r-- 1 mysql mysql 101805 Jun 25 18:23 LICENSE.router
    drwxrwxr-x 3 mysql mysql     17 Sep  2 15:22 man
    -rw-r--r-- 1 mysql mysql    700 Jun 25 18:23 README.router
    drwxrwxr-x 3 mysql mysql     16 Sep  2 15:22 share

    bin目录下存放的是可执行文件,可将该目录添加到PATH环境变量中方便执行,例如:

    export PATH=.:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/home/mysql/mysql-5.6.14/bin:/home/mysql/mysql-router-8.0.17-linux-glibc2.12-x86_64/bin;

    然后就可以执行mysqlrouter命令,如检查版本或显示帮助:

    [mysql@hdp1~]$mysqlrouter --version
    MySQL Router  Ver 8.0.17 for linux-glibc2.12 on x86_64 (MySQL Community - GPL)
    [mysql@hdp1~]$mysqlrouter --help
    [mysql@hdp1~]$mysqlrouter --help
    MySQL Router  Ver 8.0.17 for linux-glibc2.12 on x86_64 (MySQL Community - GPL)
    Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
    
    Oracle is a registered trademark of Oracle Corporation and/or its
    affiliates. Other names may be trademarks of their respective
    owners.
    
    Configuration read from the following files in the given order (enclosed
    in parentheses means not available for reading):
      (/home/mysql/mysql-router-8.0.17-linux-glibc2.12-x86_64/bin/.././mysqlrouter.conf)
      (/home/mysql/mysql-router-8.0.17-linux-glibc2.12-x86_64/bin/.././mysqlrouter.ini)
      (/home/mysql/.mysqlrouter.conf)
      (/home/mysql/.mysqlrouter.ini)
    
    ...

            各种安装包的下载地址为https://dev.mysql.com/downloads/router/。其它情况的安装可参考https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-installation.html

    2. 启动

            MySQL Router启动时需要读取其配置文件,获取基本连接路由信息。Router插件执行基于连接的路由,这意味着它将数据包转发到服务器而不检查它们。这是一种提供高吞吐量的简单方法。一个基本的连接路由设置如下所示:

    [logger]
    level = INFO
    
    [routing:secondary]
    bind_address = localhost
    bind_port = 7001
    destinations = 172.16.1.125:3306,172.16.1.126:3306,172.16.1.127:3306
    routing_strategy = round-robin
    
    [routing:primary]
    bind_address = localhost
    bind_port = 7002
    destinations = 172.16.1.125:3306,172.16.1.126:3306,172.16.1.127:3306
    routing_strategy = first-available

            这里设置了两个路由策略:通过本地7001端口,循环连接到172.16.1.125:3306、172.16.1.126:3306、172.16.1.127:3306三个MySQL实例,由round-robin路由策略所定义;通过本地7002端口,对同样的三个MySQL实例设置首个可用策略。首个可用策略使用目标列表中的第一个可用服务器,即当172.16.1.125:3306可用时,所有7002端口的连接都转发到它,否则转发到172.16.1.126:3306,以此类推。Router不会检查数据包,也不会根据分配的策略或模式限制连接,因此应用程序可以据此确定将读写请求发送到不同的服务器。本例中可将读请求发送到本地7001端口,将读负载均衡到三台服务器。同时将写请求发送到7002,这样只写一个服务器,从而实现的读写分离。

            将以上配置保存到/home/mysql/.mysqlrouter.conf文件,并后台启动MySQL Router:

    [mysql@hdp1~]$mysqlrouter -c /home/mysql/.mysqlrouter.conf &

    查看进程确认MySQL Router已经启动:

    [mysql@hdp1~]$ps -ef | grep router
    mysql    327410 326543  0 16:31 pts/0    00:00:00 mysqlrouter -c /home/mysql/.mysqlrouter.conf
    ...

    缺省的日志文件中显示如下信息:

    [mysql@hdp1~]$more ~/mysql-router-8.0.17-linux-glibc2.12-x86_64/mysqlrouter.log 
    2019-09-02 16:42:36 routing INFO [7f151540b700] [routing:primary] started: listening on localhost:7002, routing strategy = first-available
    2019-09-02 16:42:36 routing INFO [7f1514c0a700] [routing:secondary] started: listening on localhost:7001, routing strategy = round-robin
    [mysql@hdp1~]$

    查看监听状态:

    [mysql@hdp1~]$netstat -tnlp
    (Not all processes could be identified, non-owned process info
     will not be shown, you would have to be root to see it all.)
    Active Internet connections (only servers)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
    tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -                   
    tcp        0      0 127.0.0.1:199           0.0.0.0:*               LISTEN      -                   
    tcp6       0      0 :::80                   :::*                    LISTEN      -                   
    tcp6       0      0 :::22                   :::*                    LISTEN      -                   
    tcp6       0      0 ::1:7001                :::*                    LISTEN      329852/mysqlrouter  
    tcp6       0      0 ::1:7002                :::*                    LISTEN      329852/mysqlrouter  
    [mysql@hdp1~]$

            现在,MySQL Router正在侦听端口7001和7002,并将请求发送到适当的MySQL实例:

    [mysql@hdp1~]$mysql -uwxy -p123456 -P7001 --protocol=TCP -e"select @@hostname"
    Warning: Using a password on the command line interface can be insecure.
    +------------+
    | @@hostname |
    +------------+
    | hdp2       |
    +------------+
    [mysql@hdp1~]$mysql -uwxy -p123456 -P7001 --protocol=TCP -e"select @@hostname"
    Warning: Using a password on the command line interface can be insecure.
    +------------+
    | @@hostname |
    +------------+
    | hdp3       |
    +------------+
    [mysql@hdp1~]$mysql -uwxy -p123456 -P7001 --protocol=TCP -e"select @@hostname"
    Warning: Using a password on the command line interface can be insecure.
    +------------+
    | @@hostname |
    +------------+
    | hdp4       |
    +------------+
    [mysql@hdp1~]$mysql -uwxy -p123456 -P7001 --protocol=TCP -e"select @@hostname"
    Warning: Using a password on the command line interface can be insecure.
    +------------+
    | @@hostname |
    +------------+
    | hdp2       |
    +------------+
    [mysql@hdp1~]$mysql -uwxy -p123456 -P7002 --protocol=TCP -e"select @@hostname"
    Warning: Using a password on the command line interface can be insecure.
    +------------+
    | @@hostname |
    +------------+
    | hdp2       |
    +------------+
    [mysql@hdp1~]$mysql -uwxy -p123456 -P7002 --protocol=TCP -e"select @@hostname"
    Warning: Using a password on the command line interface can be insecure.
    +------------+
    | @@hostname |
    +------------+
    | hdp2       |
    +------------+
    [mysql@hdp1~]$mysql -uwxy -p123456 -P7002 --protocol=TCP -e"select @@hostname"
    Warning: Using a password on the command line interface can be insecure.
    +------------+
    | @@hostname |
    +------------+
    | hdp2       |
    +------------+
    [mysql@hdp1~]$

            由上可见,发送到本地7001端口的请求,被循环转发到三个服务器,而发送到本地7002端口的请求,全部被转发到172.16.1.125:3306。

            routing_strategy是MySQL Router的核心选项,从8.0.4版本开始引入,当前有效值为first-available、next-available、round-robin、round-robin-with-fallback。顾名思义,该选项实际控制路由策略,即客户端请求最终连接到哪个MySQL服务器实例。相对于以前版本mode的选项,routing_strategy选项更为灵活,并且不能同时设置routing_strategy和mode,静态路由的设置只能选择其中之一。对于InnoDB Cluster而言,该设置时可选的,缺省使用round-robin策略。

    • round-robin:每个新连接都以循环方式连接到下一个可用的服务器,以实现负载平衡。
    • round-robin-with-fallback:用于InnoDB Cluster。每个新的连接都以循环方式连接到下一个可用的SECONDARY服务器。如果SECONDARY服务器不可用,则以循环方式使用PRIMARY服务器。
    • first-available:新连接从目标列表路由到第一个可用服务器。如果失败,则使用下一个可用的服务器,如此循环,直到所有服务器都不可用为止。
    • next-available:与first-available类似,新连接从目标列表路由到第一个可用服务器。与first-available不同的是,如果一个服务器被标记为不可访问,那么它将被丢弃,并且永远不会再次用作目标。重启Router后,所有被丢弃服务器将再次可选。此策略向后兼容MySQL Router 2.x中mode为read-write的行为。

            现在7002端口的路由策略为first-available,下面依次停止172.16.1.125:3306、172.16.1.126:3306、172.16.1.127:3306,观察7002端口的访问情况。

    # 停止 172.16.1.125:3306
    [mysql@hdp2~]$mysqladmin -uwxy -p123456 -h172.16.1.125 -P3306 shutdown
    mysqladmin: [Warning] Using a password on the command line interface can be insecure.
    [mysql@hdp2~]$
    
    # 访问7002
    [mysql@hdp1~]$mysql -uwxy -p123456 -P7002 --protocol=TCP -e"select @@hostname"
    Warning: Using a password on the command line interface can be insecure.
    +------------+
    | @@hostname |
    +------------+
    | hdp3       |
    +------------+
    
    # 停止 172.16.1.126:3306
    [mysql@hdp3~]$mysqladmin -uwxy -p123456 -h172.16.1.126 -P3306 shutdown
    mysqladmin: [Warning] Using a password on the command line interface can be insecure.
    [mysql@hdp3~]$
    
    # 访问7002
    [mysql@hdp1~]$mysql -uwxy -p123456 -P7002 --protocol=TCP -e"select @@hostname"
    Warning: Using a password on the command line interface can be insecure.
    +------------+
    | @@hostname |
    +------------+
    | hdp4       |
    +------------+
    [mysql@hdp1~]$
    
    # 停止 172.16.1.127:3306
    [mysql@hdp4~]$mysqladmin -uwxy -p123456 -h172.16.1.127 -P3306 shutdown
    mysqladmin: [Warning] Using a password on the command line interface can be insecure.
    [mysql@hdp4~]$
    
    # 启动172.16.1.125:3306
    [mysql@hdp2~]$mysqld_safe --defaults-file=/etc/my.cnf &
    
    # 访问7002
    [mysql@hdp1~]$mysql -uwxy -p123456 -P7002 --protocol=TCP -e"select @@hostname"
    Warning: Using a password on the command line interface can be insecure.
    +------------+
    | @@hostname |
    +------------+
    | hdp2       |
    +------------+
    [mysql@hdp1~]$

            first-available总是循环查找目标列表中第一个可用服务器并连接它。将7002的策略改为next-available,把上面的步骤再做一遍,会看到最后的查询失败。即使此时172.16.1.125:3306可用也不会再次连接它,除非重启Router。

    # 最后的查询连接失败
    [mysql@hdp1~]$mysql -uwxy -p123456 -P7002 --protocol=TCP -e"select @@hostname"
    Warning: Using a password on the command line interface can be insecure.
    ERROR 2003 (HY000): Can't connect to remote MySQL server for client connected to 'localhost:7002'
    
    # 重启路由
    [mysql@hdp1~]$kill `ps -ef | grep router | grep -v grep | awk '{print $2}'`
    [mysql@hdp1~]$mysqlrouter -c ~/.mysqlrouter.conf &
    
    # 再次查询
    [mysql@hdp1~]$mysql -uwxy -p123456 -P7002 --protocol=TCP -e"select @@hostname"
    Warning: Using a password on the command line interface can be insecure.
    +------------+
    | @@hostname |
    +------------+
    | hdp2       |
    +------------+
    [mysql@hdp1~]$

            可以在网络上的单台或多台主机上运行多个MySQL路由器实例,而无需将MySQL Router隔离到单个机器上。这是因为MySQL Router对任何特定服务器或主机都不具有亲和性。要停止MySQL Router,只需用kill或killall命令直接杀掉相关进程。MySQL Router只起到一个转发流量的作用,它实在太“轻”了,以至都没有一个单独的停止命令。

    三、配置

            MySQL Router启动时可以从配置文件、扩展配置文件、命令行选项三个地方获取配置信息。本节说明MySQL Router配置文件的位置、配置文件语法和配置选项。

    1. 配置文件位置

    (1)缺省配置文件
            MySQL Router在启动时扫描缺省配置文件,并可选择在运行时从命令行加载用户定义的配置文件。默认情况下,MySQL Router扫描依赖于操作系统的特定位置以查找配置文件。执行mysqlrouter --help可以查看系统上的缺省配置文件位置:

    [mysql@hdp1~]$mysqlrouter --help | more
    MySQL Router  Ver 8.0.17 for linux-glibc2.12 on x86_64 (MySQL Community - GPL)
    Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
    
    Oracle is a registered trademark of Oracle Corporation and/or its
    affiliates. Other names may be trademarks of their respective
    owners.
    
    Configuration read from the following files in the given order (enclosed
    in parentheses means not available for reading):
      (/home/mysql/mysql-router-8.0.17-linux-glibc2.12-x86_64/bin/.././mysqlrouter.conf)
      (/home/mysql/mysql-router-8.0.17-linux-glibc2.12-x86_64/bin/.././mysqlrouter.ini)
      /home/mysql/.mysqlrouter.conf
      (/home/mysql/.mysqlrouter.ini)
    Plugins Path:
      /home/mysql/mysql-router-8.0.17-linux-glibc2.12-x86_64/lib/mysqlrouter
    
    Default Log Directory:
      /home/mysql/mysql-router-8.0.17-linux-glibc2.12-x86_64
    
    Default Persistent Data Directory:
      /home/mysql/mysql-router-8.0.17-linux-glibc2.12-x86_64/bin/../var/lib/mysqlrouter
    
    Default Runtime State Directory:
      /home/mysql/mysql-router-8.0.17-linux-glibc2.12-x86_64/bin/../run
    
    ...

            从帮助信息的开始部分可以看到MySQL Router查找的缺省配置文件和查找顺序。括号中的文件不可用,这里只有/home/mysql/.mysqlrouter.conf一个可用缺省配置文件。注意,如果使用-c或--config选项传入用户定义的配置文件,则不会加载缺省配置文件。

    (2)用户定义和扩展配置文件
            用户定义配置文件由-c或--config命令行选项指定,扩展配置文件由-a或--extra-config命令行选项指定。从缺省配置文件或使用--config选项指定的文件读取配置后,读取扩展配置文件:

    shell> mysqlrouter --config /custom/path/to/router.conf --extra-config /another/config.conf

    可以传入多个扩展配置选项,并按照输入的顺序加载文件:

    shell> mysqlrouter --config b.conf --extra-config a.conf --extra-config c.conf

    在上面的示例中,首先加载b.conf,然后按顺序加载a.conf和c.conf。此外由于使用了--config,不会加载缺省配置文件。每个加载的配置文件都会覆盖先前读取的配置文件中的设置。

    2. 配置文件语法

            MySQL Router配置文件格式类似于MySQL服务器的配置文件,符合传统INI文件格式,其中包含多个段,每个段中包含多个选项。选项中的目录支持支持正斜杠和反斜杠,反斜杠无条件复制而不是转义字符。配置文件可以包含注释行,注释行以井号(#)或分号(;)开头,并继续到行尾。注意只支持整行注释,不支持行中、行尾注释。(1)段
    每个配置文件都包含一个配置段列表,其中每个段包含一系列配置选项,每个配置选项都有名称和值,例如:

    [section name]
    option = value
    option = value
    option = value
    
    [section name:optional section key]
    option = value
    option = value
    option = value

            中括号中的是段名和可选的段键,段名与段键之间用冒号(:)分隔。段名和段键的组合对于配置是唯一的,中括号内不能有首尾空格。段名与段键由一个或多个字母、数字或下划线(_)的序列组成,不允许使用其它字符。

            段类似于命名空间。例如user选项,其含义取决于其关联的段。[DEFAULT]段中的user指的是运行MySQL Router的系统用户,该用户也受--user命令行选项控制。[metadata_cache]段中定义的user,指的是访问MySQL服务器元数据的MySQL用户。

            下面列举几个主要的段:

    • [DEFAULT]:DEFAULT是一个特殊的段,用于选项缺省值,在该段中查找其它段中没出现的选项,通常配置扩展配置文件的目录、日志的目录、MySQL Router运行时的目录(如pid文件)等。DEFAULT段不接受段键。
    • [logger]:logger段只有一个选项,设置日志的记录级别。
    • [routing:NAME]:该段是MySQL Router主要配置部分,设置不同的路由实例,其中NAME是自定义的段键名。

    (2)选项

            在段名之后,可以有一个零或多个选项行,其中每个选项行的形式如下:

    name = value

            处理之前将删除选项名称或选项值上的任何首尾空格。选项名称不区分大小写。选项值支持在大括号中引用选项名称,作为变量插入值。变量引用值是在检索选项值时完成的,而不是在读取配置文件时。如果变量未定义,则不进行替换,并按字面读取选项值。考虑下面的示例配置文件:

    [DEFAULT]
    prefix = /usr/
    
    [sample]
    bin = {prefix}bin/{name}
    lib = {prefix}lib/{name}
    name = magic
    directory = /data/{mysqlrouterdata}

    这里bin的值是“/usr/bin/magic”,lib的值是“/usr/lib/magic”。由于未定义名为“{mysqlrouterdata}”的变量,directory的值是“/data/{mysqlrouterdata}”。

            MySQL Router定义了配置文件可用的如下预定义变量。变量使用大括号,例如{program}作为Router可执行程序预定义变量。

    • program:程序的名称,通常是mysqlrouter。
    • origin:二进制文件所在目录。
    • logging_folder:日志文件所在目录。
    • plugin_folder:插件文件所在目录。
    • runtime_folder:运行时数据文件所在目录。
    • config_folder:配置文件所在目录。

    3. 配置文件示例

            启动时,MySQL Router会读取配置文件列表,这些配置文件一起构成Router的配置。至少需要一个配置文件,否则启动Router时会报 Error: No valid configuration file available 错误。下面是一个名为mycluster的MySQL InnoDB cluster的基本连接路由示例,读写流量发送到6446端口,只读访问使用6447端口。

    [DEFAULT]
    logging_folder=/opt/routers/myrouter/log
    runtime_folder=/opt/routers/myrouter/run
    data_folder=/opt/routers/myrouter/data
    connect_timeout=30
    read_timeout=30
    
    [logger]
    level = INFO
    
    [metadata_cache:mycluster]
    router_id=5
    bootstrap_server_addresses=mysql://localhost:3310,mysql://localhost:3320,mysql://localhost:3330
    user=mysql_router
    metadata_cluster=mycluster
    ttl=5
    
    [routing:mycluster_default_rw]
    bind_address=0.0.0.0
    bind_port=6446
    destinations=metadata-cache://mycluster/default?role=PRIMARY
    routing_strategy=round-robin
    
    [routing:mycluster_default_ro]
    bind_address=0.0.0.0
    bind_port=6447
    destinations=metadata-cache://mycluster/default?role=SECONDARY
    routing_strategy=round-robin

            该配置中定义了五个段:

    • [DEFAULT]中定义了数据文件目录、日志文件目录、运行时文件目录的位置,以及连接和读取MySQL元数据服务器的超时时间为30秒。
    • [logger]中定义日志级别为info,可选值有info、debug、warning、error、fatal,不区分大小写。
    • [metadata_cache:mycluster]中定义MySQL服务器元数据访问信息:router_id是整型的路由ID。bootstrap_server_addresses是逗号分隔的InnoDB cluster中的MySQL实例。user定义访问元数据的用户。metadata_cluster定义InnoDB cluster名称。ttl定义缓存时间为5秒。
    • [routing:mycluster_default_rw]和[routing:mycluster_default_ro]分别定义读写路由和只读路由。bind_address指定路由使用本机IP地址。配置文件中的bind_address选项只接受一个地址,但是可以使用bind_addres = 0.0.0.0绑定到localhost上的所有地址。bind_port指定客户端连接Router使用的端口。destinations引用由metadata-cache定义的目标地址,以利用InnoDB Cluster的元数据缓存来动态配置主机信息。如果不使用InnoDB Cluster,destinations可以指定为逗号分隔的IP:port地址,但bind_address中的地址不能出现在destinations列表中。routing_strategy定义路由策略,本例中读写和只读均为循环访问三个节点。

            配置选项的完整说明,参见https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-conf-options.html

            总的来说,MySQL Router从原理、安装、配置到部署使用都是如此轻而易举,可满足简单高可用应用场景的需求。

    展开全文
  • Vue基础知识总结 11:前端路由vue-router

    千次阅读 多人点赞 2021-10-06 17:11:44
    一、前端路由vue-router 1、维基百科 路由就是通过互联的网络把信息从源地址传输到目的地址的活动。 2、路由的机制 路由包括路由和转发。 路由器 -> 公网IP -> 映射表 -> 内网IP 映射表:[内网ip1:...

    🍅 作者简介:哪吒,CSDN2021博客之星亚军🏆、新星计划导师✌、博客专家💪

    🍅 哪吒多年工作总结:Java学习路线总结,搬砖工逆袭Java架构师

    🍅 关注公众号【哪吒编程】,回复1024,获取Java学习路线思维导图、大厂面试真题、加入万粉计划交流群、一起学习进步

    目录

    ​一、前端路由vue-router

    1、维基百科

    2、路由的机制

    3、后端渲染

    4、后端路由阶段

    ​5、前后端分离

    6、单页面富应用阶段

    7、SPA页面

    8、前端路由

    二、改变URL,但是页面不进行整体的刷新

    ​1、URL的hash

    2、HTML5的history 

    三、安装和使用vue-router

    1、安装vue-router

    2、在模块化工程中使用它(因为它是一个插件,所以可以通过Vue.use()来安装路由功能)

    3、使用vue-router的步骤

    4、router-link与router-view

    5、vue-router代码实例

     四、router-link的其它属性补充

    五、vue-router动态路由的使用

    六、vue-router打包文件的解析

    七、路由懒加载

    1、什么是懒加载

    2、懒加载的方式

    3、代码实例

    八、路由嵌套

    1、嵌套路由是一个很常见的功能

    2、实现嵌套路由的两个步骤

     3、嵌套路由代码实例

    九、vue-router参数传递

    1、传递参数主要有两种类型: params和query

    2、代码实例

    十、vue-router全局导航守卫

    1、生命周期函数

    2、前置守卫

    十一、keep-alive与vue-router


    ​一、前端路由vue-router

    1、维基百科

    路由就是通过互联的网络把信息从源地址传输到目的地址的活动。

    2、路由的机制

    路由包括路由和转发。
    路由器 -> 公网IP -> 映射表 -> 内网IP
    映射表:[内网ip1:电脑标识1,内网ip2:电脑标识2]

    3、后端渲染

    JSP:java server page
    后端渲染 == html + css + java
    java代码的作用是从数据库中读取数据,然后将他们动态的放在页面中。
    后端渲染的意思就是,前端请求后端,页面的数据在后端已经渲染好了,然后再返回前端,内容包括HTML+css,当然是包含数据的HTML。
    后端路由:后端处理URL和页面之间的映射关系。

    4、后端路由阶段

    早期的网站开发整个HTML页面是由服务器来渲染的。
    服务器直接生产渲染好对应的HTML页面, 返回给客户端进行展示。

    但是, 一个网站, 这么多页面服务器如何处理呢?

    1. 一个页面有自己对应的网址, 也就是URL。
    2. URL会发送到服务器, 服务器会通过正则对该URL进行匹配, 并且最后交给一个Controller进行处理。
    3. Controller进行各种处理, 最终生成HTML或者数据, 返回给前端。
    4. 这就完成了一个IO操作。

    上面的这种操作, 就是后端路由:

    • 当我们页面中需要请求不同的路径内容时, 交给服务器来进行处理, 服务器渲染好整个页面, 并且将页面返回给客户顿。
    • 这种情况下渲染好的页面, 不需要单独加载任何的js和css, 可以直接交给浏览器展示, 这样也有利于SEO的优化。 

    后端路由的缺点:

    1. 一种情况是整个页面的模块由后端人员来编写和维护的。
    2. 另一种情况是前端开发人员如果要开发页面, 需要通过PHP和Java等语言来编写页面代码。
    3. 而且通常情况下HTML代码和数据以及对应的逻辑会混在一起, 编写和维护都是非常糟糕的事情。

    ​5、前后端分离

    后端只负责提供数据,不负责其它任何阶段。
    浏览器中显示的网页中的大部分内容,都是由前端写的JS代码在浏览器中执行,最终渲染出来的网页。

    随着Ajax的出现, 有了前后端分离的开发模式。

    后端只提供API来返回数据, 前端通过Ajax获取数据, 并且可以通过JavaScript将数据渲染到页面中。

    这样做最大的优点就是前后端责任的清晰, 后端专注于数据上, 前端专注于交互和可视化上。
    并且当移动端(iOS/Android)出现后, 后端不需要进行任何处理, 依然使用之前的一套API即可。
    目前很多的网站依然采用这种模式开发。

    6、单页面富应用阶段

    其实SPA最主要的特点就是前后端分离的基础上加上了一层前端路由;
    也就是前端来维护一套路由规则

    7、SPA页面

    SPA:单页富应用
    整个网页只有一个HTML网页。

    8、前端路由

    URL和前端页面的映射关系。
    -----> vue router

    前端路由的核心是什么呢?
    改变URL,但是页面不进行整体的刷新。

    二、改变URL,但是页面不进行整体的刷新

    ​1、URL的hash

    URL的hash也就是锚点,本质上是改变window.location的href属性。
    我们可以通过直接赋值location.hash来改变href,但是页面不发生刷新。

    2、HTML5的history 

    history.pushState({},'','home')

    history.pushState相当于栈的操作,先进后出,弹栈和入栈的操作。

    history.pushState入栈;

    history.back()出栈;

    history.go(-1)  相当于 history.back();

    history.forward 相当于history.go(1);

    history.replaceState():不能返回;

    三、安装和使用vue-router

    1、安装vue-router

    npm install vue-router --save

    2、在模块化工程中使用它(因为它是一个插件,所以可以通过Vue.use()来安装路由功能)

    1. 导入路由对象,并且调用Vue.use(VueRouter)
    2. 创建路由实例,并传入路由映射配置
    3. 在Vue实例中挂载创建的路由实例

    3、使用vue-router的步骤

    1. 创建路由组件
    2. 配置路由映射,组件和路径映射关系
    3. 使用路由:通过<router-link>和<router-view>

    4、router-link与router-view

    <router-link>:该标签是一个vue-router中已经内置的组件,它会被渲染成一个<a>标签。
    <router-view>:该标签会根据当前的路径,动态渲染出不同的组件。
    网页的其他内容,比如顶部的标题/导航,或者底部的一些版权信息等会和<router-view>处于同一个等级。
    在路由切换时,切换的是<router-view>挂载的组件,其他内容不会发生改变。

    5、vue-router代码实例

    (1)App.vue

    <template>
      <div id="app">
        <router-link to="/home" >首页</router-link>
        <router-link to="/about">关于</router-link>
        <router-view></router-view>
      </div>
    </template>
    
    <script>
    export default {
      name: 'App'
    }
    </script>
    

    (2)Home.vue

    <template>
      <div>
        <h2>我是首页</h2>
        <p>我是首页内容, 哈哈哈</p>
      </div>
    </template>
    
    <script>
      export default {
        name: "Home"
      }
    </script>
    
    <style scoped>
    
    </style>
    

    (3)About.vue

    <template>
      <div>
        <h2>我是关于</h2>
        <p>我是关于内容, 呵呵呵</p>
      </div>
    </template>
    
    <script>
      export default {
        name: "About"
      }
    </script>
    
    <style scoped>
    
    </style>
    

    (4)main.js

    import Vue from 'vue'
    import App from './App'
    import router from './router'
    
    Vue.config.productionTip = false
    
    new Vue({
      el: '#app',
      router,
      render: h => h(App)
    })
    

    (5)index.js

    // 配置路由相关的信息
    import VueRouter from 'vue-router'
    import Vue from 'vue'
    
    import Home from '../components/Home'
    import About from '../components/About'
    
    // 1.通过Vue.use(插件), 安装插件
    Vue.use(VueRouter)
    
    // 2.创建VueRouter对象
    const routes = [
      {
        path: '',
        // redirect重定向
        redirect: '/home'
      },
      {
        path: '/home',
        component: Home
      },
      {
        path: '/about',
        component: About
      }
    ]
    const router = new VueRouter({
      // 配置路由和组件之间的应用关系
      routes,
      mode: 'history',
      linkActiveClass: 'active'
    })
    
    // 3.将router对象传入到Vue实例
    export default router
    
    

    (6)浏览器展示

     四、router-link的其它属性补充

    1. tag:tag可以指定router-link之后渲染成什么组件,比如<router-link tag='button'></router-link>,此时就是一个button了;
    2. replace:增加replace属性,就相当于replaceState;
    3. class:可以为标签增加样式,比如选中的会自动赋值router-link-active;
    4. active-class=“active”:选中的;也可以在router组件中配置linkActiveClass: 'active';

    通过代码跳转路由:

    <script>
    export default {
      name: 'App',
      methods: {
        homeClick() {
          // 通过代码的方式修改路由 vue-router
          // push => pushState
          this.$router.push('/home')
          //this.$router.replace('/home')
          console.log('homeClick');
        },
        aboutClick() {
          this.$router.push('/about')
          //this.$router.replace('/about')
          console.log('aboutClick');
        }
      }
    }
    </script>

    五、vue-router动态路由的使用

    在某些情况下,一个页面的path路径可能是不确定的,比如我们进入用户界面时,希望路径中存在用户id,这种path和Component相互匹配的关系,我们称之为动态路由,也是路由传递数据的一种方式。

    this.$route表示正在活跃的路由。

    获取路径中的姓名:

    ...
    <router-link :to="'/user/'+userId">用户</router-link>
    ...
    <template>
      <div>
        <h2>我是用户界面</h2>
        <p>我是用户的相关信息, 嘿嘿嘿</p>
        <h2>{{userId}}</h2>
        <h2>{{$route.params.id}}</h2>
        <button @click="btnClick">按钮</button>
      </div>
    </template>
    
    <script>
      export default {
        name: "User",
        computed: {
          userId() {
            return this.$route.params.id
          }
        }
    </script>

    六、vue-router打包文件的解析

    七、路由懒加载

    1、什么是懒加载

    当打包构建应用时,JavaScript包会变得非常大,影响页面加载。

    如果我们能吧不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。

    2、懒加载的方式

    (1)结合Vue的异步组件和Webpack的代码分析

    const Home = resolve => { require.ensure(['../components/Home.vue'], 
    () => { resolve(require('../components/Home.vue')) })};
    

    (2)amd写法

    const About = resolve => require(['../components/About.vue'], resolve);
    

    (3)ES6我们可以有更加简单的写法来组织Vue异步组件和Webpack的代码分割

    const Home = () => import('../components/Home.vue')
    

    3、代码实例

    index.js

    // import Home from '../components/Home'
    // import About from '../components/About'
    // import User from '../components/User'
    
    // 懒加载方式
    const Home = () => import('../components/Home')
    const About = () => import('../components/About')
    const User = () => import('../components/User')

    八、路由嵌套

    1、嵌套路由是一个很常见的功能

    比如在home页面中,我们希望通过/home/news和/home/message访问一些内容;

    一个路径映射一个组件,访问这两个路径也分别渲染这两个组件;

    2、实现嵌套路由的两个步骤

    1. 创建对应的子组件,并且在路由映射中配置对应的子路由;
    2. 在组件内部使用<router-view>标签;

     3、嵌套路由代码实例

    (1)index.js

    // 配置路由相关的信息
    import VueRouter from 'vue-router'
    import Vue from 'vue'
    
    const Home = () => import('../components/Home')
    const HomeNews = () => import('../components/HomeNews')
    const HomeMessage = () => import('../components/HomeMessage')
    
    const About = () => import('../components/About')
    const User = () => import('../components/User')
    const Profile = () => import('../components/Profile')
    
    // 1.通过Vue.use(插件), 安装插件
    Vue.use(VueRouter)
    
    // 2.创建VueRouter对象
    const routes = [
      {
        path: '',
        // redirect重定向
        redirect: '/home'
      },
      {
        path: '/home',
        component: Home,
        meta: {
          title: '首页'
        },
        children: [
          {
            path: 'news',
            component: HomeNews
          },
          {
            path: 'message',
            component: HomeMessage
          }
        ]
      }
    ]
    const router = new VueRouter({
      // 配置路由和组件之间的应用关系
      routes,
      mode: 'history',
      linkActiveClass: 'active'
    })
    
    // 3.将router对象传入到Vue实例
    export default router
    
    

    (2)Home.vue

    <template>
      <div>
        <h2>我是首页</h2>
        <p>我是首页内容, 哈哈哈</p>
    
        <router-link to="/home/news">新闻</router-link>
        <router-link to="/home/message">消息</router-link>
    
        <router-view></router-view>
    
        <h2>{{message}}</h2>
      </div>
    </template>
    
    <script>
      export default {
        name: "Home",
        data() {
          return {
            message: '你好啊',
            path: '/home/news'
          }
        }
      }
    </script>
    
    <style scoped>
    
    </style>
    

    (3)HomeNews.vue

    <template>
      <div>
        <ul>
          <li>美女1</li>
          <li>美女2</li>
          <li>美女3</li>
          <li>美女4</li>
        </ul>
      </div>
    </template>
    
    <script>
      export default {
        name: "HomeNews"
      }
    </script>
    
    <style scoped>
    
    </style>
    

    九、vue-router参数传递

    1、传递参数主要有两种类型: params和query

    params的类型:

    1. 配置路由格式: /router/:id
    2. 传递的方式: 在path后面跟上对应的值
    3. 传递后形成的路径: /router/123, /router/abc

    query的类型:

    1. 配置路由格式: /router, 也就是普通配置
    2. 传递的方式: 对象中使用query的key作为传递方式
    3. 传递后形成的路径: /router?id=123, /router?id=abc
       

    2、代码实例

    (1)传值

    <script>
    ...
    export default {
      ...
      methods: {
        userClick() {
          this.$router.push('/user/' + this.userId)
        },
        profileClick() {
          this.$router.push({
            path: '/profile',
            query: {
              name: 'kobe',
              age: 19,
              height: 1.87
            }
          })
        }
      }
    }
    </script>

    (2)取值

    <template>
      <div>
        <h2>{{$route.query.name}}</h2>
        <h2>{{$route.query.age}}</h2>
        <h2>{{$route.query.height}}</h2>
      </div>
    </template>
    

    十、vue-router全局导航守卫

    1、生命周期函数

    <script>
      export default {
        name: "Home",
        data() {
          return {
            message: '你好啊',
            path: '/home/news'
          }
        },
        created() {
          console.log('home created');
        },
        destroyed() {
          console.log('home destroyed');
        },
        // 这两个函数, 只有该组件被保持了状态使用了keep-alive时, 才是有效的
        activated() {
          this.$router.push(this.path);
          console.log('activated');
        },
        deactivated() {
          console.log('deactivated');
        },
        beforeRouteLeave (to, from, next) {
          console.log(this.$route.path);
          this.path = this.$route.path;
          next()
        }
      }
    </script>

    2、前置守卫

    (1)动态修改标题

    跳转前回调

    // 前置守卫(guard)
    router.beforeEach((to, from, next) => {
      // 从from跳转到to
      document.title = to.matched[0].meta.title
      // 必须调用next(),表示执行下一步的意思
      next()
    })
    

    (2)beforeEach源码分析:

     (3)跳转后回调

    // 后置钩子(hook)
    router.afterEach((to, from) => {
      // console.log('--我是CSDN哪吒--');
    })

    十一、keep-alive与vue-router

    keep-alive是vue内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。

    router-view也是一个组件,如果直接被包在keep-alive里面,所有路径匹配到的试图组件都会被缓存。

    🍅 作者简介:哪吒,CSDN2021博客之星亚军🏆、新星计划导师✌、博客专家💪

    🍅 哪吒多年工作总结:Java学习路线总结,搬砖工逆袭Java架构师

    🍅 关注公众号【哪吒编程】,回复1024,获取Java学习路线思维导图、大厂面试真题、加入万粉计划交流群、一起学习进步

     关注公众号,回复1024,获取Java学习路线思维导图、加入万粉计划交流群

    展开全文
  • Vue Router4路由

    千次阅读 2021-08-04 15:12:48
    Vue Router4路由 官网:https://next.router.vuejs.org/zh/guide/essentials/route-matching-syntax.html 1、在vue-router是什么? Vue.js 的官方路由(就这么简单一句话) 2、Vue Router4 新特性 简单对比总结了...

    Vue Router4路由

    官网:vue-router4

    1、Vue-router是什么?

    Vue.js 的官方路由(就这么简单一句话)

    2、Vue Router4 新特性

    简单对比总结了一下

    • Vue3支持最新版本由于Vue 3 引入了createApp API,该API更改了将插件添加到Vue实例的方式。 因此,以前版本的Vue Router将与Vue3不兼容。Vue Router 4 引入了createRouter API,该API创建了一个可以在Vue3中安装 router 实例。
    • History选项在Vue Router 4中,这些模式已被抽象到模块中,可以将其导入并分配给新的history 选项。 这种额外的灵活性让我们可以根据需要自定义路由器。
    // Vue Router 4
    import { createRouter, createWebHistory } from "vue-router";
    export default createRouter({
      history: createWebHistory(),
      routes: [],
    });
    
    • 动态路由Vue Router 4 提供了addRoute方法实现动态路由。这个方法平时比较少用到,但是确实有一些有趣的用例。 例如,假设我们要为文件系统应用程序创建UI,并且要动态添加路径。 我们可以按照以下方式进行操作:
    methods: {
      uploadComplete (id) {
        router.addRoute({
          path: `/uploads/${id}`,
          name: `upload-${id}`,
          component: FileInfo
        });
      }
    }
    
    • 导航守卫可以返回值并非next导航守卫是Vue Router的钩子,允许用户在跳转之前或之后运行自定义逻辑,例如 beforeEachbeforeRouterEnter等。它们通常用于检查用户是否有权访问某个页面,验证动态路由参数或销毁侦听器。在版本4中,我们可以从hook 方法中中返回值或Promise。 这样可以方便快捷地进行如下操作:

      // Vue Router 3
      router.beforeEach((to, from, next) => {
        if (!isAuthenticated) {
          next(false);
        }
        else { 
          next();
        }
      })
      // Vue Router 4
      router.beforeEach(() => isAuthenticated);
      

    3、安装和配置router.js文件

    npm install vue-router@4//一般使用npm,4.x的版本最新
    
    import {
        createRouter,
        createWebHashHistory
    } from 'vue-router'
    
    import Server from "../components/distribution_services/Index.vue"
    import Data from "../components/data_processing/Index.vue"
    import Visual from "../components/three_dimensional_visualization/Index.vue"
    import Details from "../components/authorization_details/index.vue"
    import Buy from "../components/authorized_purchase/Index.vue"
    import Terrain from "../components/distribution_services/terrain/Index.vue"
    import Image from "../components/distribution_services/image/Index.vue"
    import Lodmodel from "../components/distribution_services/lodModel/Index.vue"
    import Resource from "../components/distribution_services/assets/Index.vue"
    import Scene from "../components/distribution_services/scene/Index.vue"
    import Tile from "../components/distribution_services/model/Index.vue"
    import Tilt from "../components/distribution_services/osgb/Index.vue"
    
    const router = createRouter({
        history: createWebHashHistory(), // hash模式:createWebHashHistory,history模式:createWebHistory
        //hash 模式使用URL哈希来模拟完整的URL,以便在URL更改时不会重新加载页面。 history 模式利用 HTML5 History API 来实现URL导航,也是无需重新加载页面。
        linkExactActiveClass: 'active',//配置高亮
        routes: [{
                path: '/',
                name: 'data',
                components: {
                    out: Data
                }
            },
            {
                path: '/server',
                name: 'server',
                redirect: '/server/terrain', //首个重定向
                components: {
                    out: Server
                },
                //路由嵌套使用children
                children: [{
                        path: 'terrain',
                        name: 'terrain',
                        components: {
                            inside: Terrain
                        },
                    }, {
                        path: 'image',
                        name: 'image',
                        components: {
                            inside: Image
                        },
                    },
                    {
                        path: 'lodmodel',
                        name: 'lodmodel',
                        components: {
                            inside: Lodmodel
                        },
                    },
                    {
                        path: 'resource',
                        name: 'resource',
                        components: {
                            inside: Resource
                        },
                    },
                    {
                        path: 'scene',
                        name: 'scene',
                        components: {
                            inside: Scene
                        },
                    },
                    {
                        path: 'tile',
                        name: 'tile',
                        components: {
                            inside: Tile
                        },
                    },
                    {
                        path: 'tilt',
                        name: 'tilt',
                        components: {
                            inside: Tilt
                        },
                    },
                ]
            },
            {
                path: '/visual',
                name: 'visual',
                components: {
                    out: Visual
                }
            },
            {
                path: '/details',
                name: 'details',
                components: {
                    out: Details
                }
            },
            {
                path: '/buy',
                name: 'buy',
                components: {
                    out: Buy
                }
            }
    
        ]
    })
    
    export default router
    

    以上是routerjs文件,在vue4中引入router

    app.use(router)
    

    高亮配置

    • 通过router.js中 linkExactActiveClass: ‘active’,//配置高亮
    • 然后在css中.router-link-active{background:#fff}即可

    4、router-link和router-view

    • router-link 自定义组件,用来创建链接,可实现不重新加载页面的情况下更改URL地址,通过传入to 属性指定链接。
    • router-view 将显示与 url 对应的组件,相当于一个视图窗口

    视图注意点:我们如果多个router-view的时候,怎么指定view视图窗口?

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K94mzuLO-1628061158392)(C:\Users\13689\AppData\Roaming\Typora\typora-user-images\image-20210804094325051.png)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iVleYbRA-1628061158395)(C:\Users\13689\AppData\Roaming\Typora\typora-user-images\image-20210804095238467.png)]
    配置router.js文件中components中可以看到,属性名称是router-view的对应名称,自定义即可

    5、路由嵌套

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JYJp1ggP-1628061158396)(C:\Users\13689\AppData\Roaming\Typora\typora-user-images\image-20210804134824489.png)]

    如你所见,children 配置只是另一个路由数组,就像 routes 本身一样。因此,你可以根据自己的需要,不断地嵌套视图。

    6、编程式导航

    这个更编程化思想一点,我个人用到link连接多一点

    6.1导航不同位置

    除了使用 <router-link> 创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现。

    在 Vue 实例中,你可以通过 $router 访问路由实例。因此你可以调用 this.$router.push

    想要导航到不同的 URL,可以使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,会回到之前的 URL。

    声明式编程式
    <router-link :to="...">router.push(...)

    该方法的参数可以是一个字符串路径,或者一个描述地址的对象。例如:

    // 字符串路径
    router.push('/users/eduardo')
    
    // 带有路径的对象
    router.push({ path: '/users/eduardo' })
    
    // 命名的路由,并加上参数,让路由建立 url
    router.push({ name: 'user', params: { username: 'eduardo' } })
    
    // 带查询参数,结果是 /register?plan=private
    router.push({ path: '/register', query: { plan: 'private' } })
    
    // 带 hash,结果是 /about#team
    router.push({ path: '/about', hash: '#team' })
    

    注意:如果提供了 pathparams 会被忽略,上述例子中的 query 并不属于这种情况。取而代之的是下面例子的做法,你需要提供路由的 name 或手写完整的带有参数的 path

    const username = 'eduardo'
    // 我们可以手动建立 url,但我们必须自己处理编码
    router.push(`/user/${username}`) // -> /user/eduardo
    // 同样
    router.push({ path: `/user/${username}` }) // -> /user/eduardo
    // 如果可能的话,使用 `name` 和 `params` 从自动 URL 编码中获益
    router.push({ name: 'user', params: { username } }) // -> /user/eduardo
    // `params` 不能与 `path` 一起使用
    router.push({ path: '/user', params: { username } }) // -> /user
    

    由于属性 torouter.push 接受的对象种类相同,所以两者的规则完全相同。

    6.2替换当前位置

    它的作用类似于 router.push,唯一不同的是,它在导航时不会向 history 添加新记录,正如它的名字所暗示的那样——它取代了当前的条目。

    声明式编程式
    <router-link :to="..." replace>router.replace(...)

    也可以直接在传递给 router.pushrouteLocation 中增加一个属性 replace: true

    router.push({ path: '/home', replace: true })
    // 相当于
    router.replace({ path: '/home' })
    

    6.3横跨历史

    该方法采用一个整数作为参数,表示在历史堆栈中前进或后退多少步,类似于 window.history.go(n)。图下所示

    // 向前移动一条记录,与 router.forward() 相同
    router.go(1)
    
    // 返回一条记录,与router.back() 相同
    router.go(-1)
    
    // 前进 3 条记录
    router.go(3)
    
    // 如果没有那么多记录,静默失败
    router.go(-100)
    router.go(100)
    

    6.4篡改历史

    router.pushrouter.replacerouter.gowindow.history.pushStatewindow.history.replaceStatewindow.history.go 的翻版,它们确实模仿了 window.history 的 API。
    因此,在使用 Vue Router 时,操作历史记录就会觉得很熟悉。

    7、重定向

    7.1重定向得使用场景

    首先学习和使用一项技术要知道为什么要用?应用场景是什么?在官网中并没有直接解释说明,只是上来告诉如何去用

    下边看例子

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yjEv5e1b-1628061158397)(C:\Users\13689\AppData\Roaming\Typora\typora-user-images\image-20210804141543593.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k5qK4nGt-1628061158398)(C:\Users\13689\AppData\Roaming\Typora\typora-user-images\image-20210804141520882.png)]

    以上两图得区别是什么?当我点击一级路由时会显示二级目录,但是这个时候我想默认选中/重定向一个二级路由,这时候怎么办?当我点击一级路由时候,这个时候重定向二级路由中一个,当成默认选项

    7.2如何设置重定向?

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OZKGciZY-1628061158399)(C:\Users\13689\AppData\Roaming\Typora\typora-user-images\image-20210804141737915.png)]

    • 重定向也是通过 routes 配置来完成,下面例子是从 /a 重定向到 /b
    const routes = [{ path: '/home', redirect: '/' }]
    
    • 重定向的目标也可以是一个命名的路由:
    const routes = [{ path: '/home', redirect: { name: 'homepage' } }]
    
    • 甚至是一个方法,动态返回重定向目标:
    const routes = [
      {
        // /search/screens -> /search?q=screens
        path: '/search/:searchText',
        redirect: to => {
          // 方法接收目标路由作为参数
          // return 重定向的字符串路径/路径对象
          return { path: '/search', query: { q: to.params.searchText } }
        },
      },
      {
        path: '/search',
        // ...
      },
    ]
    

    8、导航守卫

    导航守卫,顾名思义就是用户在跳转之前或之后运行自定义逻辑来实现一定的目的.

    应用场景当没有登录的时候导航跳转的时候,重定向到login路由中(登录和内容区域是同一个页面)

    // to代表将要访问的路径
    // from代表从哪个路径跳转过来
    // next是函数,表示放行
    router.beforeEach((to,from,next) => {
      if(to.path === '/login') return next();
      const tokenStr = window.sessionStorage.getItem('token');//获取token值
      if(!tokenStr) return next('/login');
      next()
    })
    
    展开全文
  • Vue中路由 (Vue Router)

    千次阅读 2021-12-23 15:13:38
    Vue中路由 (Vue Router) 一、 vue中路由 Router 路由:根据请求的路径按照一定的路由规则进行请求的转发从而帮助我们实现统一请求的管理 概念:它和vue.js的核心深度集成,让构成单页面应用变得易如反掌 理解:让组件...
  • react-router-dom v6 使用

    万次阅读 多人点赞 2021-11-19 00:07:56
    react-router-dom react-router-dom v6 整体体验相对于 v5 ,体验要好更多,最大的一个改变,就是曾经的 Route 不可嵌套,整个路由配置必须拆分成若干小块,除非通过 react-router-config 这种插件,才可以实现对...
  • 而用 Vue.js + Vue Router 创建单页应用,感觉很自然:使用 Vue.js ,我们已经可以通过组合组件来组成应用程序,当你要把 Vue Router 添加进来,我们需要做的是,将组件 (components) 映射到路由 (routes),然后告诉...
  • vue-router 详解

    万次阅读 多人点赞 2021-01-16 12:15:20
    文章目录1、认识vue-router2、安装和使用vue-router 1、认识vue-router 目前前端流行的三大框架,都有自己的路由实现: Angular的ngRouter React的ReactRouter Vue的vue-router vue-router是Vue.js官方的路由插件...
  • Vue路由(vue-router)详细讲解指南

    万次阅读 2022-01-19 10:21:49
    Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。路由实际上就是可以理解为指向,就是我在页面上点击一个按钮需要跳转到对应的页面,这就是路由跳转; 首先我们...
  • Vue-router的使用(vue3.0版本)

    千次阅读 2021-08-20 15:17:47
    vue-router 使用过程一级目录二级目录三级目录 一级目录 vue-router有三个概念 route, routes, router。 1, route,一条路由,它是单数,点击内容后跳转到指定内容,index按钮 => index内容, 这是一条route, ...
  • Vue 3.X 使用Vue Router 4.x 进行路由配置,本文我们就来研究下如何使用Vue Router 4.x,本文中所有的使用方式都是使用 Composition API的方式。 本文通过一步步介绍Vue Router 4.x的使用,来搭建一个简单的博客系统...
  • react-router v6 路由统一管理及路由拦截方案

    千次阅读 热门讨论 2022-01-07 10:38:33
    上一篇分享了react-router v5 版本的路由管理及拦截方案,但也存在一些缺陷,例如不支持嵌套路由、不支持动态路由参数等。 后来看到了react-router v6 版本useRoutes api 的特性,决定升级到v6版本,并对路由管理和...
  • MySQL Router 介绍篇

    千次阅读 2021-01-19 08:02:11
    MySQL Router 是什么?相信还有很多人没有听说过MySQL Router,很多人对它还不了解,在这篇文章里,将对MySQL Router进行一个简明介绍。首先,介绍一下MySQL Router推出的背景。MySQL Router 是一个轻量级的中间件,...
  • Vue全家桶系列之Vue-router(三)

    千次阅读 2021-09-06 22:51:16
    上篇文章说了vue-router的基本使用,接下来看下其他的使用方法 2.路由的重定向 还是拿之前的例子,有3个页面(home,about,help) 如果都没有匹配上,那怎么办?我可以让它重定向home页面,这里重定向有多种写法,...
  • MikroTik RouterOS v6.27 L6许可,可顺利升级到7.x版本。 此文件为VMware的导出文件。可安装到VMware Workstation和VMware ESX服务器。 默认用户名admin 密码为空
  • RouterOS 6.48.6 安装与配置

    千次阅读 2022-03-25 17:46:51
    手头刚好有台旧的Dell服务器,板载两个网口,后来又扩展了一个4网口的网卡这样就有了六个网口,用它安装RouterOS,来实现NTH多线路带宽叠加,以及来做PCC负载均衡的实验就足够了。 说干就干,首先来到Mikrotik的官网...
  • router文件夹

    千次阅读 2020-12-20 19:06:36
    [success] # router文件夹说明接下来会讲一下 **正常路由结构** ,以及 **封装好的路由结构**。>[success] ## 正常路由**创建项目初始化路由** 会在 **src文件夹** 下生成一个 **router.js** 文件。**router.js**...
  • 超详细解读OSPF Router-ID

    千次阅读 2021-11-06 19:24:32
    理解OSPF Router-ID 1:原理概述: 一些动态路由协议要求使用Router-ID作为路由器的身份标示,如果在启动这些路由协议时没有指定Router-ID,则路由进程可能无法正常启动。 Router-ID选举规则为,如果通过Router-...
  • vue router总结 $router和$route及routerrouter与route区别

    千次阅读 多人点赞 2019-10-03 15:54:41
    1 this.$router和this.$route的区别 vue router this.$router是VueRouter的实例方法,当导航到不同url,可以使用this.$router.push方法,这个方法则会向history里面添加一条记录,当点击浏览器回退按钮或者this.$...
  • Vue-cli4——vue-router路由

    千次阅读 2020-11-18 13:34:27
    Vue-cli4——vue-router路由(一) Day1 文章目录Vue-cli4——vue-router路由(一)前言一、代码解析1.1 src/router/index.js1.2 src/App.vue二、实例2.1 简单的实例2.2 在网页中不显示#号2.3 重定向2.4 router-...
  • Vue router2.0

    千次阅读 2022-04-24 15:58:03
    使用Vue安装 npm install vue-router --save 路由的引入 import router from './router' /* eslint-disable no-new */ new Vue({ el: '#app', store, router, components: { App }, template: '<App/>...
  • React Router 6 (React路由) 最详细教程

    千次阅读 2022-03-29 02:21:40
    **React Router** 经历多个版本的发展,现在已经到了 **React Router 6**。虽然网络上写 React-Router 路由本身的教程很多,但真正讲到 React-Router 6 的并不多。同时因为第 6 版引入了很多新的概念,以及大量使用 ...
  • Vue3 / Ts Router详解

    千次阅读 2022-03-25 15:02:32
    router/index.ts import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router"; // 2. 配置路由 const routes: Array<RouteRecordRaw> = [ { path: "/login", component: () => ...
  • Vue路由——vue-router

    千次阅读 2022-01-27 23:18:11
    前端路由与后端路由 路由 路由(routing):指从源到目的地时,决定端到端路径的决策过程。 路由分为两大类:前端路由和后端...const router=express.Router() router.get('/login',function(req,res){ 路由的处理函数
  • 那就是路由vue-router,以及数据请求axios了。 axios的用法与vue2的差别不大,就是一些ts的语法问题,所以也就不对axios的用法做介绍了,本篇来介绍下vue-router路由的使用。 本篇也不从创建项目开始了,对vite+vue...
  • vue-router 路由传参

    千次阅读 2022-03-18 18:09:59
    vue-router传递参数分为两大类: 编程式的导航 router.push 声明式的导航 <router-link>
  • react-router-dom从V5升级到V6后,有些使用做了一些改变: (1) Switch 重命名为 Routes // v5 <Switch> <Route exact path="/"><Home /></Route> <Route path="/profile"><...
  • router-view 和 router-link 的区别

    千次阅读 2022-01-26 12:59:52
    1、router-view 和 router-link 的区别 1.router-link和router-view在同一个vue文件(A.vue)里面, 2. router-link设置路由跳转, // <router-link :to="'/url/'"> <li> <a>login</a&...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 453,790
精华内容 181,516
关键字:

router