Flutter自动路由插件auto_route使用详解

目录
  • 一、简介
  • 二、基本使用
    • 2.1 安装插件
    • 2.2 定义路由表
    • 2.3 生成路由
    • 2.4 路由跳转
    • 2.5 处理返回结果
  • 三、路由导航
    • 3.1 嵌套导航
    • 3.2 Tab 导航
    • 3.3 PageView
    • 3.4 声明式导航
  • 四、高级用法
    • 4.1 路由控制器
    • 4.2 Paths
      • 4.2.1 Path Parameters
      • 4.2.2 Inherited Path Parameters
      • 4.2.3 Query Parameters
      • 4.2.4 Redirecting Paths
    • 4.3 路由守护
    • 4.4 路由观察者

一、简介

在Flutter应用开发过程中,多个页面的跳转需要使用路由,除了官方提供的Navigator外,我们还可以使用一些第三方路由框架来实现页面的管理和导航,如Fluro、Frouter等。不过,今天要给大家介绍的是另一款路由框架auto_route。

auto_route是一个设计精简、低耦合的路由框架,支持自动生成路由代码、动态添加路由、以及路由的参数传递等功能。相比其他的路由框架,auto_route的使用也更加简洁。

二、基本使用

2.1 安装插件

和其他Flutter插件的使用流程一样,使用之前需要先在项目中安装auto_route插件,安装的的脚本如下:

dependencies:
  auto_route: [latest-version]
dev_dependencies:
  auto_route_generator: [latest-version]
  build_runner:

2.2 定义路由表

接下来,定义一个路由表的管理类,用来同意管理应用的路由,需要使用@MaterialAutoRouter注解进行标识,如下。

@MaterialAutoRouter(
  replaceInRouteName: 'Page,Route',
  routes: <AutoRoute>[
    AutoRoute(page: BookListPage, initial: true),
    AutoRoute(page: BookDetailsPage),
  ],
)
class $AppRouter {}

要生成路由文件的一部分而不是独立的 AppRouter 类,只需将 Part 指令添加到AppRouter 并扩展生成的私有路由器即可。

part 'app_router.gr.dart';
@MaterialAutoRouter(
  replaceInRouteName: 'Page,Route',
  routes: <AutoRoute>[
    AutoRoute(page: BookListPage, initial: true),
    AutoRoute(page: BookDetailsPage),
  ],
)
class AppRouter extends _$AppRouter{}

接下来,我们使用build_runner提供的命令即可生成路由代码。

//自动刷新路由表
flutter packages pub run build_runner watch
//生成路由代码
flutter packages pub run build_runner build

等待命令执行完成之后,即可在app_router.dart同级的目录下生成一个app_route.gr.dart文件,也是我们执行路由跳转时需要用到的代码。最后,我们打开main.dart入口文件,然后注册路由文件。

class App extends StatelessWidget {
  final _appRouter = AppRouter();
  @override
  Widget build(BuildContext context){
    return MaterialApp.router(
      routerDelegate: _appRouter.delegate(),
      routeInformationParser: _appRouter.defaultRouteParser(),
    );
  }
}

2.3 生成路由

当然,auto_route还支持为每个声明的 AutoRoute 生成一个 PageRouteInfo 对象,这些对象包含路径信息以及从页面的默认构造函数中提取的强类型页面参数。

class BookListRoute extends PageRouteInfo {
  const BookListRoute() : super(name, path: '/books');
  static const String name = 'BookListRoute';
}

并且,如果声明的路由有子路由,那么 AutoRoute 会在其构造函数中添加一个子参数,如下。

class UserRoute extends PageRouteInfo {
   UserRoute({List<PagerouteInfo> children}) :
    super(
         name,
         path: '/user/:id',
         initialChildren: children);
  static const String name = 'UserRoute';
}

2.4 路由跳转

和其他的路由框架一样,AutoRouter 也提供常见的 push、pop 和 remove 方法。比如,我们要打一个新的页面,那么可以使用下面

AutoRouter.of(context).replaceAll([const LoginRoute()]);  //LoginRoute为路由
//或者
AutoRouter.of(context).navigate(const BooksListRoute())

如果我们使用的是命名路由,那么可以使用navigateNamed()方法,如下。

AutoRouter.of(context).pushNamed('/books') ;

当然,很多时候,路由的跳转还会涉及很多的参数传递,那么对于需要传递参数的路由,我们需要怎么处理呢?对于参数传递,我们可以在目标路由页面使用构造函数的方式,然后再用AutoRouter进行传递。

