前端学习-前端路由

176 阅读1分钟

前端路由

前端路由,指的是 URL 与内容间的映射关系

Hash 方式

通过 hashchange 事件监听 hash 变化,并进行网页内容更新。

<div>
    <a href="#/">首页</a>
    <a href="#/category">分类页</a>
    <a href="#/user">用户页</a>
  </div>
  <div id="container">
    这是首页功能
</div>

<script>
    // 准备对象,用于封装 hash 功能。
    var router = {
      // 路由存储位置: 保存了 url 与 内容处理函数的对应关系。
      routes: {},
      // 定义路由规则的方法
      route: function (path, callback) {
        //将path作为key存储到routes对象,因为path是字符串所以必须用中括号的形式
        this.routes[path] = callback;
      },
      // 初始化路由的方法
      init: function () {
        //因为window.onhashchange中的this指向的是window,需要访问对象中的其他内容可以将this提前赋值给一个变量
        var that = this;
        window.onhashchange = function () {
          // 当 hash 改变,我们需要得到当前新的 hash
          var hash = location.hash.replace('#', '');
          // 根据 hash 触发 routes 中的对应 callback,通过&&运算符判断假如routes存在对应的函数则进行调用
          that.routes[hash] && that.routes[hash]();
        };
      }
    };

    var container = document.getElementById('container');
    // 定义路由规则
    router.route('/', function () {
      container.innerHTML = '这是首页功能';
    });
    router.route('/category', function () {
      container.innerHTML = '这是分类功能';
    });
    router.route('/user', function () {
      container.innerHTML = '这是用户功能';
    });

    // 初始化路由
    router.init();


</script>

特点总结:

  • Hash 方式兼容性好。
  • 地址中具有 #,不太美观。
  • 前进后退功能较为繁琐。

History 方式

  • History 方式采用 HTML5 提供的新功能实现前端路由

  • 在操作时需要通过 history.pushState() 变更 URL并执行对应操作。

<div>
    <a href="/">首页</a>
    <a href="/category">分类</a>
    <a href="/user">用户</a>
</div>
<div id="container">
    这是首页功能
</div>

<script>
    var router = {
      // 存储路由的对象
      routes: {},
      // 定义路由的方法
      route (path, callback) {
        this.routes[path] = callback;
      },
      // 用于触发指定的路由操作
      go (path) {
        // 更改 url
        history.pushState(null, null, path);
        // 触发路由对应的回调函数
        this.routes[path] && this.routes[path]();
      }
    };

    // 设置 a 标签的功能
    var links = document.querySelectorAll('a');
    var container = document.querySelector('#container');

    links.forEach(function (ele) {
      ele.addEventListener('click', function (event) {
        //通过getAttribute获取href的内容
        router.go(this.getAttribute('href'));
        //阻止跳转
        event.preventDefault();
      });
    });

    // 路由规则
    router.route('/', function () {
      container.innerHTML = '首页功能';
    });

    router.route('/category', function () {
      container.innerHTML = '分类功能';
    });

    router.route('/user', function () {
      container.innerHTML = '用户功能';
    });

</script>

前进后退功能

  • 首先需要在更改 url 时保存路由标记。
  • 通过 popstate 事件监听前进后退按钮操作,并检测 state。
  • 调用初始化方法监听前进后退操作并处理。
 <div>
    <a href="/">首页</a>
    <a href="/category">分类</a>
    <a href="/user">用户</a>
</div>
<div id="container">
    这是首页功能
</div>

<script>
    var router = {
      // 存储路由的对象
      routes: {},
      // 定义路由的方法
      route (path, callback) {
        this.routes[path] = callback;
      },
      // 用于触发指定的路由操作
      go (path) {
        // 更改 url
        history.pushState({ path: path }, null, path);
        // 触发路由对应的回调函数
        this.routes[path] && this.routes[path]();
      },
      // 设置初始化方法,用来检测前进后退按钮的功能
      init () {
        var that = this;
        window.addEventListener('popstate', function (e) {
          var path = e.state ? e.state.path : '/';
          that.routes[path] && that.routes[path]();
        });
      }
    };

    router.init();

    // 设置 a 标签的功能
    var links = document.querySelectorAll('a');
    var container = document.querySelector('#container');

    links.forEach(function (ele) {
      ele.addEventListener('click', function (event) {
        router.go(this.getAttribute('href'));
        event.preventDefault();
      });
    });

    // 路由规则
    router.route('/', function () {
      container.innerHTML = '首页功能';
    });

    router.route('/category', function () {
      container.innerHTML = '分类功能';
    });

    router.route('/user', function () {
      container.innerHTML = '用户功能';
    });   

  </script>

特点总结:

  • 书写简答格式美观
  • pushState可存储数据量更大
  • 兼容性差
  • 刷新页面时需要后端支持