vue脚手架搭建

朱雀 2024-04-17 05:42 168阅读 0赞

vue2:脚手架搭建

简介

vue.js有著名的全家桶系列,包含了vue-router,vuex, vue-resource,再加上构建工具vue-cli,就是一个完整的vue项目的核心构成。

vue-cli这个构建工具大大降低了webpack的使用难度,支持热更新,有webpack-dev-server的支持,相当于启动了一个请求服务器,给你搭建了一个测试环境,只关注开发就OK。

步骤

1.安装vue-cli

① 使用npm(需要安装node环境)全局安装webpack,打开命令行工具输入:npm install webpack -g或者(npm install -g webpack),安装完成之后输入 webpack -v,如下图,如果出现相应的版本号,则说明安装成功。
在这里插入图片描述
② 全局安装vue-cli,在cmd中输入命令:

  1. npm install --global vue-cli

安装完成之后输入 vue -V(注意这里是大写的“V”),如下图,如果出现相应的版本号,则说明安装成功。
在这里插入图片描述
打开C:\Users\admin\AppData\Roaming\npm可以查看vue安装目录
打开node_modules也可以看到:vue-cli目录

2.用vue-cli来构建项目

① 我首先在D盘新建一个文件夹(dxl_vue)作为项目存放地,然后使用命令行cd进入到项目目录输入:

  1. vue init webpack vueTest

vueTest 是自定义的项目名称,命令执行之后,会在当前目录生成一个以该名称命名的项目文件夹。

输入命令后,会跳出几个选项让你回答:

Project name (baoge): ——-项目名称,直接回车,按照括号中默认名字(注意这里的名字不能有大写字母,如果有会报错Sorry, name can no longer contain capital letters),阮一峰老师博客为什么文件名要小写 ,可以参考一下。
Project description (A Vue.js project): ——项目描述,也可直接点击回车,使用默认名字
Author (): ——作者
接下来会让用户选择:
Runtime + Compiler: recommended for most users 运行加编译,既然已经说了推荐,就选它了
Runtime-only: about 6KB lighter min+gzip, but templates (or any Vue-specificHTML) are ONLY allowed in .vue files - render functions are required elsewhere 仅运行时,已经有推荐了就选择第一个了
Install vue-router? (Y/n) 是否安装vue-router,这是官方的路由,大多数情况下都使用,这里就输入“y”后回车即可。
Use ESLint to lint your code? (Y/n) 是否使用ESLint管理代码,ESLint是个代码风格管理工具,是用来统一代码风格的,一般项目中都会使用。
接下来也是选择题Pick an ESLint preset (Use arrow keys) 选择一个ESLint预设,编写vue项目时的代码风格,直接y回车
Setup unit tests with Karma + Mocha? (Y/n) 是否安装单元测试,我选择安装y回车
Setup e2e tests with Nightwatch(Y/n)? 是否安装e2e测试 ,我选择安装y回车
Should we run npm install for you after the project has been created? (recommended) (Use arrow keys)
默认是use npm就好

在这里插入图片描述
回答完毕后上图就开始构建项目了。

注意:如果构建初始项目报错:
在这里插入图片描述
然后按提示执行 yarn global add @vue/cli-init
由于我这里的yarn版本太旧了,所以报错,需要更新版本

  1. npm install yarn@latest -g

重新安装最新版,进入旧版目录删除yarn目录,可通过 命令: $ yarn global bin找到旧版的目录
安装完成后,如果需要配置环境变量记得把yarn的bin目录添加到系统path环境变量中
yarn -v查看版本,然后继续执行vue项目构建
在这里插入图片描述
② 配置完成后,可以看到目录下多出了一个项目文件夹vueTest,然后cd进入这个文件夹:
安装依赖:

  1. npm install

( 如果安装速度太慢。可以安装淘宝镜像,打开命令行工具,输入:

  1. npm install -g cnpm --registry=https://registry.npm.taobao.org

然后使用cnpm来安装 )
在这里插入图片描述

npm(cnpm) install :安装所有的模块,如果是安装具体的哪个个模块,在install 后面输入模块的名字即可。而只输入install就会按照项目的根目录下的package.json文件中依赖的模块安装(这个文件里面是不允许有任何注释的),每个使用npm管理的项目都有这个文件,是npm操作的入口文件。因为是初始项目,还没有任何模块,所以我用npm install 安装所有的模块。安装完成后,目录中会多出来一个node_modules文件夹,这里放的就是所有依赖的模块。

解释下每个文件夹代表的意思(仔细看一下这张图):
在这里插入图片描述
如果报错:
先解决错误,比如
在这里插入图片描述
原因一般是下载源被封了,我们连接淘宝的下载源下载:

npm install chromedriver —chromedriver_cdnurl=http://cdn.npm.taobao.org/dist/chromedriver

3.启动项目
  1. npm run dev

