第07课:基础功能演练——路由与交互

第07课:基础功能演练——路由与交互

当掌握了前几篇文章的内容,你已经可以写出各种独立的案例了,但是都仅限于一个个独立的静态页面。而本文所讲述的内容,就是让大家能将一个个页面链接起来成为一个项目,并且与后台进行交互,这样你就可以拥有一个完整的项目案例了。

路由

路由这一词语相比大家都不陌生,但是前端工作中的路由有的人可能不是很清楚,先给大家介绍下前端路由。

用户都是通过地址来访问我们的项目,如:http://192.168.0.1:8080/#/index 或者 http://gitbook.cn/gitchat/columns。

跟在你 IP 或者网址后面的部分,决定了你访问到的是哪个页面,展示哪些内容。

在之前的工作中,你可能通过 a 标签来进行页面的跳转来控制用户访问到的内容。

在 Vue.js 中,我们将通过路由来对页面进行控制,不再使用你的 a 标签进行直接跳转,虽然最后也会被渲染成为一个 a 标签。

注意:路由更多用在 SPA 中,也就是单页应用上。在单页应用中,我们整个页面都是在同一个网页中,所以需要使用路由来进行页面上的跳转,而不是使用 a 标签。

如何使用路由

在 Vue.js 中,路由功能通过 vue-router 来完成,vue-router 是一个独立的 JavaScript,需要安装或者引入。

安装方式
npm install vue-router
引入方式
<script src="js/vue-router.js"></script>

使用路由我们会定义一个路由列表。

//path指的是路径名,也就是你访问使用的路径
//component指的是模版,当你访问前面路径的时候展示的对应模版

var router = new VueRouter({
  routes: [
    { path: '/user', 
      name: 'user',
      component: User
      },
    { path: '/login',
      name: 'login',
      component: Login
      },
    { path: '/', 
      name: 'index',
      component: Index
      },

  ]
})

然后我们在页面中进行使用。

//这样就可以前端登录模块
<router-link to="/login">TO login</router-link>
vue-router 的实例

用 Vue.js + vue-router 创建单页应用,是非常简单的。使用 Vue.js,我们已经可以通过组合组件来组成应用程序,当你要把 vue-router 添加进来,我们需要做的是,将组件(components)映射到路由(routes),然后告诉 vue-router 在哪里渲染它们。下面是个基本的例子。

<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>

<div id="app">
  <h1>Hello App!</h1>
  <p>
    <!-- 使用 router-link 组件来导航. -->
    <!-- 通过传入 `to` 属性指定链接. -->
    <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
    <router-link to="/foo">Go to Foo</router-link>
    <router-link to="/bar">Go to Bar</router-link>
  </p>
  <!-- 路由出口 -->
  <!-- 路由匹配到的组件将渲染在这里 -->
  <router-view></router-view>
</div>

JavaScript
// 0. 如果使用模块化机制编程,導入 Vue.js 和VueRouter,要调用 Vue.use(VueRouter)

// 1. 定义(路由)组件。
// 可以从其他文件 import 进来
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }

// 2. 定义路由
// 每个路由应该映射一个组件。 其中"component" 可以是
// 通过 Vue.extend() 创建的组件构造器,
// 或者,只是一个组件配置对象。
// 我们晚点再讨论嵌套路由。
const routes = [
  { path: '/foo', component: Foo },
  { path: '/bar', component: Bar }
]

// 3. 创建 router 实例,然后传 `routes` 配置
// 你还可以传别的配置参数, 不过先这么简单着吧。
const router = new VueRouter({
  routes // (缩写)相当于 routes: routes
})

// 4. 创建和挂载根实例。
// 记得要通过 router 配置参数注入路由,
// 从而让整个应用都有路由功能
const app = new Vue({
  router
}).$mount('#app')

