Vue2构建项目实战

vue构建单页应用原理

SPA

不是指水疗。是 single page web application 的缩写。中文翻译为 单页应用程序 或 单页Web应用。更多解释清参看 百度百科:SPAjavascript

全部的前端人员都应该明白咱们的页面的 url 构成:css

1 http://www.fengcms.com/index.html?name=fungleo&old=32#mylove/is/world/peace

 

如上的 url 由如下部分组成:html

  1. http:// 规定了页面采用的协议。
  2. www.fengcms.com 为页面所属的域名。
  3. index.html 为读取的文件名称。
  4. ?name=fungleo&old=32 给页面经过 GET 方式传送的参数
  5. #mylove/is/world/peace 为页面的锚点区域

前面四个发生改变的时候,会触发浏览器的跳转亦或是刷新行为,而更改 url 中的锚点,并不会出现这种行为,所以,几乎全部的 spa 应用都是利用锚点的这个特性来实现路由的转换。以咱们的 vue 项目为例,它的本地 url 结构通常为如下格式:前端

1 http://localhost:8080/#/setting/task

 

能够明显的看到咱们所谓的路由地址是在 # 号后面的,也就是利用了锚点的特性。vue

RESTful 风格接口

实际状况是,咱们在先后端在约定接口的时候,能够约定各类风格的接口,可是,RESTful 接口是目前来讲比较流行的,而且在运用中比较方便和常见的接口。java

虽然它有一些缺陷,目前 github 也在主推 GraphQL 这种新的接口风格,但目前国内来讲仍是 RESTful 接口风格比较广泛。node

而且,在掌握了 RESTful 接口风格以后,会深刻的理解这种接口的优缺点,到时候,你天然会去想解决方案,而且在项目中实行新的更好的理念,因此,我这系列的博文,依然采用 http://cnodejs.org/ 网站提供的 RESTful 接口来实战。jquery

了解程序开发的都应该知道,咱们所作的大多数操做都是对数据库的四格操做 “增删改查” 对应到咱们的接口操做分别是:linux

  1. post 插入新数据
  2. delete 删除数据
  3. put 修改数据
  4. get 查询数据

注意,这里是咱们约定,并不是这些动做只能干这件事情。从表层来讲,除get外的其余方法,没有什么区别,都是同样的。从深层来讲包括 get在内的全部方法都是如出一辙的,没有任何区别。可是,咱们约定,每种动做对应不一样的操做,这样方便咱们统一规范咱们的全部操做。webpack

假设,咱们的接口是 /api/v1/love 这样的接口,采用 RESTful 接口风格对应操做是以下的:


get 操做 /api/v1/love

获取 /api/v1/love 的分页列表数据,获得的主体,将是一个数组,咱们能够用数据来遍历循环列表

post 操做 /api/v1/love

咱们会往 /api/v1/love 插入一条新的数据,咱们插入的数据,将是JOSN利用对象传输的。

get 操做 /api/v1/love/1

咱们获取到一个 ID 为 1 的的数据,数据通常为一个对象,里面包含了 1 的各项字段信息。

put 操做 /api/v1/love/1

咱们向接口提交了一个新的信息,来修改 ID 为 1 的这条信息

delete 操做 /api/v1/love/1

咱们向接口请求,删除 ID 为 1 的这一条数据


由上述例子可知,咱们实现了5种操做,但只用了两个接口地址, /api/v1/love 和 /api/v1/love/1 。因此,采用这种接口风格,能够大幅的简化咱们的接口设计。

1、安装 nodejs 环境

你能够在 https://nodejs.org/ nodejs 官方网站下载安装包,而后进行安装。若是是 linux 或者 mac 命令行的用户,也可使用命令行安装。

在安装好了 nodejs 以后,咱们在终端中输入如下两个命令:

node -v

npm -v

可以获得版本号信息,则说明你的 nodejs 环境已经安装完成了。

2、安装 vue-cli VUE的脚手架工具

vue-cil是vue的脚手架工具。其模板能够经过 vuejs-templates 来查看。

咱们首先安装全局vue-cil脚手架,用于帮助搭建所需的模板框架,命令以下:

npm install -g vue-cli
# 回车,等待安装...
vue
# 回车,若出现vue信息说明表示成功

这个命令只须要运行一次就能够了。安装上以后,之后就不用安装了。

下面,咱们来用vue-cil构建一个项目。

首先,咱们在终端中把当前目录定位到你准备存放项目的地方。如我是准备放在~/Sites/MyWork/这个目录下面,那么个人命令以下:

cd ~/Sites/MyWork

(也能够直接在目录内打开终端)进入到目录以后,咱们按照下面的代码逐条输入,新建一个本身的vue项目,vuedemo是本身起的项目名称

vue init webpack vuedemo
# 这里须要进行一些配置,默认回车便可
? Project name vuedemo
? Project description A Vue.js project
? Author
? Vue build standalone
? Install vue-router? Yes
? Use ESLint to lint your code? Yes
? Pick an ESLint preset Standard
? Set up unit tests Yes
? Pick a test runner jest
? Setup e2e tests with Nightwatch? Yes
? Should we run `npm install` for you after the project has been created? (reco
mmended) npm

  vue-cli · Generated "vuedemo".