如果浏览器打开之后,没有加载出页面,有可能是本地的 8080 端口被占用,需要修改一下配置文件 config里的index.js
在这里插入图片描述
如果本地调试项目时,建议将build 里的assetsPublicPath的路径前缀修改为 ’ ./ ‘(开始是 ’ / ‘),因为打包之后,外部引入 js 和 css 文件时,如果路径以 ’ / ’ 开头,在本地是无法找到对应文件的(服务器上没问题)。所以如果需要在本地打开打包后的文件,就得修改文件路径。
我的端口没有被占用,直接成功(服务启动成功后浏览器会默认打开一个“欢迎页面”):
在这里插入图片描述

注意:在进行vue页面调试时,一定要去谷歌商店下载一个vue-tool扩展程序。
谷歌安装扩展可以查看本人的另外一篇博客
在这里插入图片描述

4.vue-cli的webpack配置分析

从package.json可以看到开发和生产环境的入口。
在这里插入图片描述
可以看到dev中的设置,build/webpack.dev.conf.js,该文件是开发环境中webpack的配置入口。
在webpack.dev.conf.js中出现webpack.base.conf.js,这个文件是开发环境和生产环境,甚至测试环境,这些环境的公共webpack配置。可以说,这个文件相当重要。
还有config/index.js 、build/utils.js 、build/build.js等

5.打包上线

注意,自己的项目文件都需要放到 src 文件夹下。
在项目开发完成之后,可以输入 npm run build 来进行打包工作。

  1. npm run build

tips:

  1. 1.npm 开启了npm run dev以后怎么退出或关闭?
  2. ctrl+c
  3. 2.--save-dev
  4. 自动把模块和版本号添加到模块配置文件package.json中的依赖里devdependencies部分
  5. 3. --save-dev --save 的区别
  6. --save 安装包信息将加入到dependencies(生产阶段的依赖)
  7. --save-dev 安装包信息将加入到devDependencies(开发阶段的依赖),所以开发阶段一般使用它

打包完成后,会生成 dist 文件夹,如果已经修改了文件路径,可以直接打开本地文件查看。
项目上线时,只需要将 dist 文件夹放到服务器就行了。

Vue2:vue-router(路由)

简介

由于Vue在开发时对路由支持的不足,于是官方补充了vue-router插件。vue的单页面应用是基于路由和组件的,路由用于设定访问路径,并将路径和组件映射起来。传统的页面应用,是用一些超链接来实现页面切换和跳转的。在vue-router单页面应用中,则是路径之间的切换,实际上就是组件的切换。路由就是SPA(单页应用)的路径管理器。再通俗的说,vue-router就是我们WebApp的链接路径管理系统。
  有的小伙伴会有疑虑,为什么我们不能像原来一样直接用a标签编写链接呢?因为我们一般用Vue做的都是单页应用,只有一个主页面index.html,所以你写的标签是不起作用的,要使用vue-router来进行管理。

一、安装

如果你用vue-cli脚手架来搭建项目,配置过程会选择是否用到路由,如果选择y,后面下载依赖会自动下载vue-router。
vue-router手动安装:

  1. npm install vue-router

二、创建组件

如果在一个模块化工程中使用它,必须要通过 Vue.use() 明确地安装路由功能,用vue-cli生产了我们的项目结构,src文件目录下会有一个router文件夹,此处就是编写路由组件的地方。在src/router/index.js,这个文件就是路由的核心文件:

在这里插入图片描述

在这里插入图片描述

  1. import Vue from 'vue' //引入Vue
  2. import Router from 'vue-router' //引入vue-router
  3. import Hello from '@/components/Hello' //引入根目录下的Hello.vue组件
  4. Vue.use(Router) //Vue全局使用Router
  5. export default new Router({
  6. routes: [ //配置路由,这里是个数组
  7. { //每一个链接都是一个对象
  8. path: '/', //链接路径
  9. name: 'Hello', //路由名称,
  10. component: Hello //对应的组件模板
  11. },{
  12. path:'/hi',
  13. component:Hi,
  14. children:[ //子路由,嵌套路由 (此处偷个懒,免得单独再列一点)
  15. {path:'/',component:Hi},
  16. {path:'hi1',component:Hi1},
  17. {path:'hi2',component:Hi2},
  18. ]
  19. }
  20. ]
  21. })

注意:被选中的router-link将自动添加一个class属性值.router-link-active。

  1. <router-link to="/">[text]</router-link>

to:导航路径,要填写的是你在router/index.js文件里配置的path值,如果要导航到默认首页,只需要写成 to=”/“ ,
[text] :就是我们要显示给用户的导航名称。

2.router-view 用于渲染匹配到的组件。

①.可以给router-view组件设置transition过渡(Vue2.0 Transition常见用法全解惑)。

  1. <transition name="fade">
  2. <router-view ></router-view>
  3. </transition>

css过渡类名:
组件过渡过程中,会有四个CSS类名进行切换,这四个类名与transition的name属性有关,比如name=“fade”,会有如下四个CSS类名:

fade-enter:进入过渡的开始状态,元素被插入时生效,只应用一帧后立刻删除。
fade-enter-active:进入过渡的结束状态,元素被插入时就生效,在过渡过程完成后移除。
fade-leave:离开过渡的开始状态,元素被删除时触发,只应用一帧后立刻删除。
fade-leave-active:离开过渡的结束状态,元素被删除时生效,离开过渡完成后被删除。