router-link 的使用方式跟 a 标签相似,a 标签通过 href 来决定去那里,router-link 通过 to 来决定去那里,上面这种通过 router-link 标签来实现的方式叫做声明式,除了这种方式我们还有另外的编程式来完成,此时会用到 router.push()、router.replace()、router.go(n)三个方法。下面分别做介绍。

router.push(),该方法的参数可以是一个字符串路径,或者一个描述地址的对象,可参见下面代码示例。

// 字符串
router.push('/Index')

// 对象
router.push({ path: '/Index' })

// 命名的路由
router.push({ name: 'Index', params: { userId: 123 }})

// 带查询参数,变成 /login?username=username
router.push({ path: 'login', query: { username: 'username' }})

router.replace(),跟 router.push 很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样——替换掉当前的 history 记录。

也就是说,你通过 router.replace() 前往到某个页面,当你点击返回的时候,返回的不是你来的那个页面,而是你还在那个页面之前的页面。因为 router.replace() 在记录中直接替换了原有的记录。

这个方法在router-link中也可以使用,代码如下。

<router-link :to="..." replace>

router.go(n),这个方法的参数是一个整数,意思是在 history 记录中向前或后退多少步,类似 window.history.go(n),代码如下。

// 在浏览器记录中前进一步,等同于 history.forward()

router.go(1)
// 后退一步记录,等同于 history.back()

router.go(-1)
// 前进 3 步记录

router.go(3)
// 如果 history 记录不够用,那就会失败

router.go(-100)
router.go(100)

这三者功能就是来源于 window.history.pushState、 window.history.replaceState 和 window.history.go。

我们在实际工作中,往往会遇见这样一些情况,我点击某个跳转按钮的时候会根据不同的情况进行不同的跳转。在这样的情况下,我通常喜欢在按钮上绑定一个事件,在事件中进行判断,根据不同的判断然后使用 router.push() 等进行跳转,代码如下。

//点击个人中心,根据是否登录的状态进行判断

goUserInfo:function(){
    if(this.isLogin==true){//如果已经登录就跳往用户中心
        router.push('/user')
    }else{//如果没有登录,就跳往登录页面
        router.push('/login')
    }
}

交互

交互,一个正常的页面,或多或少都会与后台进行交互,在没使用的 Vue.js 的时候,你或许使用原生 XMLHttpRequest,或许使用 Ajax,或许使用其他插件进行交互。

而在 Vue.js 中,我们通常使用两种方式进行交互,vue-resource 和 axios。

vue-resource

vue-resource 很小,在压缩以后只有12KB,服务端启用 gzip 压缩后只有 4.5KB 大小。它与 Vue.js 所兼容的浏览器版本也是一致的。

我们在使用 vue resource 时,需要先安装或者引入。

安装方式
npm install vue-resource
引入方式
<script src="js/vue-resource.js"></script>
vue-resource 的API

它的整体使用与 Ajax 相差不大,也有一些区别,在 vue-resource 中,我们通常直接采用 post 或者 get 进行请求,它一共提供了7种 API,请见下。

  • get(url, [options])
  • head(url, [options])
  • delete(url, [options])
  • jsonp(url, [options])
  • post(url, [body], [options])
  • put(url, [body], [options])
  • patch(url, [body], [options])

其中,url 为请求地址,options 中是一些配置。

options 中各个参数的解析,请见下表。

参数 类型 描述
url string 请求的URL
method string 请求的HTTP方法,例如:'GET', 'POST'或其他HTTP方法
body Object, FormData string request body
params Object 请求的URL参数对象
headers Object request header
timeout number 单位为毫秒的请求超时时间 (0 表示无超时时间)
before function(request) 请求发送前的处理函数,类似于jQuery的beforeSend函数
progress function(event) ProgressEvent回调处理函数
credentials boolean 表示跨域请求时是否需要使用凭证
emulateHTTP boolean 发送PUT, PATCH, DELETE请求时以HTTP POST的方式发送,并设置请求头的X-HTTP-Method-Override
emulateJSON boolean 将request body以application/x-www-form-urlencoded content type发送