AutoRouter.of(context).pushAll([IndexRoute(login: true)]);

除了跳转,我们还可能需要处理路由弹栈的场景,对于弹栈,需要用到pop()函数。和其他的路由框架一样,pop()默认只弹出一个,如果要弹出多个,可以使用下面的方式。

//弹出到指定的路由
context.router.popUntilRouteWithName('HomeRoute');
//弹出到最顶部
context.router.popUntilRoot();

如果要清除,或者删除路由栈里面的内容,可以是呀AutoRouter还提供了remove()函数。

context.router.removeLast();
context.router.removeWhere((route) => );

下面是AutoRouter常用方法的一个汇总。

context.pushRoute(const BooksListRoute());
context.replaceRoute(const BooksListRoute());
context.navigateTo(const BooksListRoute());
context.navigateNamedTo('/books');
context.navigateBack();
context.popRoute();

2.5 处理返回结果

有时候,两个路由之间,需要获取页面的处理结果,并将结果返回给上一个页面。对于这种场景,只需要在返回的时候返回结果即可,并在上一个路由使用await进行接收。

router.pop<bool>(true);
var result = await router.push<bool>(LoginRoute());

三、路由导航

3.1 嵌套导航

在应用开发中,嵌套导航是一种比较常见的场景,这意味着,在一个路由页面中嵌套另外的多个路由。

嵌套路由就像父路由的子字段一样。在上面的示例中,UsersPage、PostsPage 和SettingsPage就是DashboardPage的子路由,所以它们的定义如下。

@MaterialAutoRouter(
  replaceInRouteName: 'Page,Route',
  routes: <AutoRoute>[
    AutoRoute(
      path: '/dashboard',
      page: DashboardPage,
      children: [
        AutoRoute(path: 'users', page: UsersPage),
        AutoRoute(path: 'posts', page: PostsPage),
        AutoRoute(path: 'settings', page: SettingsPage),
      ],
    ),
    AutoRoute(path: '/login', page: LoginPage)
  ],
)
class $AppRouter {}

要完成嵌套路由渲染和构建,我们需要在嵌套路由的最外层使用AutoRouter 的小部件,如下。

class DashboardPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Column(
          children: [
            NavLink(label: 'Users', destination: const UsersRoute()),
            NavLink(label: 'Posts', destination: const PostsRoute()),
            NavLink(label: 'Settings', destination: const SettingsRoute()),
          ],
        ),
        Expanded(
          // nested routes will be rendered here
          child: AutoRouter(),
        )
      ],
    );
  }
}

如果我们需要跳转到嵌套路由的子组件,我们使用下面的方式就可以导航到嵌套路由的子路由。

AutoRoute(
      path: '/dashboard',
      page: DashboardPage,
      children: [
        AutoRoute(path: '', page: UsersPage),
        //The same thing can be done using the initial flag
        //AutoRoute(page: UsersPage,initial: true),
        AutoRoute(path: 'posts', page: PostsPage),
      ],
    ),

3.2 Tab 导航

前面我们介绍的都是栈管理,即StackRouter,遵循先进后出的逻辑。除了支持StackRouter,auto_route还支持Tab Navigation,下面是示例代码。

class DashboardPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return AutoTabsRouter(
      routes: const [
        UsersRoute(),
        PostsRoute(),
        SettingsRoute(),
      ],
      builder: (context, child, animation) {
        final tabsRouter = AutoTabsRouter.of(context);
        return Scaffold(
            body: FadeTransition(
              opacity: animation,
              child: child,
            ),
            bottomNavigationBar: BottomNavigationBar(
              currentIndex: tabsRouter.activeIndex,
              onTap: (index) {
                tabsRouter.setActiveIndex(index);
              },
              items: [
                BottomNavigationBarItem(label: 'Users',...),
                BottomNavigationBarItem(label: 'Posts',...),
                BottomNavigationBarItem(label: 'Settings',...),
              ],
            ));
      },
    );
  }
}

当然,上面的代码看起来有点复杂,所以如果我们只是实现Tab导航,那么可以使用下面的简洁代码。