从上面四个类名可以看出,fade-enter-active和fade-leave-active在整个进入或离开过程中都有效,所以CSS的transition属性在这两个类下进行设置。

过渡模式mode:

in-out(mode默认in-out模式):新元素先进入过渡,完成之后当前元素过渡离开。
out-in:当前元素先进行过渡离开,离开完成后新元素过渡进入。

②.还可以配合使用,keep-alive可以缓存数据,这样不至于重新渲染路由组件的时候,之前那个路由组件的数据被清除了。比如对当前的路由组件a进行了一些DOM操作之后,点击进入另一个路由组件b,再回到路由组件a的时候之前的DOM操作还保存在,如果不加keep-alive再回到路由组件a时,之前的DOM操作就没有了,得重新进行。如果你的应用里有一个购物车组件,就需要用到keep-alive。

  1. <transition>
  2. <keep-alive>
  3. <router-view></router-view>
  4. </keep-alive>
  5. </transition>

四、动态路由匹配

我们经常需要把某种模式匹配到的所有路由,全都映射到同个组件。
调用router的map方法映射路由,每条路由以key-value的形式存在,key是路径,value是组件。例如:’/home’是一条路由的key,它表示路径;{component: Home}则表示该条路由映射的组件:

  1. router.map({
  2. '/home': { component: Home },
  3. '/about': { component: About }
  4. })

例如,我们有一个 User 组件,对于所有 ID 各不相同的用户,都要使用这个组件来渲染。那么,我们可以在 vue-router 的路由路径中使用『动态路径参数』来达到这个效果。

  1. const User = {
  2. template: '<div>User</div>'
  3. }
  4. const router = new VueRouter({
  5. routes: [
  6. // 动态路径参数 以冒号开头
  7. { path: '/user/:id', component: User }
  8. ]
  9. })

例如: /user/foo 和 /user/bar 都将映射到相同的路由。
一个『路径参数』使用冒号 : 标记。当匹配到一个路由时,参数值会被设置到this.$route.params,可以在每个组件内使用。
你可以在一个路由中设置多段『路径参数』,对应的值都会设置到 $route.params 中。例如:

在这里插入图片描述

五、vue-router参数传递

1.用name传值(不推荐)
在这里插入图片描述

2.通过 标签中的to传参

  1. <router-link :to="{name:‘dxl’,params:{key:value}}">hello</router-link>

name:就是我们在路由配置文件中起的name值。
另:命名路由就是用一个名称来标识一个路由,在定义路由的时候设置一个name属性即可。在router-link中也可以用路由的名字来链接到一个路由。

params:就是我们要传的参数,它也是对象形势,在对象里可以传递多个值。
最后用$route.params.username进行接收.

3.用url传参
上面第五点也有提到。 :冒号的形式传递参数
(1).在router路由配置文件里以冒号的形式设置参数

  1. {
  2. path:'/params/:newsId/:userName,
  3. component:Params
  4. }

(2).组件形式,在src/components目录下建立我们params.vue组件。
我们在页面里输出了url传递的参数。

  1. <template>
  2. <div>
  3. <h2>{
  4. { msg }}</h2>
  5. <p>新闻ID:{
  6. { $route.params.newsId}}</p>
  7. <p>用户名:{
  8. { $route.params.userName}}</p>
  9. </div>
  10. </template>
  11. <script>
  12. export default {
  13. name: 'params',
  14. data () {
  15. return {
  16. msg: 'params page'
  17. }
  18. }
  19. }
  20. </script>

(3).标签path路径中传值

  1. <router-link to="/params/888/dxl shuai>params</router-link>

(4).正则表达式在URL传值中的应用
希望我们传递的新闻ID只能是数字的形式,这时候我们就需要在传递时有个基本的类型判断,

  1. path:'/params/:newsId(\\d+)/:userName'

六.响应路由参数的变化

当使用路由参数时,例如从 /user/foo 导航到 /user/bar,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。
复用组件时,想对路由参数的变化作出响应的话:
(1). watch(监测变化) $route 对象:

  1. const User = {
  2. template: '...',
  3. watch: {
  4. '$route' (to, from) {
  5. // 对路由变化作出响应...
  6. }
  7. }
  8. }

(2).beforeRouteUpdate 导航守卫
如果目的地和当前路由相同,只有参数发生了改变 (比如从一个用户资料到另一个 /users/1 -> /users/2),你需要使用 beforeRouteUpdate来响应这个变化 (比如抓取用户信息)。

  1. const User = {
  2. template: '...',
  3. beforeRouteUpdate (to, from, next) {
  4. // react to route changes...
  5. // don't forget to call next()
  6. }
  7. }

七、实现不同路由不同页面标题

// 定义路由的时候如下定义,name也可为中文

  1. const routes = [
  2. { path: '/goods', component: goods, name: 'goods' },
  3. { path: '/orders', component: orders, name: 'orders' },
  4. { path: '/seller', component: seller, name: 'seller' }
  5. ];