请求用法请见下面代码。

//get方法
this.$http.get('/url', options).then(function(res){
  // 响应成功回调
  alert(res)
}, function(err){
  // 响应错误回调
  alert(err)
});

简单实例,如下。

var app = new Vue({
  el: '#app',
  data: {
    url:'http://192.168.0.1:8080/api/login',
    userName:'',//用户名,通过v-model绑定到用户名输入框
    password:''//用户密码,通过v-model绑定到密码输入框
  },
  methods: {
   login:function(){
   var data={
       userName:this.userName,
       password:this.password
   }
    this.$http.post(url, data).then(function(res){
         // 响应成功回调
         if(res.data.success==true){//后台返回成功
             alert('登录成功')
         }else{//后台返回失败
             alert('登录失败')
         }
    }, function(err){//网络响应错误
      // 响应错误回调
      alert('网络错误')
    });
   }
  }
})

注意:很多时候有人会出现这样的情况,请求回来数据,结果发现对数据进行操作的时候会报错,XXX为 undefined ,对于这样的情况而言,大家需要验证,你请求回来的数据是什么格式,它的数据结构是怎么样的。很多时候会因为忽略这一问题而出现此类错误。

axios

Vue.js 更新到2.0之后,作者就宣告不再对 vue-resource 更新了,推荐使用 axios.js。

同样的,axios 在使用前,也需要进行安装或者直接引入使用。

安装方式
npm install axios
引入方式
<script src="js/axios.min.js"></script>
axios 的API

axios 为我们提供了八种 API,请见下。

  • axios.request(config)
  • axios.get(url[, config])
  • axios.delete(url[, config])
  • axios.head(url[, config])
  • axios.options(url[, config])
  • axios.post(url[, data[, config]])
  • axios.put(url[, data[, config]])
  • axios.patch(url[, data[, config]])

其中,url 是请求路径,data 是请求参数,config 中是一些请求配置。

以下列出了一些请求时的设置选项。只有 url 是必须的,如果没有指明 method 的话,默认的请求方法是 GET。