class DashboardPage extends StatelessWidget {
 @override
Widget build(context) {
 @override
  Widget build(context) {
    return AutoTabsScaffold(
       routes: const [
        UsersRoute(),
        PostsRoute(),
        SettingsRoute(),
      ],
      bottomNavigationBuilder: (_,tabsRouter) {
          return BottomNavigationBar(
              currentIndex: tabsRouter.activeIndex,
              onTap: tabsRouter.setActiveIndex
              items: [
                BottomNavigationBarItem(label: 'Users',...),
                BottomNavigationBarItem(label: 'Posts',...),
                BottomNavigationBarItem(label: 'Settings',...),
              ],
            )),
       }
    );
}

3.3 PageView

当然,我们也可以使用 AutoTabsRouter.pageView 构造函数来实现使用 PageView 的选项卡。

AutoTabsRouter.pageView(
     routes: [
        BooksTab(),
        ProfileTab(),
        SettingsTab(),
        ],
     builder: (context, child, _) {
        return Scaffold(
              appBar: AppBar(
              title: Text(context.topRoute.name),
              leading: AutoLeadingButton()),
              body: child,
              bottomNavigationBar: BottomNavigationBar(
                    currentIndex: tabsRouter.activeIndex,
                    onTap: tabsRouter.setActiveIndex
                    items: [
                      BottomNavigationBarItem(label: 'Books',...),
                      BottomNavigationBarItem(label: 'Profile',...),
                      BottomNavigationBarItem(label: 'Settings',...),
                    ],
                  ),
            ),
      ); },
   );

3.4 声明式导航

声明式导航需要与 auto_route 一起使用,只需要使用 AutoRouter.declarative 构造函数并返回基于状态的路由列表即可。

AutoRouter.declarative(
  routes: (handler) => [
     BookListRoute(),
     if(_selectedBook != null)
     BookDetailsRoute(id: _selectedBook.id),
 ],);

四、高级用法

4.1 路由控制器

事实上,每个嵌套的 AutoRouter 都有自己的路由控制器来管理其内部的堆栈,获得路由控制器最简单的方法是使用上下文。在前面的示例中,我们调用的 AutoRouter.of(context) 就是用来获得根路由控制器的。

需要说明的是,对于渲染嵌套路由的 AutoRouter 小部件,我们使用上面的方式获取的 是小部件树中最近的父控制器而不是根控制器,下面是一个典型的路由控制器的结构示意图。

从上图中可以看出,我们可以通过调用 router.parent() 来访问父路由控制器,对于这个通用函数,在真正调用的时候,我们还需要指定类型,比如StackRouter/TabsRouter。

router.parent<StackRouter>()
router.parent<TabsRouter>()

当然,如果是获取根路由控制器,那么是不需要进行类型转换的,因为它始终是 StackRouter。

router.root

另一方面,为了在其他地方使用这个路由控制器,可以定义一个全局的key,比如。

class DashboardPage extends StatefulWidget {
  @override
  _DashboardPageState createState() => _DashboardPageState();
}
class _DashboardPageState extends State<DashboardPage> {
  final _innerRouterKey = GlobalKey<AutoRouterState>();
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Column(
          children: [
            NavLink(label: 'Users',
            onTap:(){
               final router = _innerRouterKey.currentState?.controller;
               router?.push(const UsersRoute());
             }
            ),
            ...
          ],
        ),
        Expanded(
          child: AutoRouter(key: _innerRouterKey),
        )
      ],
    );
  }
}

当然,我们也可以在没有全局key的情况下,使用下面的方式获取路由控制器,条件是这个路由已经启动,这个有点类似于Java的反射机制。

context.innerRouterOf<StackRouter>(UserRoute.name)
context.innerRouterOf<TabsRouter>(UserRoute.name)

4.2 Paths

在 AutoRoute 中,使用路径是可选的,因为 PageRouteInfo 对象是按名称匹配的,除非使用根委托中的 initialDeepLink、pushNamed、replaceNamed和navigateNamed 等方法。

如果我们不指定路径,系统将自动生成路径,例如BookListPage 将“book-list-page”作为路径,如果初始 arg 设置为 true,则路径将为“/”。在Flutter开发中,当页面层级比较深时,就可以使用paths方式。

AutoRoute(path: '/books', page: BookListPage),

4.2.1 Path Parameters

当然,我们还可以在paths中添加参数。

AutoRoute(path: '/books/:id', page: BookDetailsPage),

然后,我们只需要在目标路由使用 @PathParam('optional-alias') 方式即可获取传递的参数,比如。