// 创建路由实例

  1. const router = new VueRouter({
  2. routes: routes
  3. })

// 关键在这里,设置afterEach钩子函数

  1. router.afterEach((to, from, next) => {
  2. document.title = to.name;
  3. })

八、重定向

刚进入应用都是进入到“/”这个路由的,如果想直接进入到“/goods”怎么办,有两种方法。一种是利用重定向,另一种是利用vue-router的导航式编程。
redirect基本重定向:

  1. const routes = [
  2. { path: '/', redirect: '/goods'}
  3. ]

重定向的目标也可以是一个命名的路由。

  1. const routes = [
  2. { path: '/', redirect: { name: 'goods' }}
  3. ]

重定向时也可以传递参数

  1. {
  2. path:'/',
  3. redirect:'/goods/:newsId(\\d+)/:userName'
  4. }

★.这里不得不提到alias别名的使用。
1.首先我们在路由配置文件里给路径起一个别名,dxl。

  1. {
  2. path: '/hi',
  3. component: Hi,
  4. alias:'/dxl'
  5. }

2.配置我们的,起过别名之后,可以直接使用标签里的to属性,进行重新定向。

  1. <router-link to="/dxl">jspang</router-link>

区别:

redirect:仔细观察URL,redirect是直接改变了url的值,把url变成了真实的path路径。
alias:URL路径没有别改变,这种情况更友好,让用户知道自己访问的路径,只是改变了中的内容。

★★★.注意一个大坑:
别名alias在path为’/‘中,是不起作用的。

  1. {
  2. path: '/',
  3. component: Hello,
  4. alias:'/home'
  5. }

九、编程式导航

1.router.push( )
想要导航到不同的 URL,则使用 router.push (在创建vue实例并挂载后调用)。router.push方法就是用来动态导航到不同的链接的,这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。
当你点击 时,这个方法会在内部调用,所以说,点击 等同于调用 router.push(…)。

注意:
如果提供了 path,params 会被忽略,而 query 并不属于这种情况。取而代之的是下面例子的做法,你需要提供路由的 name 或手写完整的带有参数的 path:

  1. const userId = 123
  2. router.push({ name: 'user', params: { userId }}) // -> /user/123
  3. router.push({ path: `/user/${userId}` }) // -> /user/123
  4. // 这里的 params 不生效
  5. router.push({ path: '/user', params: { userId }}) // -> /user

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

3.router.go(n)
这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)。
// 在浏览器记录中前进一步,等同于 history.forward()

  1. router.go(1)

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

  1. router.go(-1)

自定义一个goback()方法,并使用this.$router.go(-1),进行后退操作

  1. <script>
  2. export default {
  3. name: 'app',
  4. methods:{
  5. goback(){
  6. this.$router.go(-1);
  7. },
  8. goHome(){
  9. this.$router.push('/');
  10. }
  11. }
  12. }
  13. </script>

十、路由中的钩子