# Project initialization finished!
# ========================

To get started:

cd vuedemo
npm install
npm run dev

Documentation can be found at https://vuejs-templates.github.io/webpack

如上图所示,就说明咱们的项目构建成功了。而且,给出了下面要执行的命令,咱们进入项目,安装并运行:


#在cmd输入项目名
cd vuedemo
#回车,进入到具体项目文件夹
npm install
#回车,等待一小会儿
#回到项目文件夹,会发现项目结构里,多了一个node_modules文件夹(该文件里的内容就是以前安装的依赖)
最后,执行下面一句,把项目跑起来
npm run dev
DONE Compiled successfully in 4388ms

> Listening at http://localhost:8080

成功执行以上命令后访问 http://localhost:8080/,输出结果

总上所述,安装vue-cil后执行四行命令,就能够把一个名为vuedemo的项目跑起来。

进入项目文件夹后vue init webpack vuedemo新建一个项目

进入项目cd vuedemo

建立项目npm install

运行项目npm run dev

固然,这个名字你是能够随便起的,根据你的实际项目来定。

经过上面的这些命令,咱们就实现了新建一个vue+webpack的项目。在运行了npm run dev以后,会自动打开一个浏览器窗口,就能够看到实际的效果了。

JavaScript Standard

在建立项目时咱们有开启了一个standard语法效验,JavaScript 代码规范,自带 linter & 代码自动修正。

官网:https://standardjs.com/readme-zhcn.html