class BookDetailsPage extends StatelessWidget {
  const BookDetailsPage({@PathParam('id') this.bookId});
  final int bookId;
  ...

4.2.2 Inherited Path Parameters

不过,如果使用 @PathParm() 标识的构造函数参数与路由没有同名的路径参数但它的父级有,那么该路径参数将被继承并且生成的路由不会将此作为参数。

AutoRoute(
	  path: '/product/:id',
	  page: ProductScreen,
	  children: [
		  AutoRoute(path: 'review',page: ProductReviewScreen),
	 ],
 ),

当然,我们还可以在路由页面添加一个名为 id 的路径参数,从上面的示例中,我们知道ProductReviewScreen没有路径参数,在这种情况下,auto_route 将检查是否有任何祖先路径可以提供此路径参数,如果有则会标记它作为路径参数,否则会引发错误。

class ProductReviewScreen extends StatelessWidget {
  const ProductReviewScreen({super.key, @pathParam required String id});
}

4.2.3 Query Parameters

和前面的查询参数的方式相同,只需使用 @QueryParam('optional-alias') 注解构造函数参数即可获取参数的值。

RouteData.of(context).pathParams;
context.routeData.queryParams

如果参数名称与路径/查询参数相同,则可以使用 const @pathParam 或者@queryParam 并且不需要传递 slug/别名,比如。

class BookDetailsPage extends StatelessWidget {
  const BookDetailsPage({@pathParam this.id});
  final int id;
  ...

4.2.4 Redirecting Paths

当然,我们也可以使用RedirectRoute来实现路径的重定向,重定向路径时需要使用redirectTo参数指定重定后的路由,比如。

<AutoRoute> [
     RedirectRoute(path: '/', redirectTo: '/books'),
     AutoRoute(path: '/books', page: BookListPage),
 ]

当然,使用重定向时还可以跟一些参数,比如。

<AutoRoute> [
     RedirectRoute(path: 'books/:id', redirectTo: '/books/:id/details'),
     AutoRoute(path: '/books/:id/details', page: BookDetailsPage),
 ]

除此之外,auto_route 还支持使用通配符来匹配无效或未定义的路径,可以将它作为默认的路径。

AutoRoute(path: '*', page: UnknownRoutePage)
AutoRoute(path: '/profile/*', page: ProfilePage)
RedirectRoute(path: '*', redirectTo: '/')

4.3 路由守护

我们可以将路由守卫视为中间件或者拦截器,不经过分配的守卫无法将路由添加到堆栈中,这对于限制对某些路由的访问是很有用,相当于在执行路由跳转前我们可以对路由做一些限制。

下面,我们使用 AutoRouteGuard 创建一个路由保护,然后在 onNavigation 方法中实现我们的路由逻辑。

class AuthGuard extends AutoRouteGuard {
 @override
 void onNavigation(NavigationResolver resolver, StackRouter router) {
      //触发条件
     if(authenitcated){
        resolver.next(true);
      }else{
         router.push(LoginRoute(onResult: (success){
               resolver.next(success);
          }));
         }
     }
}

在onNavigation方法中,NavigationResolver 对象包含可以调用的属性,所以我们可以使用resolver.route 访问的受保护路由,以及调用resolver.pendingRoutes 访问挂起的路由列表。

接下来,我们将守卫分配给我们想要保护的路线即可,使用方式如下。

AutoRoute(page: ProfileScreen, guards: [AuthGuard]);

有时候,我们希望获取父窗口包裹的小部件的上下文提供的一些值,那么只需实现 AutoRouteWrapper,并让 WrapRoute(context) 方法返回小部件的子级即可。

class ProductsScreen extends StatelessWidget implements AutoRouteWrapper {
  @override
  Widget wrappedRoute(BuildContext context) {
  return Provider(create: (ctx) => ProductsBloc(), child: this);
  }
  ...

4.4 路由观察者

为了方便查看路由栈的具体情况,我们可以通过扩展 AutoRouterObserver 来实现,然后重写里面的函数来进行查看,比如。

class MyObserver extends AutoRouterObserver {
  @override
  void didPush(Route route, Route? previousRoute) {
    print('New route pushed: ${route.settings.name}');
  }
 @override
  void didInitTabRoute(TabPageRoute route, TabPageRoute? previousRoute) {
    print('Tab route visited: ${route.name}');
  }
  @override
  void didChangeTabRoute(TabPageRoute route, TabPageRoute previousRoute) {
    print('Tab route re-visited: ${route.name}');
  }
}

然后,我们将观察者传递给根委托 AutoRouterDelegate。

return MaterialApp.router(
      routerDelegate: AutoRouterDelegate(
        _appRouter,
        navigatorObservers: () => [MyObserver()],
      ),
      routeInformationParser: _appRouter.defaultRouteParser(),
    );

以上就是Flutter自动路由插件auto_route使用详解的详细内容,更多关于Flutter自动路由插件的资料请关注我们其它相关文章!

(0)

相关推荐