1.路由配置文件中的钩子函数:
在路由文件中我们只能写一个beforeEnter,就是在进入此路由配置时:

  1. {
  2. path:'/params/:newsId(\\d+)/:userName',
  3. component:Params,
  4. beforeEnter:(to,from,next)=>{
  5. console.log('我进入了params模板');
  6. console.log(to);
  7. console.log(from);
  8. next();
  9. },

三个参数:

  1. to:路由将要跳转的路径信息,信息是包含在对像里边的。
  2. from:路径跳转前的路径信息,也是一个对象的形式。
  3. next:路由的控制参数,常用的有next(true)和next(false)。

2.写在模板中的钩子函数:

  1. 写在模板中就可以有两个钩子函数可以使用。
  2. beforeRouteEnter:在路由进入前的钩子函数。
  3. beforeRouteLeave:在路由离开前的钩子函数。
  4. export default {
  5. name: 'params',
  6. data () {
  7. return {
  8. msg: 'params page'
  9. }
  10. },
  11. beforeRouteEnter:(to,from,next)=>{
  12. console.log("准备进入路由模板");
  13. next();
  14. },
  15. beforeRouteLeave: (to, from, next) => {
  16. console.log("准备离开路由模板");
  17. next();
  18. }
  19. }

★此处常用于数据获取。

导航完成之后获取:先完成导航,然后在接下来的组件生命周期钩子中获取数据。在数据获取期间显示『加载中』之类的指示。
当你使用这种方式时,我们会马上导航和渲染组件,然后在组件的 created 钩子中获取数据。这让我们有机会在数据获取期间展示一个 loading 状态,还可以在不同视图间展示不同的 loading 状态。
假设我们有一个 Post 组件,需要基于 $route.params.id 获取文章数据:

  1. <template>
  2. <div class="post">
  3. <div class="loading" v-if="loading">
  4. Loading...
  5. </div>
  6. <div v-if="error" class="error">
  7. {
  8. { error }}
  9. </div>
  10. <div v-if="post" class="content">
  11. <h2>{
  12. { post.title }}</h2>
  13. <p>{
  14. { post.body }}</p>
  15. </div>
  16. </div>
  17. </template>
  18. export default {
  19. data () {
  20. return {
  21. loading: false,
  22. post: null,
  23. error: null
  24. }
  25. },
  26. created () {
  27. // 组件创建完后获取数据,
  28. // 此时 data 已经被 observed 了
  29. this.fetchData()
  30. },
  31. watch: {
  32. // 如果路由有变化,会再次执行该方法
  33. '$route': 'fetchData'
  34. },
  35. methods: {
  36. fetchData () {
  37. this.error = this.post = null
  38. this.loading = true
  39. // replace getPost with your data fetching util / API wrapper
  40. getPost(this.$route.params.id, (err, post) => {
  41. this.loading = false
  42. if (err) {
  43. this.error = err.toString()
  44. } else {
  45. this.post = post
  46. }
  47. })
  48. }
  49. }
  50. }

导航完成之前获取:导航完成前,在路由进入的守卫中获取数据,在数据获取成功后再执行导航。
通过这种方式,我们在导航转入新的路由前获取数据。我们可以在接下来的组件的 beforeRouteEnter 守卫中获取数据,当数据获取成功后只调用 next 方法。

  1. export default {
  2. data () {
  3. return {
  4. post: null,
  5. error: null
  6. }
  7. },
  8. beforeRouteEnter (to, from, next) {
  9. getPost(to.params.id, (err, post) => {
  10. next(vm => vm.setData(err, post))
  11. })
  12. },
  13. // 路由改变前,组件就已经渲染完了
  14. // 逻辑稍稍不同
  15. beforeRouteUpdate (to, from, next) {
  16. this.post = null
  17. getPost(to.params.id, (err, post) => {
  18. this.setData(err, post)
  19. next()
  20. })
  21. },
  22. methods: {
  23. setData (err, post) {
  24. if (err) {
  25. this.error = err.toString()
  26. } else {
  27. this.post = post
  28. }
  29. }
  30. }
  31. }

十一、History 模式

vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。
如果不想要很丑的 hash,我们可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。

  1. const router = new VueRouter({
  2. mode: 'history',
  3. routes: [...]
  4. })

在学习过渡效果的时候,我们学了mode的设置,但是在路由的属性中还有一个mode。
mode的两个值:

histroy:当你使用 history 模式时,URL 就像正常的 url,http://www.dxl.com/user/id
不过这种模式要玩好,还需要后台配置支持。因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问 http://www.dxl.com/user/id就会返回 404,。所以要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。

这么做以后,你的服务器就不再返回 404 错误页面,因为对于所有路径都会返回 index.html 文件。为了避免这种情况,你应该在 Vue 应用里面覆盖所有的路由情况,然后在给出一个 404 页面。

  1. const router = new VueRouter({
  2. mode: 'history',
  3. routes: [
  4. { path: '*', component: Error}
  5. ]
  6. })

这里的path:’*‘就是找不到页面时的配置,component是我们新建的一个Error.vue的文件

hash:默认’hash’值,但是hash看起来就像无意义的字符排列,不太好看也不符合我们一般的网址浏览习惯。不配置时是这样的:http://localhost:8080/\#/users,多个\#号。

十二、路由组件传参

(这点是直接粘贴的vue官网上的教程,此处是重点要多看多体会!)
在组件中使用 $route 会使之与其对应路由形成高度耦合,从而使组件只能在某些特定的 URL 上使用,限制了其灵活性。
解耦前:
id不能直接拿出来使用

  1. const User = {
  2. template: '<div>User {
  3. { $route.params.id }}</div>'
  4. }
  5. const router = new VueRouter({
  6. routes: [
  7. { path: '/user/:id', component: User }
  8. ]
  9. })

使用 props 将组件和路由解耦:

  1. const User = {
  2. props: ['id'],
  3. template: '<div>User {
  4. { id }}</div>'
  5. }
  6. const router = new VueRouter({
  7. routes: [
  8. { path: '/user/:id', component: User, props: true },
  9. // 对于包含命名视图的路由,你必须分别为每个命名视图添加 `props` 选项:
  10. {
  11. path: '/user/:id',
  12. components: { default: User, sidebar: Sidebar },
  13. props: { default: true, sidebar: false }
  14. }
  15. ]
  16. })

这样你便可以在任何地方使用该组件,使得该组件更易于重用和测试。
1.布尔模式
如果 props 被设置为 true,route.params 将会被设置为组件属性。
2.对象模式
如果 props 是一个对象,它会被按原样设置为组件属性。当 props 是静态的时候有用。

  1. const router = new VueRouter({
  2. routes: [
  3. { path: '/promotion/from-newsletter', component: Promotion, props: { newsletterPopup: false } }
  4. ]
  5. })

3.函数模式
你可以创建一个函数返回 props。这样你便可以将参数转换成另一种类型,将静态值与基于路由的值结合等等。

  1. const router = new VueRouter({
  2. routes: [
  3. { path: '/search', component: SearchUser, props: (route) => ({ query: route.query.q }) }
  4. ]
  5. })

