|
1.路由
1.1路由的作用
在传统的Web应用中个,每个URL对应网站中的一个页面;但在SPA(单页面应用中),由于只有一个页面,如果要实现不同URL在相同页面显示不同的路由,就需要根据URL来跟换Web组件,这需要额外的路由技术来实现。
例如以下三个页面,头部和底部都是相同的,而中间需要根据URL的不同,显示不同的中间组件,这时就需要路由。
1.2使用CLI3创建带路由功能的Vue2项目(案例)
(1)创建vue项目- vue create funnyshop‐vue2
复制代码 (2)选择手动设置特性(Manually select features)
(3)添加路由特性选项
(4)使用历史模式路由等特性项目特性
1.3 路由使用入门
1.3.1 项目路由规划
根据功能结构,我们可以把手机微商界面分割为若干个子组件。
具体子组件功能如下所示
组件名称
| 功能描述
| HeaderPart
| 网页头部的导航和搜索框
| FooterPart
| 页面底部的导航
| ProductList
| 产品列表
| Login
| 登录
| Cart
| 购物车
| ProductDetail
| 产品详情
| (1)在index.html页面中导入全局样式(可选)- <!DOCTYPE HTML>
- <html lang="en">
- <head>
- <meta charset="UTF‐8">
- <title>Document</title>
- <meta name="viewport" content="width=device‐width, initial‐scale=1.0, maximum‐scale=1.0, minimum‐scale=1.0, user‐scalable=no"
- <link rel="stylesheet" href="<%= BASE_URL %>css/base.css" rel="external nofollow" >
- <link rel="stylesheet" href="<%= BASE_URL %>css/page.css" rel="external nofollow" >
- </head>
- <body>
- <div id="app"></div>
- </body>
- </html>
复制代码 (2)项目根组件App.vue
在项目根组件中导入公共子组件(headerpart、footerpart)和根据路由加载的部分(routerview)- <template>
- <div class="pageWrapper">
- <header‐part />
- <div class="pageBreak"></div>
- <router‐view></router‐view>
- <div class="pageBreak"></div>
- <footer‐part />
- </div>
- </template>
- <script>
- import HeaderPart from './components/HeaderPart.vue'
- import FooterPart from './components/FooterPart.vue'
- export default {
- name:"app",
- components:{HeaderPart, FooterPart}
- }
- </script>
复制代码 其中不是我们定义的组件,而是vue的路由组件,只是一个占位符,用于显示不同url下所 需要加载的变化部分。
1.3.2 路由映射定义
带router的vue2项目创建后,src目录下会多出一个名为“router.js”的文件,该文件用于定义路由规则, 也就是不同的URL路径下所要加载的Vue子组件对应关系和参数传递规则。- import Vue from 'vue'
- import Router from 'vue‐router'
- import ProductList from './components/ProductList.vue'
- import Login from './components/Login.vue'
- import ProductDetail from './components/ProductDetail.vue'
- import Cart from './components/Cart.vue'
- Vue.use(Router)
- export default new Router({
- mode: 'history',
- base: process.env.BASE_URL,
- routes: [
- {
- path: '/',
- name: 'home',
- component: ProductList
- },
- {
- path: '/product‐list',
- name: 'product‐list',
- component: ProductList
- },
- {
- path:'/login',
- name:'login',
- component: Login
- },
- {
- path:'/product/:id',
- name:'product',
- component: ProductDetail
- },
- {
- path:'/cart',
- name:'cart',
- component: Cart
- },
- ]
- })
复制代码 routes配置中的每一项代表一条路由规则。
path是URL路径,可以定义路径参数(如“/product/:id”中的id);name是路由名称,用于引用; component指定加载的组件名称。
完成组件划分(*.vue)和路由映射(router.js)后,应用就可以根据路由规则显示不同的页面内容了。
1.3.3 通过路由连接(替代<a>)切换页面内容
传统的超链接<a href="...">会使页面发生同步跳转,在SPA应用中只有一张页面,内容的切换全部是异 步方式的。
(1)通过<router-link> 组件实现“跳转”
routerlink是一个路由组件,可以理解为异步的跳转连接标签(<a>)
routerlink的to属性可以设置切换的URL。to后面可以设置“静态的URL”或者绑定“一个路由项对象”,例 如下面的两个示例,前者设置URL,后者绑定一个定义了的路由对象。- <router‐link to="/login">登录</router‐link>
- <router‐link :to="{name:'cart'}">购物车</router‐link>。
复制代码 (2)通过推送路由变更$router.push(),从而实现“跳转”
配置好路由的项目中,我们可以在任意Vue组件内部,通过this.$router访问路由对象,通过 $router.push()方法,我们可以向路由推送跳转,实现组件的切换。- this.$router.push({name:"product‐list", query:{"name":val}});
复制代码 1.3.4 路由参数的获取
(1)路径参数与获取 我们在路由映射中(router.js)定义了以下一项:- { path:'/product/:id', name:'product', component: ProductDetail }
复制代码 也就是在跳转到ProductDetail组件时,我们会传入名为id的路径参数。
例如,在产品列表中有以下路由连接,点击后实际的URL可能为 “/product/5”,其中5是id参数。- <router‐link :to="{name:'product',params:{id:item.id}}">产品1连接</router‐link>
复制代码 这时,我们可以在目标组件ProductDetail中,通过 “$route.params.参数名” 获取到路径参数值:- let id = this.$route.params.id;
复制代码 (2)查询字符串参数的获取
路径参数是URL路径的一部分,通常只能用于传递必要参数(一定要提供的参数),对于可选参数就应 该使用查询字符串的方式来传递,例如:“search?name=abc&page=101”。
对于查询字符串参数,我们可以通过以下方式传递。- searchByProductName(e){
- var val = e.target.value;
- this.$router.push({name:"product‐list", query:{"name":val}});
- }
复制代码 上述路由推送会产生类似这样的URL:“productlist?name=xxxx” 这时,我们可以在目标组件ProducList中,通过“$router.query.参数名”获取查询字符串参数值。- let searchName = this.$route.query.name
复制代码 2 异步请求
2.1 后端RESTful Web服务和代理
(1)后端RESTful Web服务
SPA一般都采用前后端分离的开发方式。后端可以使用任何的服务器端Web技术,诸如JavaEE、 PHP、Node.js、Python等等,后端提供基于RESTful风格的Web服务,接收前端请求并返回JSON格式 的数据。
这里使用基于Spring Boot的MVC技术提供后端服务,具体细节略去,仅在这里描述所提供的服务接 口。
URL
| 功能
| http://localhost:9090/api/products/latest
| 获取最新的4种产品,返回JSON格式数据
| http://localhost:9090/api/products/1
| 获取id=1的商品明细信息
| http://localhost:9090/api/products?name=青瓷
| 模糊查询名称中包含“青瓷”的产品信息,返回
JSON格式数据
| 具体请求效果如下图所示。
(2)服务的代理
作为前后端分离的项目,后端和前端往往不是运行在同一个服务器中的。例如上述开发中,后端的 JavaEE服务是运行在Tomcat服务器(Spring Boot内嵌的容器)中的,而前端则是使用Node.js提供的测 试服务器。前者域名为“localhost:9090”,而后者是“localhost:3000”。这时,如果前端通过AJAX技术请 求后端数据,就会遇到JavaScript请求不能跨域执行的问题而无法请求。要解决这个问题,要么就需要 使用jsonp协议(跨域JSON协议),要么就要把前后端两个服务器通过代理服务器代理到同一个域名之 下。在实际部署中,我们可以通过Nginx等静态资源服务器实现代理,而在开发中Vue项目可以直接配置 后端代理,把lcoalhost:9090的域名请求代理到localhost:3000域名之下。
在项目根目录下添加 “vue.config.js” 文件,这时vue项目的配置文件,在其中可以设置开发服务器的端 口 “port” 和后端Web服务的代理“proxy”。- module.exports = {
- devServer: {
- port: 3000,
- proxy: {
- '/api': {
- target: 'http://localhost:9090', // target host
- },
- }
- }
- };
复制代码 如上所示,当我们请求 “localhost:3000/api/xxx” 时,请求被代理到了 “http://localhost:9090/api/xxx”, 这样前后端就不存在跨域问题了。
2.2 使用 axois 组件请求后端数据
(1)Promise与fetch API
传统的静态网页是通过XMLHttpRequest对象实现对后端数据的异步请求的(例如jQuery的$.ajax),请 求成功后需要执行回调函数。
这种传统的回调在复杂的使用环境中往往会一个接一个的嵌套,让代码陷入难以维护的“Callback地 狱”。新一代的JavaScript(ES6),不再建议使用XMLHttpRequest,而是用一种叫Promise的方式组织 代码,让我们不用陷入到回调的连环套中,而是用平面的方式来处理所有回调。新一代的浏览器中都支 持一个名为fetch的API方法,可以实现Promise方式的请求。
(2)axios组件
fetch API虽然基于Promise已经很好用了,但fetch功能还是过于原始,在实际应用中我们可能还需要一 些拦截器等扩展模块。
为此 vue 的作者推荐我们使用一个名为 axios 的JavaScript扩展包来实现后台请 求功能。axios有良好的Promise和拦截器机制。
2.3 axios的使用
axios的详细使用请参考互联网 https://www.npmjs.com/package/axios,这里只是简单介绍。
(1)为Vue项目添加axios
在项目根目录中执行以下Node指令:(2)axios基本用法
Method
| Api
| Get
| axios.get(url).then(successCallback).catch(errorHandler)
| Post
| axios.post(url, data).then(successCallback).catch(errorHandler)
| Put
| axios.put(url, data).then(successCallback).catch(errorHandler)
| Delete
| axios.delete(url).then(successCallback).catch(errorHandler)
| (3)axios的拦截器
axios可以在(组件的)请求或相应处理的之前插入拦截器,统一处理异步请求中的公共问题。
例如我们可以在react程序入口“index.js”中添加如下代码,统一在请求发出前添加jwt请求头,或者在响 应出错时定位到页面。- import axios from 'axios';
- //请求前处理
- axios.interceptors.request.use(
- config => {
- const token = window.localStorage.getItem("jwt‐token");
- if(token)
- config.headers={'Authorization': 'Bearer '+token};
- return config;
- },
- error=>{
- return Promise.reject(error);
- }
- );
- //响应前处理
- axios.interceptors.response.use(
- response => {
- return response;
- },
- error => {
- const httpCode = error.response.status;
- if(httpCode>=400 && httpCode<600){
- window.location.href="/error" rel="external nofollow" ;
- }
- return Promise.reject(error);
- }
- );
复制代码 2.4 在项目中实现请求
下面演示了ProductList组件中如何向后端请求商品信息。- <template>
- <div class="contentWrapper">
- <h4 class="contentTitle">新品上架:</h4>
- <div class="productListWrapper">
- <div class="productWrapper" v‐for="(item,i) in products" :key="i">
- <router‐link :to="{name:'product',params:{id:item.id}}">
- <img :src="'images/content/'+item.id+'‐1.jpg'" alt=""/>
- </router‐link>
- <div class="productInfoWrapper">
- <span class="productTitle">{{item.name}}</span>
- <a class="purchaseButton">¥{{item.unitPrice}} 购买</a>
- </div>
- </div>
- </div>
- </div>
- </template>
-
- <script>
- export default {
- name: 'product‐list',
- data(){
- return {
- products:[]
- };
- },
- mounted(){
- this.fetchData();
- },
- methods:{
- fetchData(){
- if(this.$route.query.name){
- this.axios.get("/api/products?name="+this.$route.query.name).then(res=>this
- }else{
- this.axios.get("/api/products/latest").then(res=>this.products=res.data);
- }
- }
- }
- }
- </script>
复制代码 总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
来源:https://www.jb51.net/javascript/323498joc.htm
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|