  • Flutter app页面路由以及路由拦截的实现

    为什么要使用路由 在之前我们的代码中,页面跳转使用的代码如下所示: Navigator.of(context).push( MaterialPageRoute(builder: (context) => LoginPage()), ); 在开发过程中,随着页面的增加,如果继续使用这种方式会有如下缺陷: 代码耦合严重:涉及到页面跳转的地方就需要插入页面的构造函数,意味着需要知道其他页面的构建方式. 不易维护:一旦某个页面发生了变化,需要将涉及到该页面的跳转全部改变. 权限控制不方便:假设某些页面需

  • Flutter路由之fluro的配置及跳转

    目录 1.pubspec.yaml导包,注意格式~ 2.新建路由类,改类是定义页面的路径,然后将页面handler和路径设置到路由中 3.新建router_handler.dart,处理参数和跳转页面 4.调用传参 5.接收数据 6.问题来了,因为fluro无法直接传中文的,这里就需要用到编码码解码了,也就是encode和decode 1.pubspec.yaml导包,注意格式~ dependencies: flutter: sdk: flutter fluro: ^1.6.3 2.新建路由类,

  • Flutter路由传递参数及解析实现

    上一篇Flutter页面路由及404路由拦截实现介绍了使用路由来实现页面的跳转,从而简化页面之间的耦合,并可以实现路由拦截.在实际开发中,我们经常会需要在页面跳转的时候携带路由参数,典型的例子就是从列表到详情页的时候,需要携带详情的 id,以便详情页获取对应的数据.同时,有些时候还需要返回时携带参数返回上一级,以便上级页面根据返回结果更新.本篇将介绍这两种情形的实现. Navigator 的 push 和 pop方法 Navigator 导航器的 push 和 pop 方法可以携带参数在页面间传

  • Flutter如何完成路由拦截,实现权限管理

    之前几篇介绍了 fluro 的路由管理和转场动画,本篇介绍如何完成路由拦截,进而实现权限管理."此路是我开,此树是我栽.若是没权限,403到来!" 相关文章 若想了解 flutter 的路由相关篇章,请查阅下面的篇章: //www.jb51.net/article/215167.htm //www.jb51.net/article/214856.htm //www.jb51.net/article/215564.htm //www.jb51.net/article/215549.htm

  • flutter 路由机制的实现

    目录 实现基础 _routeNamed _flushHistoryUpdates add push pop remove 总结 整个 flutter 应用的运行都只是基于原生应用中的一个 view,比如 android 中的 FlutterView,flutter 中的页面切换依赖于它的路由机制,也就是以 Navigator 为中心的一套路由功能,使得它能够完成与原生类似且能够自定义的页面切换效果. 下面将介绍 flutter 中的路由实现原理,包括初始化时的页面加载.切换页面的底层机制等. 实

  • Flutter 路由插件fluro的使用

    前面两篇文章我们介绍了Flutter 的原生导航器 Navigator 实现页面跳转,路由及路由拦截的使用,具体可以参考之前的文章: //www.jb51.net/article/215167.htm //www.jb51.net/article/214856.htm 使用原生的路由基本上能够满足大部分需求,但如果想要对页面做类似浏览器 url 那样的路由,或者控制页面跳转的转场动画,那么原生的路由需要做不少的改造.在 pub 上,有优秀的路由插件 fluro 解决这类问题. fluro的使用方

  • Flutter自动路由插件auto_route使用详解

    目录 一.简介 二.基本使用 2.1 安装插件 2.2 定义路由表 2.3 生成路由 2.4 路由跳转 2.5 处理返回结果 三.路由导航 3.1 嵌套导航 3.2 Tab 导航 3.3 PageView 3.4 声明式导航 四.高级用法 4.1 路由控制器 4.2 Paths 4.2.1 Path Parameters 4.2.2 Inherited Path Parameters 4.2.3 Query Parameters 4.2.4 Redirecting Paths 4.3 路由守护

  • 使用JQuery自动完成插件Auto Complete详解

    问题 当你查找一些特殊的东西,当你输入准确的词时,找到它可能是困难的(或者很耗时).在输入的时候展示出结果(自动完成),使查找变得更简单. 解决方案 使用JQuery自动完成插件,更新现有图书列表页面上的搜索,当用户键入的时候立即显示结果. 讨论 自动完成插件是不会象jQuery基本库一样自动包含在MVC项目中的,所以需要做的第一件事就是的是下载插件 访问http://jquery.com/.两个主要的文件是必需的:JavaScript文件和CSS文件.把新下载的javascript文件放到你M