/search?q=vue会将{query: ‘vue’}作为属性传递给 SearchUser 组件。
请尽可能保持 props 函数为无状态的,因为它只会在路由发生变化时起作用。如果你需要状态来定义 props,请使用包装组件,这样 Vue 才可以对状态变化做出反应。

  1. function dynamicPropsFn (route) {
  2. const now = new Date()
  3. return {
  4. name: (now.getFullYear() + parseInt(route.params.years)) + '!'
  5. }
  6. }
  7. const router = new VueRouter({
  8. mode: 'history',
  9. base: __dirname,
  10. routes: [
  11. { path: '/', component: Hello }, // No props, no nothing
  12. { path: '/hello/:name', component: Hello, props: true }, // Pass route.params to props
  13. { path: '/static', component: Hello, props: { name: 'world' }}, // static values
  14. { path: '/dynamic/:years', component: Hello, props: dynamicPropsFn }, // custom logic for mapping between route and props
  15. { path: '/attrs', component: Hello, props: { name: 'attrs' }}
  16. ]
  17. })

vue-resource(不推荐)——axios(推荐)

vue-resource早已不再更新!推荐用axios!!
  vue-resource是Vue.js的一款插件,它可以通过XMLHttpRequest或JSONP发起请求并处理响应。也就是说,Ajax能做的事情,vue-resource插件一样也能做到,而且vue-resource的API更为简洁。划重点,vue-resource还提供了非常有用的inteceptor(拦截器)功能(经常使用),使用inteceptor可以在请求发送前和发送请求后做一些处理,比如使用inteceptor在ajax请求时显示loading界面,或者在请求发送前在headers中设置token,加入token验证,拦截器在axios中详细介绍。

一、简单介绍vue-resource用法

1.引入
  1. import Vue from 'vue'
  2. import VueResource from 'vue-resource'
  3. Vue.use(VueResource)
2.使用

引入vue-resource后,可以基于全局的Vue对象使用http,也可以基于某个Vue实例使用http。

  1. 在一个Vue实例内使用$http
  2. this.$http.get('/Url', [options]).then((response) => {
  3. // 响应成功回调
  4. }, (response) => {
  5. // 响应错误回调
  6. });
3.跨域

解决vue-resource post请求跨域问题:
vue提供了一个简单的解决方法,就是 Vue.http.options.emulateJSON = true 其实等同于在headers中添加 ‘Content-Type’: ‘application/x-www-form-urlencoded’。
注意:$http请求和jquery中使用ajax还是有点区别,这里的post的data默认不是以form data的形式,而是request payload。所以你们别忘了将emulateJSON 属性设置为true,即可解决这个问题。

  1. Vue.http.options.emulateJSON = true

form data和request payload的区别:

*form date
get请求,是将请求参数以&方法,拼接在url后面,如:http://www.dxl.com?name=dxl&password=8888;
真正可以明显看出区分的是在post请求上,
post请求时,头文件 中Content-Type 是默认值 application/x-www-form-urlencoded,参数是放在 form date中的。
request payload
post请求时,头文件 中Content-Type 是默认值 application/json;charset=UTF-8,参数是放在 request payload 中的。

  1. JSONP请求:
  2. getJsonp: function() {
  3. this.$http.jsonp(this.apiUrl).then(function(response){
  4. this.$set('gridData', response.data)
  5. })
  6. }
4.resource服务

vue-resource提供了另外一种方式访问HTTP——resource服务
resource对象也有两种访问方式:

  1. 全局访问:Vue.resource
  2. 实例访问:this.$resource

(1)get请求

  1. getCustomers: function() {
  2. var resource = this.$resource(this.apiUrl)
  3. vm = this
  4. resource.get()
  5. .then((response) => {
  6. vm.$set('gridData', response.data)
  7. })
  8. .catch(function(response) {
  9. console.log(response)
  10. })

}

(2)post请求
使用save方法发送POST请求。

  1. createCustomer: function() {
  2. var resource = this.$resource(this.apiUrl)
  3. vm = this
  4. resource.save(vm.apiUrl, vm.item)
  5. .then((response) => {
  6. vm.$set('item', {})
  7. vm.getCustomers()
  8. })
  9. this.show = false
  10. }

(3)使用update方法发送PUT请求,使用remove或delete方法发送DELETE请求

5.拦截器interceptors
  1. Vue.http.interceptors.push((request, next) => {
  2. // ...
  3. // 请求发送前的处理逻辑
  4. // ...
  5. next((response) => {
  6. // ...
  7. // 请求发送后的处理逻辑
  8. // ...
  9. // 根据请求的状态,response参数会返回给successCallback或errorCallback
  10. return response
  11. })
  12. })

二、axios

1.介绍

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。
看这个吧,传送门→https://www.kancloud.cn/yunye/axios/234845
axios支持IE8。

它可以:

  1. 从浏览器中创建 XMLHttpRequests
  2. node.js 创建 http请求
  3. 支持 Promise API
  4. 拦截请求和响应
  5. 转换请求数据和响应数据
  6. 取消请求
  7. 自动转换 JSON 数据
  8. 客户端支持防御 XSRF

