vue 之路由vue-router

vue 之路由vue-router

什么是路由

  1. 后端路由: 对于普通的网站,所有的超链接都是URL地址,所有的URL地址都对应服务器上对应的资源;

  2. 前端路由: 对于单页面应用程序来说,主要通过URL中的hash(#号)来实现不同页面之间的切换,同时,hash有一个特点:HTTP请求中不会包含hash相关的内容;所以,单页面程序中的页面跳转主要用hash实现;

  3. 在单页面应用程序中,这种通过hash改变来切换页面的方式,称作前端路由(区别于后端路由);

在 vue 中使用 vue-router

  1. 导入 vue-router 组件类库:
  <script src="./lib/vue-router-2.7.0.js"></script>
  1. 使用 router-link 组件来导航
<router-link to="/login">登录</router-link>
<router-link to="/register">注册</router-link>
  1. 使用 router-view 组件来显示匹配到的组件
<router-view></router-view>
  1. 创建使用Vue.extend创建组件
    var login = Vue.extend({
      template: '

登录组件

'
}); // 4.2 使用 Vue.extend 来创建注册组件 var register = Vue.extend({ template: '

注册组件

'
});
  1. 创建一个路由 router 实例,通过 routers 属性来定义路由匹配规则
    var router = new VueRouter({
      routers: [
        { path: '/login', component: login },
        { path: '/register', component: register }
      ]
    });
  1. 使用 router 属性来使用路由规则
    var vm = new Vue({
      el: '#app',
      router: router // 使用 router 属性来使用路由规则
    });

完整代码:

<div id="app">
    //router-link 默认渲染为一个a 标签 
    <router-link to="/login" tag="span">登录</router-link>
    <router-link to="/register">注册</router-link>
    //这是 vue-router 提供的元素,专门用来 当作占位符的,将来,路由规则,匹配到的组件,就会展示到这个 router-view 中去
    //可以把 router-view 认为是一个占位符
    <transition mode="out-in">
      <router-view></router-view>
    </transition>
  </div>

  <script>
    // 组件的模板对象
    var login = {
      template: '

登录组件

'
} var register = { template: '

注册组件

'
} // 创建一个路由对象, 当 导入 vue-router 包之后,在 window 全局对象中,就有了一个 路由的构造函数,叫做 VueRouter // 在 new 路由对象的时候,可以为 构造函数,传递一个配置对象 var routerObj = new VueRouter({ // route // 这个配置对象中的 route 表示 【路由匹配规则】 的意思 routes: [ // 路由匹配规则 // 每个路由规则,都是一个对象,这个规则对象,身上,有两个必须的属性: // 属性1 是 path, 表示监听 哪个路由链接地址; // 属性2 是 component, 表示,如果 路由是前面匹配到的 path ,则展示 component 属性对应的那个组件 // 注意: component 的属性值,必须是一个 组件的模板对象, 不能是 组件的引用名称; // { path: '/', component: login }, { path: '/', redirect: '/login' }, // 这里的 redirect 和 Node 中的 redirect 完全是两码事 { path: '/login', component: login }, { path: '/register', component: register } ], // linkActiveClass: 'myactive' }) // 创建 Vue 实例,得到 ViewModel var vm = new Vue({ el: '#app', data: {}, methods: {}, router: routerObj // 将路由规则对象,注册到 vm 实例上,用来监听 URL 地址的变化,然后展示对应的组件 }); </script>

在路由规则中定义参数

  1. 在规则中定义参数:
{ path: '/register/:id', component: register }
  1. 通过 this.$route.params来获取路由中的参数:
var register = Vue.extend({
      template: '

注册组件 --- {{this.$route.params.id}}

'
});

完整代码:

<div id="app">

    // 如果在路由中,使用 查询字符串,给路由传递参数,则 不需要修改 路由规则的 path 属性
    <router-link to="/login?id=10&name=zs">登录</router-link>
    <router-link to="/register">注册</router-link>
    <router-view></router-view>
  </div>

  <script>

    var login = {
      template: '

登录 --- {{ $route.query.id }} --- {{ $route.query.name }}

'
, data(){ return { msg: '123' } }, created(){ // 组件的生命周期钩子函数 // console.log(this.$route) // console.log(this.$route.query.id) } } var register = { template: '

注册

'
} var router = new VueRouter({ routes: [ { path: '/login', component: login }, { path: '/register', component: register } ] }) // 创建 Vue 实例,得到 ViewModel var vm = new Vue({ el: '#app', data: {}, methods: {}, // router: router router }); </script>

在路由规则中传参

<div id="app">

   //如果在路由中,使用 查询字符串,给路由传递参数,则 不需要修改 路由规则的 path 属性
    <router-link to="/login/12/ls">登录</router-link>
    <router-link to="/register">注册</router-link>
    <router-view></router-view>
  </div>
  <script>
    var login = {
      template: '

登录 --- {{ $route.params.id }} --- {{ $route.params.name }}

'
, data(){ return { msg: '123' } }, created(){ // 组件的生命周期钩子函数 console.log(this.$route.params.id) } } var register = { template: '

注册

'
} var router = new VueRouter({ routes: [ { path: '/login/:id/:name', component: login }, { path: '/register', component: register } ] }) // 创建 Vue 实例,得到 ViewModel var vm = new Vue({ el: '#app', data: {}, methods: {}, // router: router router }); </script>

使用 children 属性实现路由嵌套

<div id="app">
    <router-link to="/account">Account</router-link>
    <router-view></router-view>
  </div>
  <template id="tmpl">
    <div>
      <h1>这是 Account 组件</h1>
      <router-link to="/account/login">登录</router-link>
      <router-link to="/account/register">注册</router-link>
      <router-view></router-view>
    </div>
  </template>
  <script>
    // 组件的模板对象
    var account = {
      template: '#tmpl'
    }
    var login = {
      template: '

登录

'
} var register = { template: '

注册

'
} var router = new VueRouter({ routes: [ { path: '/account', component: account, // 使用 children 属性,实现子路由,同时,子路由的 path 前面,不要带 / ,否则永远以根路径开始请求,这样不方便我们用户去理解URL地址 children: [ { path: 'login', component: login }, { path: 'register', component: register } ] } ] }) // 创建 Vue 实例,得到 ViewModel var vm = new Vue({ el: '#app', data: {}, methods: {}, router }); </script>

命名视图实现经典布局

  1. 标签代码结构:
<div id="app">
    <router-view></router-view>
    <div class="container">
      <router-view name="left"></router-view>
      <router-view name="main"></router-view>
    </div>
  </div>
  1. JS代码:
<script>
    var header = {
      template: '

Header头部区域

'
} var leftBox = { template: '

Left侧边栏区域

'
} var mainBox = { template: '

mainBox主体区域

'
} // 创建路由对象 var router = new VueRouter({ routes: [ /* { path: '/', component: header }, { path: '/left', component: leftBox }, { path: '/main', component: mainBox } */ { path: '/', components: { 'default': header, 'left': leftBox, 'main': mainBox } } ] }) // 创建 Vue 实例,得到 ViewModel var vm = new Vue({ el: '#app', data: {}, methods: {}, router }); </script>
  1. CSS 样式:
 <style>
    html,
    body {
      margin: 0;
      padding: 0;
    }

    .header {
      background-color: orange;
      height: 80px;
    }

    h1 {
      margin: 0;
      padding: 0;
      font-size: 16px;
    }
    .container {
      display: flex;
      height: 600px;
    }
    .left {
      background-color: lightgreen;
      flex: 2;
    }
    .main {
      background-color: lightpink;
      flex: 8;
    }
  </style>

watch属性的使用

考虑一个问题:想要实现 两个文本框的内容改变,则全名的文本框中的值也跟着改变;(用以前的知识如何实现???)

  1. 监听data中属性的改变:
 <div id="app">
    <input type="text" v-model="firstname"> +
    <input type="text" v-model="lastname"> =
    <input type="text" v-model="fullname">
  </div>
  <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        firstname: '',
        lastname: '',
        fullname: ''
      },
      methods: {},
      watch: { // 使用这个 属性,可以监视 data 中指定数据的变化,然后触发这个 watch 中对应的 function 处理函数
        'firstname': function (newVal, oldVal) {
          // console.log('监视到了 firstname 的变化')
          // this.fullname = this.firstname + '-' + this.lastname
          // console.log(newVal + ' --- ' + oldVal)
          this.fullname = newVal + '-' + this.lastname
        },
        'lastname': function (newVal) {
          this.fullname = this.firstname + '-' + newVal
        }
      }
    });
  </script>

在这里插入图片描述
2. 监听路由对象的改变:

<div id="app">
    <router-link to="/login">登录</router-link>
    <router-link to="/register">注册</router-link>
    <router-view></router-view>
  </div>

  <script>
    var login = Vue.extend({
      template: '

登录组件

'
}); var register = Vue.extend({ template: '

注册组件

'
}); var router = new VueRouter({ routes: [ { path: "/login", component: login }, { path: "/register", component: register } ] }); // 创建 Vue 实例,得到 ViewModel var vm = new Vue({ el: '#app', data: {}, methods: {}, router: router, watch: { '$route': function (newVal, oldVal) { if (newVal.path === '/login') { console.log('这是登录组件'); } } } }); </script>

computed计算属性的使用

  1. 默认只有getter的计算属性:
<div id="app">
    <input type="text" v-model="firstName"> +
    <input type="text" v-model="lastName"> =
    <span>{{fullName}}</span>
  </div>

  <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        firstName: 'jack',
        lastName: 'chen'
      },
      methods: {},
      computed: { // 计算属性; 特点:当计算属性中所以来的任何一个 data 属性改变之后,都会重新触发 本计算属性 的重新计算,从而更新 fullName 的值
        fullName() {
          return this.firstName + ' - ' + this.lastName;
        }
      }
    });
  </script>
  1. 定义有gettersetter的计算属性:
<div id="app">
    <input type="text" v-model="firstName">
    <input type="text" v-model="lastName">
    //点击按钮重新为 计算属性 fullName 赋值 
    <input type="button" value="修改fullName" @click="changeName">
    <span>{{fullName}}</span>
  </div>

  <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        firstName: 'jack',
        lastName: 'chen'
      },
      methods: {
        changeName() {
          this.fullName = 'TOM - chen2';
        }
      },
      computed: {
        fullName: {
          get: function () {
            return this.firstName + ' - ' + this.lastName;
          },
          set: function (newVal) {
            var parts = newVal.split(' - ');
            this.firstName = parts[0];
            this.lastName = parts[1];
          }
        }
      }
    });
  </script>

watchcomputedmethods之间的对比

  1. computed属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。主要当作属性来使用;
  2. methods方法表示一个具体的操作,主要书写业务逻辑;
  3. watch一个对象,键是需要观察的表达式,值是对应回调函数。主要用来监听某些特定数据的变化,从而进行某些具体的业务逻辑操作;可以看作是computedmethods的结合体;

Vue的路由实现:hash模式 和 history模式

hash模式: 在浏览器中符号“#”,#以及#后面的字符称之为hash,用window.location.hash读取;
特点: hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面。
hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 http://www.xxx.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误。

history模式: history采用HTML5的新特性;且提供了两个新方法:pushState()replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更。
history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如 http://www.xxx.com/items/id。后端如果缺少对 /items/id 的路由处理,将返回 404 错误。Vue-Router 官网里如此描述:“不过这种模式要玩好,还需要后台配置支持……所以要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是 app 依赖的页面。”

你可能感兴趣的:(vue,vue,路由)