  • jquery拖拽自动排序插件使用方法详解

    本文为大家分享了jquery拖拽自动排序插件,供大家参考,具体内容如下 该插件并不是原生js写的,是基于jquery的,想看原生的话,请绕道而行. html: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script type="text/javas

  • Flutter permission_handler 权限插件的使用详解

    编译环境:Flutter 版本v1.12.hotfix9 dart SDK:2.7.2 1 pubspec.yaml中引入: #  权限   permission_handler: ^3.2.0 ios中info.plist配置(根据权限情况使用): <!-- Permission options for the `location` group --> <key>NSLocationWhenInUseUsageDescription</key> <string&

  • Flutter状态管理Bloc使用示例详解

    目录 前言 两种使用模式 Cubit模式 最后 前言 目前Flutter三大主流状态管理框架分别是provider.flutter_bloc.getx,三大状态管理框架各有优劣,本篇文章将介绍其中的flutter_bloc框架的使用,他是bloc设计思想模式在flutter上的实现,bloc全程全称 business logic ,业务逻辑的意思,核心思想就是最大程度的将页面ui与数据逻辑的解耦,使我们的项目可读性.可维护性.健壮性增强. 两种使用模式 首先第一步引入插件: flutter_bl

  • Flutter使用Android原生播放器详解

    接上篇:播放器-IOS(Swift)篇 安卓端原生播放器的接入思路与ios基本一致,所以本篇就不废话了,直接上代码: 创建插件VideoViewPlugin实现FlutterPlugin: package io.flutter.plugins.videoplayer; import android.util.Log; import androidx.annotation.NonNull; import io.flutter.embedding.engine.plugins.FlutterPlug

  • Bootstrap 折叠(Collapse)插件用法实例详解

    Bootstrap,来自 Twitter,是目前最受欢迎的前端框架.Bootstrap 是基于 HTML.CSS.JAVASCRIPT 的,它简洁灵活,使得 Web 开发更加快捷.下面通过本文给大家介绍Bootstrap 折叠(Collapse)插件用法实例,一起看看吧! 折叠(Collapse)插件可以很容易地让页面区域折叠起来.无论您用它来创建折叠导航还是内容面板,它都允许很多内容选项. 如果您想要单独引用该插件的功能,那么您需要引用 collapse.js.同时,也需要在您的 Bootst

  • jQuery的图片轮播插件PgwSlideshow使用详解

    0 PgwSlideshow简介 PgwSlideshow是一款基于Jquery的图片轮播插件,基本布局分为上下结构,上方为大图轮播区域,用户可自定义图片轮播切换的间隔时间,也可以通过单击左右方向按键实现图片切换:下方为要轮播的所有图片的缩略图展示,可直接单击缩略图快速切换图片. PgwSlideshow主要有以下特点: •体验度很好的响应式设计 •支持桌面及移动设备 •身形矫健,压缩后的文件只有不到4KB •你可以自定义或者直接修改基本的css样式来给你想要的轮播插件美个容 PgwSlides

  • Cisco路由技术基础知识详解之一

    Cisco路由技术基础知识详解 路由器 <一> 最简单的网络可以想象成单线的总线,各个计算机可以通过向总线发送分组以互相通信.但随着网络中的计算机数目增长,这就很不可行了,会产 生许多问题: 1.带宽资源耗尽.     2.每台计算机都浪费许多时间处理无关的广播数据.     3.网络变得无法管理,任何错误都可能导致整个网络瘫痪.     4.每台计算机都可以监听到其他计算机的通信. 把网络分段可以解决这些问题,但同时你必须提供一种机制使不同网段的计算机可以互相通信,这通常涉及到在一些ISO网

  • Cisco路由技术基础知识详解

    Cisco路由技术基础知识详解 路由器 <一> 最简单的网络可以想象成单线的总线,各个计算机可以通过向总线发送分组以互相通信.但随着网络中的计算机数目增长,这就很不可行了,会产 生许多问题: 1.带宽资源耗尽.     2.每台计算机都浪费许多时间处理无关的广播数据.     3.网络变得无法管理,任何错误都可能导致整个网络瘫痪.     4.每台计算机都可以监听到其他计算机的通信. 把网络分段可以解决这些问题,但同时你必须提供一种机制使不同网段的计算机可以互相通信,这通常涉及到在一些ISO网

随机推荐