(1)get请求

  1. axios.get('/user', {
  2. params: {
  3. ID: 1111
  4. }
  5. })
  6. .then(function (response) {
  7. console.log(response);
  8. })
  9. .catch(function (error) {
  10. console.log(error);
  11. });

// 还可以这么写,es7新特性async/await

  1. async function getUser() {
  2. try {
  3. const response = await axios.get('/user?ID=1111');
  4. console.log(response);
  5. } catch (error) {
  6. console.error(error);
  7. }
  8. }

*async用于声明一个函数是异步的,而await是“等待”的意思,就是用于等待异步完成。
await只能在async函数中使用。
await可以让js进行等待,直到一个promise执行并返回它的结果,js才会继续往下执行。
async/await 面试经常问到哦,百度查一下,划重点

(2)post请求

  1. axios.post('/user', {
  2. firstName: 'xiliDong',
  3. lastName: 'dongxili'
  4. })
  5. .then(function (response) {
  6. console.log(response);
  7. })
  8. .catch(function (error) {
  9. console.log(error);
  10. });

//或者这样写

  1. axios({
  2. method: 'post',
  3. url: '/user',
  4. data: {
  5. firstName: 'xiliDong',
  6. lastName: 'dongxili'
  7. }
  8. });

(3)执行多个并发请求

  1. function getUserAccount() {
  2. return axios.get('/user/12345');
  3. }
  4. function getUserPermissions() {
  5. return axios.get('/user/12345/permissions');
  6. }
  7. axios.all([getUserAccount(), getUserPermissions()])
  8. .then(axios.spread(function (acct, perms) {
  9. // 两个请求现在都执行完成
  10. }));
2.创建实例(重点)

可以使用自定义配置新建一个 axios 实例

  1. axios.create([config])
  2. var instance = axios.create({
  3. baseURL: 'https://some-domain.com/api/',
  4. timeout: 1000,
  5. headers: {'X-Custom-Header': 'foobar'}
  6. });

(1)响应结构:

  1. {
  2. data: {}, // data由服务器提供的响应
  3. status: 200, // 服务器响应的 HTTP 状态码
  4. statusText: 'OK', // 服务器响应的 HTTP 状态信息
  5. headers: {}, // 服务器响应的头
  6. config: {} // 为请求提供的配置信息
  7. }

使用 then 时,你将接收下面这样的响应:

  1. axios.get('/user/1111')
  2. .then(function(response) {
  3. console.log(response.data);
  4. console.log(response.status);
  5. console.log(response.statusText);
  6. console.log(response.headers);
  7. console.log(response.config);
  8. });

(2)指定配置的默认值:

  1. axios.defaults.baseURL = 'https://api.example.com';
  2. axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
  3. axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

自定义实例默认值:

// 创建实例时设置配置的默认值

  1. var instance = axios.create({
  2. baseURL: 'https://api.example.com'
  3. });

// 在实例已创建后修改默认值

  1. instance.defaults.headers.common['Authorization'] = AUTH_TOKEN;

(3)拦截器:
(axios配置看我这个例子就差不多了)

  1. // request拦截器
  2. import axios from 'axios'
  3. import router from '../router'
  4. // 创建axios实例
  5. const service = axios.create({
  6. timeout: null // 请求超时时间
  7. })
  8. let serviceTips = '服务器超时'
  9. // request拦截器
  10. service.interceptors.request.use(
  11. config => {
  12. // console.log(service.interceptors)
  13. // 获取本地token
  14. let token = localStorage.getItem('tokendata')
  15. // 设置请求头
  16. let headers = 'application/json'
  17. // 是否携带token
  18. let tokenFlag = true
  19. // 是否修改请求信息
  20. if (config.opts) {
  21. // 获取携带token状态
  22. tokenFlag = config.opts ? config.opts.token : true
  23. // 获取请求头
  24. headers = config.opts.Header ? config.opts.Header : 'application/json'
  25. // 拓展头部参数
  26. let Head = config.opts.Head
  27. if (Head) {
  28. for (let key in Head) {
  29. config.headers[key] = Head[key]
  30. }
  31. }
  32. }
  33. // 暂时不加入token验证
  34. // if (token && tokenFlag) {
  35. // // 条件允许,携带token请求
  36. // config.headers['JSESSIONID'] = token
  37. // // config.headers['X-Auth0-Token'] = token
  38. // } else {
  39. // headers = 'application/x-www-form-urlencoded'
  40. // }
  41. // 设置请求格式
  42. config.headers['Content-Type'] = headers
  43. return config
  44. },
  45. err => {
  46. return Promise.reject(err)
  47. }
  48. )
  49. // http response 服务器响应拦截器
  50. service.interceptors.response.use(
  51. response => {
  52. return response
  53. },
  54. error => {
  55. if (error.response) {
  56. switch (error.response.status) {
  57. case 401:
  58. error.response.data = '登陆超时,重新登陆'
  59. router.replace({
  60. path: '/login',
  61. query: {
  62. redirect: router.currentRoute.fullPath
  63. } // 登录成功后跳入浏览的当前页面
  64. })
  65. break
  66. case 404:
  67. error.response.data = '资源不存在'
  68. break
  69. case 406:
  70. error.response.data = '头部无携带token'
  71. break
  72. case 412:
  73. // 拦截错误 并重新跳入登页重新获取token
  74. router.replace({
  75. path: '/login',
  76. query: {
  77. redirect: router.currentRoute.fullPath
  78. } // 登录成功后跳入浏览的当前页面
  79. })
  80. error.response.data = '秘钥失效'
  81. localStorage.removeItem('tokendata') // 清除token
  82. break
  83. case 415:
  84. error.response.data = '请求type有误'
  85. break
  86. case 500:
  87. error.response.data = '服务器异常'
  88. break
  89. }
  90. serviceTips = error.response.data
  91. }
  92. Message.error(serviceTips)
  93. return Promise.reject(serviceTips)
  94. }
  95. )
  96. export default service