主要的语法规则有:

  • 使用两个空格 – 进行缩进
  • 字符串使用单引号 – 须要转义的地方除外
  • 再也不有冗余的变量 – 这是致使 大量 bug 的源头!
  • 无分号 – 没什么很差。不骗你!
  • 行首不要以 ([, or ` 开头
    • 这是省略分号时惟一会形成问题的地方 – 工具里已加了自动检测!
    • 详情
  • 关键字后加空格 if (condition) { ... }
  • 函数名后加空格 function name (arg) { ... }
  • 坚持使用全等 === 摒弃 == 一但在须要检查 null || undefined 时可使用 obj == null
  • 必定要处理 Node.js 中错误回调传递进来的 err 参数。
  • 文件末尾留一空行
  • 使用浏览器全局变量时加上 window 前缀 – document 和 navigator 除外
    •   避免无心中使用到了这些命名看上去很普通的全局变量, openlengthevent 还有 name
  • 查看更多 – 为什么不试试 standard 规范呢!

3、项目目录及文件结构

以前咱们已经新建好了一个基于vue+webpack的项目。咱们在 IDE(Eclipse、Atom等) 中打开该目录,结构以下所示:

复制代码
 1 ├── README.md                       // 项目说明文档
 2 ├── node_modules                    // 项目依赖包文件夹
 3 ├── build                           // 编译配置文件,通常不用管
 4 │   ├── build.js
 5 │   ├── check-versions.js
 6 │   ├── dev-client.js
 7 │   ├── dev-server.js
 8 │   ├── utils.js
 9 │   ├── vue-loader.conf.js
10 │   ├── webpack.base.conf.js
11 │   ├── webpack.dev.conf.js
12 │   └── webpack.prod.conf.js
13 ├── config                          // 项目基本设置文件夹
14 │   ├── dev.env.js              // 开发配置文件
15 │   ├── index.js                    // 配置主文件
16 │   └── prod.env.js             // 编译配置文件
17 ├── index.html                      // 项目入口文件
18 ├── package-lock.json           // npm5 新增文件,优化性能
19 ├── package.json                    // 项目依赖包配置文件
20 ├── src                             // 咱们的项目的源码编写文件
21 │   ├── App.vue                 // APP入口文件
22 │   ├── assets                      // 初始项目资源目录,回头删掉
23 │   │   └── logo.png
24 │   ├── components              // 组件目录
25 │   │   └── Hello.vue           // 测试组件,回头删除
26 │   ├── main.js                 // 主配置文件
27 │   └── router                      // 路由配置文件夹
28 │       └── index.js            // 路由配置文件
29 └── static                          // 资源放置目录
复制代码

 

 

如上图所示,咱们的目录结构就是这样的了。

咱们绝大多数的操做,就是在 src 这个目录下面。默认的 src 结构比较简单,咱们须要从新整理。

另外 static 资源目录,咱们也须要根据放置不一样的资源,在这边构建不一样的子文件夹。

咱们来配置 src 目录

先不要管这些文件的内容,咱们先创建这些空的文件在这边。而后咱们后面去完善它。

咱们的这个项目是要作两个页面,一个是 cnodejs 的列表页面,一个是详情页面。

因此,我把项目文件夹整理成以下的结构

复制代码
 1 ├── App.vue                         // APP入口文件
 2 ├── api                             // 接口调用工具文件夹
 3 │   └── index.js                    // 接口调用工具
 4 ├── components                      // 组件文件夹,目前为空
 5 ├── config                          // 项目配置文件夹
 6 │   └── index.js                    // 项目配置文件
 7 ├── frame                           // 子路由文件夹
 8 │   └── frame.vue                   // 默认子路由文件
 9 ├── main.js                         // 项目配置文件
10 ├── page                                // 咱们的页面组件文件夹
11 │   ├── content.vue             // 准备些 cnodejs 的内容页面
12 │   └── index.vue                   // 准备些 cnodejs 的列表页面
13 ├── router                          // 路由配置文件夹
14 │   └── index.js                    // 路由配置文件
15 ├── style                           // scss 样式存放目录
16 │   ├── base                        // 基础样式存放目录
17 │   │   ├── _base.scss          // 基础样式文件
18 │   │   ├── _color.scss     // 项目颜色配置变量文件
19 │   │   ├── _mixin.scss     // scss 混入文件
20 │   │   └── _reset.scss     // 浏览器初始化文件
21 │   ├── scss                        // 页面样式文件夹
22 │   │   ├── _content.scss       // 内容页面样式文件
23 │   │   └── _index.scss     // 列表样式文件
24 │   └── style.scss              // 主样式文件
25 └── utils                           // 经常使用工具文件夹
26     └── index.js                    // 经常使用工具文件
复制代码

 

由于咱们删除了一些默认的文件,因此这个时候项目必定是报错的,先无论他,咱们根据咱们的需求,新建如上的项目结构。这些都是在 src 目录里面的结构。

4、调整app.vue和设置路由

1.调整 App.vue 文件

 咱们先把默认项目里面没用的东西先删除掉,把代码调整为下面的样子。

复制代码
 1 <template>
 2   <div id="app">
 3     <router-view></router-view>
 4   </div>
 5 </template>
 6 
 7 <script>
 8 export default {
 9   name: 'app'
10 }
11 </script>
12 
13 <style lang="css">
14   @import "./style/index.css";
15 </style>
复制代码

入口,只有一个空的路由视窗,咱们的项目的全部内容,都基于这个视窗来展示。由于scss文件容易出现语法错误,这里先用css文件替代。后期熟悉以后再更改

咱们的样式,都将从 src/style/index.css这个文件中引用,若是没有请按路径新建!

2.调整 index.vue 和 content.vue 文件

昨天,咱们在 page 文件夹下面创建了两个空文本文件 index.vue 和 content.vue 文件,是咱们准备用来放列表和内容的。

这里,咱们先去填写一点基础内容在里面。

index.vue

1 <template>
2   <div>index page</div>
3 </template>

content.vue

1 <template>
2   <div>content page</div>
3 </template>

好,写上如上的代码就行,咱们后面再丰富这些内容。

3.调整 router 路由文件

如今,这个项目还跑不起来呢,若是你运行 npm run dev 仍是会出错的。由于咱们尚未配置路由。

复制代码
 1 import Vue from 'vue'
 2 import Router from 'vue-router'
 3 import Hello from '@/components/Hello'
 4 
 5 Vue.use(Router)
 6 
 7 export default new Router({
 8   routes: [
 9     {
10       path: '/',
11       name: 'Hello',
12       component: Hello
13     }
14   ]
15 })
复制代码

以上,是默认的路由文件,引用了一个 Hello 的组件,这个组件被咱们昨天的博文中整理文件结构的时候删除掉了。因此,这里就报错啦。

咱们根据咱们的须要,来调整这个路由文件,以下:

复制代码
 1 import Vue from 'vue'
 2 import Router from 'vue-router'
 3 import Index from '@/page/index'
 4 import Content from '@/page/content'
 5 
 6 Vue.use(Router)
 7 
 8 export default new Router({
 9   routes: [
10     {
11       path: '/',
12       component: Index
13     }, {
14       path: '/content/:id',
15       component: Content
16     }
17   ]
18 })
复制代码

默认,咱们的首页,就是咱们的 index.vue 组件,这里,你可能要问 :id 是什么意思?

由于咱们的内容页面是要展现N条内容的,咱们如何来区分这些内容呢,就是根据ID来进行区分。因此,这里使用了动态路由匹配。

更多内容,能够参考官方文档《动态路由匹配

好,咱们如今,项目应该是没有任何错误,能够跑起来了。忘记跑起来的命令了?以下:

npm run dev

五。配置axios api接口调用文件

咱们经过配置基本的信息,已经让咱们的项目可以正常的跑起来了。可是,这里尚未涉及到 AJAX 请求接口的内容。

vue 自己是不支持 ajax 接口请求的,因此咱们须要安装一个接口请求的 npm 包,来使咱们的项目拥有这个功能。

这实际上是一个重要的 unix 思想,就是一个工具只作好一件事情,你须要额外的功能的时候,则须要安装对应的软件来执行。若是你之前是一个 jquery 重度用户,那么可能理解这个思想必定要深刻的理解。

支持 ajax 的工具备不少。一开始,我使用的是 superagent 这个工具。可是我发现近一年来,绝大多数的教程都是使用的 axios 这个接口请求工具。其实,这原本是没有什么差异的。可是为了防止大家在看了个人博文和其余的文章以后,产生理念上的冲突。所以,我也就改用 axios 这个工具了

 自己, axios 这个工具已经作了很好的优化和封装。可是,在使用的时候,仍是略显繁琐,所以,我从新封装了一下。固然,更重要的是,封装 axios 这个工具是为了和我之前写的代码的兼容。不过我封装得很好,也推荐你们使用。

1.封装 axios 工具,编辑 src/api/index.js 文件

首先,咱们要使用 axios 工具,就必须先安装 axios 工具。执行下面的命令进行安装

npm install axios -D

这样,咱们就安装好了 axios 工具了。

还记得咱们在第三篇博文中整理的系统结构吗?咱们新建了一个 src/api/index.js 这个空文本文件,就那么放在那里了。这里,咱们给它填写上内容。

复制代码
// 配置API接口地址
var root = 'https://cnodejs.org/api/v1'
// 引用axios
var axios = require('axios')
// 自定义判断元素类型JS
function toType (obj) {
  return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}
// 参数过滤函数
function filterNull (o) {
  for (var key in o) {
    if (o[key] === null) {
      delete o[key]
    }
    if (toType(o[key]) === 'string') {
      o[key] = o[key].trim()
    } else if (toType(o[key]) === 'object') {
      o[key] = filterNull(o[key])
    } else if (toType(o[key]) === 'array') {
      o[key] = filterNull(o[key])
    }
  }
  return o
}
/*
  接口处理函数
  这个函数每一个项目都是不同的,我如今调整的是适用于
  https://cnodejs.org/api/v1 的接口,若是是其余接口
  须要根据接口的参数进行调整。参考说明文档地址:
  https://cnodejs.org/topic/5378720ed6e2d16149fa16bd
  主要是,不一样的接口的成功标识和失败提示是不一致的。
  另外,不一样的项目的处理方法也是不一致的,这里出错就是简单的alert
*/

function apiAxios (method, url, params, success, failure) {
  if (params) {
    params = filterNull(params)
  }
  axios({
    method: method,
    url: url,
    data: method === 'POST' || method === 'PUT' ? params : null,
    params: method === 'GET' || method === 'DELETE' ? params : null,
    baseURL: root,
    withCredentials: false
  })
  .then(function (res) {
    if (res.data.success === true) {
      if (success) {
        success(res.data)
      }
    } else {
      if (failure) {
        failure(res.data)
      } else {
        window.alert('error: ' + JSON.stringify(res.data))
      }
    }
  })
  .catch(function (err) {
    let res = err.response
    if (err) {
      window.alert('api error, HTTP CODE: ' + res.status)
    }
  })
}

// 返回在vue模板中的调用接口
export default {
  get: function (url, params, success, failure) {
    return apiAxios('GET', url, params, success, failure)
  },
  post: function (url, params, success, failure) {
    return apiAxios('POST', url, params, success, failure)
  },
  put: function (url, params, success, failure) {
    return apiAxios('PUT', url, params, success, failure)
  },
  delete: function (url, params, success, failure) {
    return apiAxios('DELETE', url, params, success, failure)
  }
}
复制代码

有关 axios 的更多内容,请参考官方 github: https://github.com/mzabriskie/axios ,中文资料自行百度。

但就是这样,咱们还不能再 vue 模板文件中使用这个工具,还须要调整一下 main.js 文件。

2.调整 main.js 绑定 api/index.js 文件

此次呢,咱们没有上来就调整 main.js 文件,由于原始文件就配置得比较好,我就没有刻意的想要调整它。

原始文件以下:

复制代码
 1 import Vue from 'vue'
 2 import App from './App'
 3 import router from './router'
 4 
 5 Vue.config.productionTip = false
 6 
 7 /* eslint-disable no-new */
 8 new Vue({
 9   el: '#app',
10   router,
11   template: '<App/>',
12   components: { App }
13 })
复制代码

咱们插入如下代码:

1 // 引用API文件
2 import api from './api/index.js'
3 // 将API方法绑定到全局
4 Vue.prototype.$api = api

也就是讲代码调整为:

复制代码
import Vue from 'vue'
import App from './App'
import router from './router'

// 引用API文件
import api from './api/index.js'
// 将API方法绑定到全局
Vue.prototype.$api = api

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  template: '<App/>',
  components: { App }
})
复制代码

好了,这样,咱们就能够在项目中使用咱们封装的 api 接口调用文件了。

3.测试一下看看能不能调通

咱们来修改一下 src/page/index.vue 文件,将代码调整为如下代码:

复制代码
 1 <template>
 2   <div>index page</div>
 3 </template>
 4 <script>
 5 export default {
 6   created () {
 7     this.$api.get('topics', null, r => {
 8       console.log(r)
 9     })
10   }
11 }
12 </script>
复制代码

好,这里是调用 cnodejs.org 的 topics 列表接口,而且将结果打印出来。

咱们在浏览器中打开控制台,看看 console 下面有没有输出入下图同样的内容。若是有的话,就说明咱们的接口配置已经成功了。

好,若是你操做正确,代码没有格式错误的话,那么如今应该获得的结果是和我同样的。若是出错或者怎么样,请仔细的检查代码,看看有没有什么问题。

6、将接口用webpack代理到本地

咱们已经很是顺利的调用到了 cnodejs.org 的接口了。可是,咱们能够注意到咱们的 src/api/index.js 的第一句,就是:

1 // 配置API接口地址
2 var root = 'https://cnodejs.org/api/v1'

这里,咱们将接口地址写死了。

固然,这并非最重要的事情,而是 cnodejs.org 帮咱们把接口处理得很好,解决了跨域的问题。而咱们的实际项目中,不少接口都是不容许咱们这样跨域请求的。

而咱们的开发环境下,不可能跑到服务器上直接开发,或者在本地直接搞一个服务器环境,这样就违背了咱们先后端分离开发的初衷了。

如何解决这个问题呢?其实很是好办,要知道 跨域不是接口的限制 而是浏览器为了保障数据安全作的限制。所以,一种方法能够解决,那就是打开浏览器的限制,让咱们能够顺利的进行开发。可是无奈的是,最新的 chrome 浏览器好像已经关闭了这个选项,那么咱们只能采用另一种方法了——将接口代理到本地。

1.配置 webpack 将接口代理到本地

好在,vue-cli 脚手架工具,已经充分的考虑了这个问题,咱们只要进行简单的设置,就能够实现咱们的目的。

咱们打开 config/index.js 文件,找到如下代码:

复制代码
1   dev: {
2     env: require('./dev.env'),
3     port: 8080,
4     autoOpenBrowser: true,
5     assetsSubDirectory: 'static',
6     assetsPublicPath: '/',
7     proxyTable: {},
8     cssSourceMap: false
9   }
复制代码

其中,proxyTable: {}, 这一行,就是给咱们配置代理的。

根据 cnodejs.org 的接口,咱们把这里调整为:

复制代码
1 proxyTable: {
2   '/api/v1/**': {
3     target: 'https://cnodejs.org', // 你接口的域名
4     secure: false,
5     changeOrigin: false,
6   }
7 }
复制代码

OK,咱们这样配置好后,就能够将接口代理到本地了。

更多接口参数配置,请参考 https://github.com/chimurai/http-proxy-middleware#options

webpack 接口配置文档 https://webpack.js.org/configuration/dev-server/#devserver-proxy

2.从新配置 src/api/index.js 文件

好,上面已经代理成功了,可是咱们的 src/api/index.js 文件,仍是直接调用的人家的地址呢,咱们要调整为咱们的地址,调整以下:

1 // 配置API接口地址
2 var root = '/api/v1'

以前我有一篇博文,说过如何配置开发接口地址和生产接口地址,当时是利用了 webpack 的不一样的配置文件来进行配置的。若是咱们采用这种代理模式呢,那么就没有必要那么作了。由于咱们的系统放到生产环境的时候,通常是没有这个跨域问题的。这个问题通常仅仅是存在于咱们的开发环境下面。

值得注意的事情是,配置完成后,是不会当即生效的,咱们须要重启咱们的项目。

咱们按 ctrl + c 中止掉以前的服务,而后从新输入命令 npm run dev 重启项目,就能够了。

如上图所示,咱们能够清晰的看到,咱们跑的服务,先开启了一个代理。

从新跑起来以后,咱们看下咱们的项目在浏览器中的表现:

咱们打开浏览器控制台,切换到 network 选项卡中,选中咱们调用的接口 topics 接口,咱们能够清晰的看到,咱们读取的接口地址是咱们的本地代理过来的地址。

状态码为 304 表明这个数据没有发生变化,直接读取本地缓存了。关于 http 状态码 的部分,请参考 百度百科 http 状态码,这里不作过多的说明。

咱们再看一下数据是否是正常的过来了。切换到 Previdw 选项卡查看:

Previdw

没有问题,数据过来了。

好,到这里,咱们已经顺利的将接口代理到本地,而且数据读取出来了。咱们开始准备下面的工做吧!

7.初识*.vue文件,即VUE组件

*.vue 文件,是一个自定义的文件类型,用类 HTML 语法描述一个 Vue 组件。每一个 .vue文件包含三种类型的顶级语言块 <template><script> 和 <style>。这三个部分分别表明了 html,js,css

其中 <template> 和 <style> 是支持用预编译语言来写的。好比,在咱们的项目中,咱们能够用 scss 预编译,咱们能够这样写的:

1 <style lang="scss">

html 也有本身的预编译语言, vue 也是支持的,不过通常来讲,咱们前端人员仍是比较中意 html 原生语言,因此,我就不过多阐述了。

另外,我在 App.vue 文件中,已经用一句 @import "./style/style"; 将咱们的样式给写到指定的地方去了。因此,在后面全部的个人文章中,是不会出现这个部分的内容的。全部样式,都会在 src/style/ 文件夹中对应的位置去写。 
我这样作的好处是,不须要重复的引入各类 scss 基础文件,而且作到了项目的样式代码的可管控

1.一个常见的 *.vue 文件代码解析

首先,咱们来简单看一下:

复制代码
 1 <template>
 2   <div>
 3     <Header></Header>
 4     <div class="article_list">
 5       <ul>
 6         <li></li>
 7       </ul>
 8     </div>
 9     <Footer></Footer>
10   </div>
11 </template>
12 <script>
13 import Header from '../components/header.vue'
14 import Footer from '../components/footer.vue'
15 export default {
16   components: { Header, Footer },
17   data () {
18     return {
19       list: []
20     }
21   },
22   created () {
23     this.getData()
24   },
25   methods: {
26     getData () {
27       this.$api.get('topics', null, r => {
28         console.log(r)
29       })
30     }
31   }
32 }
33 </script>
34 <style>
35   .article_list {margin: auto;}
36 </style>
复制代码

好,以上就是一个简单的 *.vue 文件的基本结构。咱们一部分一部分的来解释。

如下,我再也不称呼它为 *.vue 文件了。改为为 vue 组件。

2.template 部分

首先,一个 vue 组件,他的 template 则表明它的 html 结构,相信你们能够理解了。可是须要注意的是,咱们不是说把代码包裹在 <template></template> 中就能够了,而是必须在里面放置一个 html 标签来包裹全部的代码。 本例子中,咱们采用了 <div></div> 标签。vue2.x 开始,就必须这样去写。这是规定

你们看到 <Header></Header> 这个代码的时候确定很奇怪,这是个什么玩意儿。其实,这是一个自定义组件。咱们在其余地方写好了一个组件,而后就能够用这种方式引入进来。

一样 <Footer></Footer> 也是一个组件。再也不累述。

其余的内容,咱们就想这么写就怎么写了。和写咱们的 html 代码没有什么太大的区别。

3.script 部分

首先,咱们须要两个自定义组件,咱们先引用进来。以下格式,比较好理解吧。

1 import Header from '../components/header.vue'
2 import Footer from '../components/footer.vue'

其次,除了引用的文件,咱们将全部的代码包裹于以下的代码中间:

1 export default {
2   // 这里写你的代码,外面要包起来。
3 }

4.style 部分

这里比较简单,就是针对咱们的 template 里内容出现的 html 元素写一些样式。如上,个人代码:

1 <style>
2   .article_list {margin: auto;}
3 </style>

就是给咱们的 .article_list 元素随便加了一个样式。

参考资料:《vue 模板语法

8、渲染列表

1.制做 header.vue 和 footer.vue 组件文件。

不是本篇文章的重点,可是仍是有比较讲一下。在第三篇博文中,咱们规划了咱们的项目文件结构,当时保留了一个 components 的空文件夹。这里,就是准备放咱们的自定义组件的。

首先,咱们去建立两个空文本文件,分别是 header.vue 文件和 footer.vue 文件。

而后,往里面输入下面的内容:

header.vue

1 <template>
2   <header class="header">
3     <h1 class="logo">Vue Demo by DEMO</h1>
4   </header>
5 </template>

footer.vue

1 <template>
2   <footer class="copy">
3     Copy &copy; DEMO
4 </footer> 5 </template>

很是简单的两个文件,表示咱们的组件已经弄好了

2.编写 src/page/index.vue 文件

复制代码
 1 <template>
 2   <div>
 3     <Header></Header>
 4     <div class="article_list">
 5       <ul>
 6         <li v-for="i in list" :key="i.id">
 7           <time v-text="i.create_at"></time>
 8           <router-link :to="'/content/' + i.id">
 9             {{ i.title }}
10           </router-link>
11         </li>
12       </ul>
13     </div>
14     <Footer></Footer>
15   </div>
16 </template>
17 <script>
18 import Header from '../components/header.vue'
19 import Footer from '../components/footer.vue'
20 export default {
21   components: { Header, Footer },
22   data () {
23     return {
24       list: []
25     }
26   },
27   created () {
28     this.getData()
29   },
30   methods: {
31     getData () {
32       this.$api.get('topics', null, r => {
33         this.list = r.data
34       })
35     }
36   }
37 }
38 </script>
复制代码

如上,代码,我就把页面渲染出来了。咱们看下实际的效果:

如上,我先用了一个 v-for 的循环,来循环数据。这里能够参考:https://cn.vuejs.org/v2/api/#v-for 文档。

在 time 标签中,我使用了 v-text="i.create_at" 来渲染时间数据。参考文档: https://cn.vuejs.org/v2/api/#v-text

router-link 是 VueRouter2 “声明式导航”的写法,在实际转换为 html 标签的时候,会转化为 <a></a>,里面的 to 属性,就至关于 a 的 href 属性。参考文档:https://router.vuejs.org/zh-cn/essentials/getting-started.html

3.编写 src/utils/index.js 文件

如上面的图片所示,因为拿到的数据是一个标准的时间格式,直接渲染在页面上,这个效果不是很理想。所以,咱们能够把时间给处理一下,而后再渲染出来。

这里,咱们能够直接在 getData () {...} 后面再写一个方法便可。可是,在一个项目中,若是全部的地方都是这样的时间格式,咱们在每个组件中都来写这样的处理方法,很显然就显得咱们比较愚蠢了。

所以,咱们能够独立出来写一个方法,而后在全部的地方均可以使用,这样就比较方便了。

还记得咱们在第三篇博文中,咱们创建了一个 src/utils/index.js 的空文本文件吗?这里,咱们要用上了。

直接给代码以下:

复制代码
 1 export default {
 2   goodTime (str) {
 3     let now = new Date().getTime()
 4     let oldTime = new Date(str).getTime()
 5     let difference = now - oldTime
 6     let result = ''
 7     let minute = 1000 * 60
 8     let hour = minute * 60
 9     let day = hour * 24
10     let month = day * 30
11     let year = month * 12
12     let _year = difference / year
13     let _month = difference / month
14     let _week = difference / (7 * day)
15     let _day = difference / day
16     let _hour = difference / hour
17     let _min = difference / minute
18 
19     if (_year >= 1) {
20       result = '发表于 ' + ~~(_year) + ' 年前'
21     } else if (_month >= 1) {
22       result = '发表于 ' + ~~(_month) + ' 个月前'
23     } else if (_week >= 1) {
24       result = '发表于 ' + ~~(_week) + ' 周前'
25     } else if (_day >= 1) {
26       result = '发表于 ' + ~~(_day) + ' 天前'
27     } else if (_hour >= 1) {
28       result = '发表于 ' + ~~(_hour) + ' 个小时前'
29     } else if (_min >= 1) {
30       result = '发表于 ' + ~~(_min) + ' 分钟前'
31     } else {
32       result = '刚刚'
33     }
34     return result
35   }
36 }
复制代码

好,代码恶心了点,我拿我之前写的代码改的,没有深刻优化,你们就随便看看,大概就是这么个东西。

写好代码以后,咱们保存文件。可是此时,咱们还不能使用咱们的这个方法函数。咱们必须在 main.js 中将咱们的方法函数给绑定上。以下代码:

1 // 引用工具文件
2 import utils from './utils/index.js'
3 // 将工具方法绑定到全局
4 Vue.prototype.$utils = utils

好了,这样,咱们写的这个函数,就能够随便被咱们调用了。咱们再来修改一下咱们上面的 index.vue 中的代码,将 time 调整为:

1 <time v-text="$utils.goodTime(i.create_at)"></time>

而后,咱们再来看一下实际的效果:

vue demo by fungleo

好,咱们已经看到,时间已经搞的挺好的了。

9、把内容页面渲染出来

前面咱们从文章中留下的引子 <router-link :to="'/content/' + i.id"> 应该知道,咱们仍是要作内容页面的。

1.编写内容页面

复制代码
 1 <template>
 2   <div>
 3     <myHeader></myHeader>
 4     <h2 v-text="dat.title"></h2>
 5     <p v-if="dat.author">做者:{{dat.author.loginname}}发表于:{{$utils.goodTime(dat.create_at)}}</p>
 6     <hr>
 7     <article v-html="dat.content"></article>
 8     <h3>网友回复:</h3>
 9     <ul>
10       <li v-for="i in dat.replies">
11         <p>评论者:{{i.author.loginname}}评论于:{{$utils.goodTime(i.create_at)}}</p>
12         <article v-html="i.content"></article>
13       </li>
14     </ul>
15     <myFooter></myFooter>
16   </div>
17 </template>
18 <script>
19 import myHeader from "../components/header.vue";
20 import myFooter from "../components/footer.vue";
21 export default {
22   components: { myHeader, myFooter },
23   data() {
24     return {
25       id: this.$route.params.id,
26       dat: {}
27     };
28   },
29   created() {
30     this.getData();
31   },
32   methods: {
33     getData() {
34       this.$api.get("topic/" + this.id, null, r => {
35         this.dat = r.data;
36       });
37     }
38   }
39 };
40 </script>
复制代码

好,咱们这边把代码写进 src/page/content.vue 文件。而后保存,我在咱们先前的列表页面随便点开一篇文章,而后咱们看下结果:

10、打包项目并发布到子目录

咱们已经完成了咱们设想的项目的开发。可是,咱们作好的这套东西,是基于 nodejs 开发的。而咱们最终但愿,咱们开发的项目,生成好一堆文件,而后随便经过任何一个 http 服务就能跑起来,也就是,还原成咱们熟悉的 html+css+js 的模式。

1.打包项目

们进入到终端,而且进入到咱们的开发目录:

 cd ~/Site/MyWork/vue-demo-cnodejs

而后运行以下代码,进行打包:

npm run build

运行结果以下:

 

好,咱们已经打包好了。文件打包位置于项目目录里面的 dist 文件夹内。

可是,咱们从上图能够看到,咱们生成了一些 .map 的文件。这就有点恶心了。当咱们的项目变得比较大的时候,这些文件,第一个是,很是大,第二个,编译时间很是长。因此,咱们要把这个文件给去掉。

咱们编辑 /config/index.js 文件,找到其中的

1 productionSourceMap: true,

修改成:

1 productionSourceMap: false,

而后咱们从新运行打包命令:

npm run build

 

没用的 map 文件已经没有了。

好,咱们能够从上图中看出,有一个 tip 。它告诉咱们,打包出来的文件,必须在 http 服务中运行,不然,不会工做。

2.安装 http-server 启动 http 服务

咱们进入 dist 文件夹,而后启动一个 http 服务,来看看能够不能够访问。

你可能不知道如何启动这样一个 http 服务,或者,你如今已经到 apache 里面去进行配置去了。不用那么麻烦,咱们有 nodejs 环境,只要全局安装一个 http-server 服务就行了呀。

npm install http-server -g

好,经过这个命令,咱们就安装好了。安装好了以后正常咱们就可以使用 http-server 命令来跑服务了。可是,这个世界不正常的时候是不少的嘛!

在终端里面输入,

http-server

看可否正常启动,仍是爆 -bash: http-server: command not found 错误,这里,是说没有找到这个命令,没有关系,这是表示,咱们的 nodejs 的程序执行路径,没有添加到环境变量中去。

首先,如上图所示,咱们的 http-server 安装到了 /usr/local/Cellar/node/7.6.0/bin/ 这个目录下面,咱们只要把这个目录,添加到环境变量便可。

请注意,你的安装路径可能和个人是不一致的,请注意调整。

咱们在终端内执行下面两个命令,就能够了。

echo 'export PATH="$PATH:/usr/local/Cellar/node/7.6.0/bin/"' >> ~/.bash_profile

. ~/.bash_profile

第一条命令是追加环境变量,第二个命令是,使咱们的追加当即生效。

固然,你也能够直接编辑 ~/.bash_profile 文件,把上面命令中的单引号里面的内容插入到文件最后面,而后执行第二个命令生效。随便。

好,一个插曲结束。咱们要把咱们打包出来的东西跑起来呀!

cd dist

http-server -p 3000

若是你是严格按照个人教程来的,那么如今已经能够顺利的跑起来了。咱们在浏览器中输入 http://127.0.0.1:3000 就应该能够访问了。

固然,会报错,说是接口找不到,404错误。由于咱们把接口给经过代理的方式开启到了本地,可是这里咱们并无开启代理,因此就跑不起来了。很正常的。

这是由于示例的接口的问题。实际开发你还要按照个人这个作。只不过,最终代码放到真实的服务器环境去和后端接口在一个 http 服务下面的话,就不存在这个问题了。

好,咱们就跑起来了。

3.将项目打包到子目录

刚刚,咱们是将文件,打包为根目录访问的。也就是说,必须在 dist 文件夹下面启动一个服务,才能把项目跑起来。

可是咱们开发的大多数项目,多是必须跑在二级目录,甚至更深层次的目录的。怎么作呢?

咱们编辑 config/index.js 文件,找到:

assetsPublicPath: '/',

把 '/' 修改成你要放的子目录的路径就好了。这里,我要放到 /dist/ 目录下面。因而,我就把这里修改成

1 assetsPublicPath: '/dist/',

而后,从新运行

 

npm run build

进行打包。

很快,就打包好了。

还记得,咱们在项目文件夹中用 npm run dev 就能够开启一个 http 服务吗?而且那里,咱们还代理了接口的。

好,咱们就这么作。

而后咱们访问二级目录 /dist/ 咱们就能够看到效果了。

注意,我访问的不是根目录,而是 /dist/ 这个子目录哦,这里是访问的咱们打包的文件的。

复制代码
1 ├── index.html
2 └── static
3     ├── css
4     │   └── app.d41d8cd98f00b204e9800998ecf8427e.css
5     └── js
6         ├── app.8ffccad49e36e43a4e9b.js
7         ├── manifest.7a471601ff5a8b26ee49.js
8         └── vendor.057dd4249604e1e9c3b5.js
复制代码

好,到这里,咱们的打包工做,就讲完了。

实际开发中,你只须要把 dist 文件夹中打包好的文件,给运维他们,让他们去部署到真实的服务器环境就行了。

11、打包项目图片等资源的处理

1.在 vue 文件中,引用图片

例如,咱们将一张图片放到资源目录 /static/image/lyf.jpg 咱们在 vue 文件中用下面的代码来使用这张图片。

1 <img src="static/image/lyf.jpg" alt="刘亦菲">

注意,最前面不要加 / 若是是这样操做的话,会变成相对根目录调用图片。若是你的项目要打包到子目录的话,这样作就会出现问题。

2.在 css 文件中,引用图片的处理

仍是上面那张图片,咱们须要在 css 中来引用,如何来写呢?

.love {
  background-image: url('../static/image/lyf.jpg');
}

好,这里为何要加上 ../ 呢?

若是是最终打包到根目录的话,可使用 / 这种路径。这个是彻底能够理解的。

但,若是是打包到子目录,咱们必须看下生成的最终路径:

复制代码
├── index.html
└── static
    ├── css
    │   └── app.a7a745952a8ca7f8c9413d53b431b8c8.css
    ├── image
    │   └── lyf.jpg
    ├── img
    │   └── lyf.9125a01.jpg
    └── js
        ├── app.39ccc604caeb34166b49.js
        ├── manifest.b1ad113c36e077a9b54d.js
        └── vendor.0b8d67613e49db91b787.js
复制代码

如上,咱们能够看到这个 css 相对 图片 的路径的地址。

你要疑问了,这样的相对路径,咱们可使用 ../image/lyf.jpg 来进行调用呀。嗯,看上去能够,可是,若是是这样的话,在开发模式中又会出错了。

因此,仍是要用 '../static/image/lyf.jpg' 这样的路径方式来调用图片。

字体图标,js 文件等,都是这样的路数。不在赘述。

本文地址http://www.cnblogs.com/zhaowy/

版权声明:本文为原创文章,版权归 做者全部,欢迎分享本文,转载请保留出处!

相关文章
相关标签/搜索