{
    //`url`是服务器链接,用来请求
    url:'/user',

    //`method`是发起请求时的请求方法
    method:`get`,

    //`baseURL`如果`url`不是绝对地址,那么将会加在其前面。
    //当axios使用相对地址时这个设置非常方便
    //在其实例中的方法
    baseURL:'http://some-domain.com/api/',

    //`transformRequest`允许请求的数据在传到服务器之前进行转化。
    //这个只适用于`PUT`,`GET`,`PATCH`方法。
    //数组中的最后一个函数必须返回一个字符串或者一个`ArrayBuffer`,或者`Stream`,`Buffer`实例,`ArrayBuffer`,`FormData`
    transformRequest:[function(data){
        //依自己的需求对请求数据进行处理
        return data;
    }],

    //`transformResponse`允许返回的数据传入then/catch之前进行处理
    transformResponse:[function(data){
        //依需要对数据进行处理
        return data;
    }],

    //`headers`是自定义的要被发送的头信息
    headers:{'X-Requested-with':'XMLHttpRequest'},

    //`params`是请求连接中的请求参数,必须是一个纯对象,或者URLSearchParams对象
    params:{
        ID:12345
    },

    //`paramsSerializer`是一个可选的函数,是用来序列化参数
    //例如:(https://ww.npmjs.com/package/qs,http://api.jquery.com/jquery.param/)
    paramsSerializer: function(params){
        return Qs.stringify(params,{arrayFormat:'brackets'})
    },

    //`data`是请求提需要设置的数据
    //只适用于应用的'PUT','POST','PATCH',请求方法
    //当没有设置`transformRequest`时,必须是以下其中之一的类型(不可重复?):
    //-string,plain object,ArrayBuffer,ArrayBufferView,URLSearchParams
    //-仅浏览器:FormData,File,Blob
    //-仅Node:Stream
    data:{
        firstName:'fred'
    },
    //`timeout`定义请求的时间,单位是毫秒。
    //如果请求的时间超过这个设定时间,请求将会停止。
    timeout:1000,

    //`withCredentials`表明是否跨网站访问协议,
    //应该使用证书
    withCredentials:false //默认值

    //`adapter`适配器,允许自定义处理请求,这会使测试更简单。
    //返回一个promise,并且提供验证返回(查看[response docs](#response-api))
    adapter:function(config){
        /*...*/
    },

    //`auth`表明HTTP基础的认证应该被使用,并且提供证书。
    //这个会设置一个`authorization` 头(header),并且覆盖你在header设置的Authorization头信息。
    auth:{
        username:'janedoe',
        password:'s00pers3cret'
    },

    //`responsetype`表明服务器返回的数据类型,这些类型的设置应该是
    //'arraybuffer','blob','document','json','text',stream'
    responsetype:'json',

    //`xsrfHeaderName` 是http头(header)的名字,并且该头携带xsrf的值
    xrsfHeadername:'X-XSRF-TOKEN',//默认值

    //`onUploadProgress`允许处理上传过程的事件
    onUploadProgress: function(progressEvent){
        //本地过程事件发生时想做的事
    },

    //`onDownloadProgress`允许处理下载过程的事件
    onDownloadProgress: function(progressEvent){
        //下载过程中想做的事
    },

    //`maxContentLength` 定义http返回内容的最大容量
    maxContentLength: 2000,

    //`validateStatus` 定义promise的resolve和reject。
    //http返回状态码,如果`validateStatus`返回true(或者设置成null/undefined),promise将会接受;其他的promise将会拒绝。
    validateStatus: function(status){
        return status >= 200 && stauts < 300;//默认
    },

    //`httpAgent` 和 `httpsAgent`当产生一个http或者https请求时分别定义一个自定义的代理,在nodejs中。
    //这个允许设置一些选选个,像是`keepAlive`--这个在默认中是没有开启的。
    httpAgent: new http.Agent({keepAlive:treu}),
    httpsAgent: new https.Agent({keepAlive:true}),

    //`proxy`定义服务器的主机名字和端口号。
    //`auth`表明HTTP基本认证应该跟`proxy`相连接,并且提供证书。
    //这个将设置一个'Proxy-Authorization'头(header),覆盖原先自定义的。
    proxy:{
        host:127.0.0.1,
        port:9000,
        auth:{
            username:'cdd',
            password:'123456'
        }
    },

    //`cancelTaken` 定义一个取消,能够用来取消请求
    //(查看 下面的Cancellation 的详细部分)
    cancelToken: new CancelToken(function(cancel){
    })
}

请求返回包含的内容,请见下面代码。

{
    //后台给你返回的内容
    data{},

    //服务器的http状态码
    status:200,


    //服务器返回的http状态信息
    statusText: 'ok',

    //服务器返回的头部信息
    headers:{},

    //axios的相关配置信息
    config:{}
}

简单实例,如下。

var app = new Vue({
  el: '#app',
  data: {
    url:'http://192.168.0.1:8080/api/login',
    userName:'',//用户名,通过v-model绑定到用户名输入框
    password:''//用户密码,通过v-model绑定到密码输入框
  },
  methods: {
   login:function(){
   var data={
       userName:this.userName,
       password:this.password
   }

    axios.post(url,data)
        .then(function(res){
         // 响应成功回调
         if(res.data.success==true){//后台返回成功
             alert('登录成功')
         }else{//后台返回失败
             alert('登录失败')
         }
        })
        .catch(function(err){//网络响应错误
          // 响应错误回调
          alert('网络错误')
        })

   }
  }
})

结语

当你使用 axios 或者 vue-resource 与后台进行交互的过程中,如果出现了什么问题,可以在读者圈进行留言,我会在看到之后回复你。也有人反馈独立的 JavaScript 文件没有地方下载,后续我会整理一份资源在读者圈发布。

上一篇
下一篇
目录