配置好了怎么使用呢?

在api.js中引入拦截器:
import fetch from ‘@/utils/fetch’ // 拦截器
export function getList(obj) {
const data = obj
return fetch({
url: ‘’,
method: ‘POST’,
data
})
}


可以使用 validateStatus 配置选项定义一个自定义 HTTP 状态码的错误范围。

  1. export function getList(obj) {
  2. const data = obj
  3. return fetch({
  4. url: '',
  5. method: 'POST',
  6. validateStatus: function(status) {
  7. // return status >= 200 && status < 300; // 默认的
  8. return status < 500; // 状态码在大于或等于500时才会 reject
  9. },
  10. data
  11. })
  12. }

重点:
axios的请求头默认为’application/json’,
即axios会默认序列化 JavaScript 对象为 JSON.
如果想使用 application/x-www-form-urlencoded 格式,你可以使用下面的配置:

  1. import Qs from 'qs'
  2. export function getList(obj) {
  3. const data = Qs.stringify(obj)
  4. return fetch({
  5. url: '',
  6. method: 'POST',
  7. headers: {
  8. 'content-type': 'application/x-www-form-urlencoded',
  9. // 如果需要XMLHttpRequest,加入这个
  10. 'X-Requested-With': 'XMLHttpRequest'
  11. },
  12. data
  13. })
  14. }

然后在在vue文件中引入此函数来获取数据

  1. // param为前端传入的参数
  2. getList(param).then(res => {
  3. if (res.data.code === 0) {
  4. console.log(res.data.data);
  5. this.allOrderTable = res.data.data.data;
  6. this.pageTotal = res.data.data.total;
  7. } else {
  8. this.$message({
  9. message: `[${res.data.msg}]:查询失败`,
  10. type: "error"
  11. });
  12. }
  13. this.listLoading = false;
  14. })
  15. .catch(() => {})

如果你想在稍后移除拦截器,可以这样:

  1. var myInterceptor = axios.interceptors.request.use(function () {/*...*/});
  2. axios.interceptors.request.eject(myInterceptor);

(4)使用 cancel token 取消请求:

可以使用 CancelToken.source 工厂方法创建 cancel token

  1. var CancelToken = axios.CancelToken;
  2. var source = CancelToken.source();
  3. axios.get('/user/1111', {
  4. cancelToken: source.token
  5. }).catch(function(thrown) {
  6. if (axios.isCancel(thrown)) {
  7. console.log('Request canceled', thrown.message);
  8. } else {
  9. // 处理错误
  10. }
  11. });
  12. // 取消请求(message 参数是可选的)
  13. source.cancel('Operation canceled by the user.');

还可以通过传递一个 executor 函数到 CancelToken
的构造函数来创建 cancel token:

  1. var CancelToken = axios.CancelToken;
  2. var cancel;
  3. axios.get('/user/12345', {
  4. cancelToken: new CancelToken(function executor(c) {
  5. // executor 函数接收一个 cancel 函数作为参数
  6. cancel = c;
  7. })
  8. });

// 取消请求

  1. cancel();

注意,还可以使用同一个 cancel token 取消多个请求

发表评论

表情:
评论列表 (有 0 条评论,168人围观)

还没有评论,来说两句吧...

相关阅读

    相关 vue脚手架

    vue2:脚手架搭建 简介 vue.js有著名的全家桶系列,包含了vue-router,vuex, vue-resource,再加上构建工具vue-cli,就是...

    相关 vue环境--脚手架

    概述 最近由于项目的原因,在学习react的过程中抽出时间来学习一下vue,所以特此记录一些学习笔记,中间如果有一些问题的话欢迎大家指出。 按理说react和vue的思

    相关 vue脚手架流程

    > 搭建vue项目之前你需要安装vue的脚手架和node.js,一起去看看怎么搭建一个vue环境吧。(学编程语言最爱看见的就是用这个先写一个helloworld,只想说我对世界

    相关 Vue脚手架

    一、安装vue-cli 安装vue-cli的前提是你已经安装了npm,安装npm你可以直接下载node的安装包进行安装。你可以在命令行工具里输入npm -v 检测你是否安