安装 nodejs 环境
node下载:nodejs 官方网站
在安装好了 nodejs 之后,我们在终端中输入以下两个命令:
node -v
npm -v
若能够得到如上图的版本号信息,则说明 nodejs 环境已经安装完成了。
检查本地npm版本:npm -v,如果版本太低可以通过:npm install -g npm进行升级。
全局安装vue-cil
vue-cil是vue的脚手架工具。命令如下:
npm install -g vue-cli
这个命令只需要运行一次就可以了。安装上之后,以后就不用安装了。
安装完成后,我们在终端中输入:
vue -V
如果输出如上图的版本号信息,则代表你安装正确。
全局安装webpack
若没有安装webpack,则输入以下命令行进行npm安装
npm install webpack -g
vue-cil构建项目
用 vue-cli 构建一个项目
下面,新建一个自己的vue项目:
vue init webpack vuedemo
项目名称是不是 vuedemo ,按回车,表示,是。当然,你也可以重写一个,然后回车。
Project name vuedemo ? Yes是不是一个 vue.js 的项目。同样,我们可以填写内容,或者直接回车
Project description A Vue.js project ? Yes作者姓名,直接回车 ,或自己输入也行
Author ? Yes这里是问你,需要不需要安装编译器,我们选择需要安装,也就是第一个,也就是直接回车就OK了。
Vue build standalone ? Yes问是不是需要安装 vue-router ,需要安装,这个是管理路由的。我们直接回车。
Install vue-router? Yes是否需要使用 ESLint 来检查你的代码。需要!所以同上,我们直接回车或N。
Use ESLint to lint your code? No是否需要安装测试功能。不要。我们输入 n 然后回车。
Set up unit tests No ?还是关于测试的内容,我们还是输出 n 然后回车。
Setup e2e tests with Nightwatch? No
如下图:
接下来
根据图上的提示,继续
cd vuedemo
npm run dev
就可以启动项目了。在浏览器里面打开localhost:8080,页面如下:
这时的目录是这样的
node_modules已经存在,就不需要npm install。
没有install的话,还是需要npm install,再运行的,如:
cd vuedemo
npm install
npm run dev
其中, npm install 因为需要联网,并且是去连 github ,如果你没有翻墙的话,可能速度会比较慢。我们可以使用国内淘宝提供的 npm 镜像源来进行安装,解决翻墙的问题。
安装方法
npm install -g cnpm --registry=https://registry.npm.taobao.org
更多内容,请参考 cnpm 官方网站: https://npm.taobao.org/
standard 标准风格规范说明
我们在上面安装了代码校验,并且采用了 standard 标准风格规范。
规范官方 github 仓库地址:https://github.com/feross/standard
缩进使用两个空格。
字符串使用单引号,用双引号只是为了避免转义单引号。
无未使用变量。这能帮助发现大量的错误。
不使用分号。这么做,没问题,真的!
行首不能是 ( ,[ 或 ` 。
这是省略分号时唯一陷阱—— standard 自动为你检查。
关键字后面放一个空格。if (condition) { … }
函数名字后面放一个空格。function name (arg) { … }
始终用 ===,不要用 ==。不过可以用 obj == null 检测 null || undefined。
始终处理 node.js 回调的 err 参数。
始终以 window 引用浏览器的全局变量。 document 和 navigator 除外。
这是为了防止使用浏览器那些命名糟糕的全局变量,比如 open, length, event 和 name。
认识项目所有文件
├── README.md // 项目说明文档
├── node_modules // 项目依赖包文件夹
├── build // 编译配置文件,一般不用管
│ ├── build.js
│ ├── check-versions.js
│ ├── dev-client.js
│ ├── dev-server.js
│ ├── utils.js
│ ├── vue-loader.conf.js
│ ├── webpack.base.conf.js
│ ├── webpack.dev.conf.js
│ └── webpack.prod.conf.js
├── config // 项目基本设置文件夹
│ ├── dev.env.js // 开发配置文件
│ ├── index.js // 配置主文件
│ └── prod.env.js // 编译配置文件
├── index.html // 项目入口文件
├── package-lock.json // npm5 新增文件,优化性能
├── package.json // 项目依赖包配置文件
├── src // 我们的项目的源码编写文件
│ ├── App.vue // APP入口文件
│ ├── assets // 初始项目资源目录,回头删掉
│ │ └── logo.png
│ ├── components // 组件目录
│ │ └── Hello.vue // 测试组件,回头删除
│ ├── main.js // 主配置文件
│ └── router // 路由配置文件夹
│ └── index.js // 路由配置文件
└── static // 资源放置目录
如上,就是我们的 vue 初始化后得到的一个项目的完整结构。其他大多数文件我们是不用管的
我们绝大多数的操作,就是在 src 这个目录下面。默认的 src 结构比较简单,我们需要重新整理。
另外 static 资源目录,我们也需要根据放置不同的资源,在这边构建不同的子文件夹。
配置 src 目录
把项目文件夹整理成如下的结构
├── App.vue // APP入口文件
├── api // 接口调用工具文件夹
│ └── index.js // 接口调用工具
├── components // 组件文件夹,目前为空
├── config // 项目配置文件夹
│ └── index.js // 项目配置文件
├── frame // 子路由文件夹
│ └── frame.vue // 默认子路由文件
├── main.js // 项目配置文件
├── page // 我们的页面组件文件夹
│ ├── content.vue // 准备些 cnodejs 的内容页面
│ └── index.vue // 准备些 cnodejs 的列表页面
├── router // 路由配置文件夹
│ └── index.js // 路由配置文件
├── style // scss 样式存放目录
│ ├── base // 基础样式存放目录
│ │ ├── _base.scss // 基础样式文件
│ │ ├── _color.scss // 项目颜色配置变量文件
│ │ ├── _mixin.scss // scss 混入文件
│ │ └── _reset.scss // 浏览器初始化文件
│ ├── scss // 页面样式文件夹
│ │ ├── _content.scss // 内容页面样式文件
│ │ └── _index.scss // 列表样式文件
│ └── style.scss // 主样式文件
└── utils // 常用工具文件夹
└── index.js // 常用工具文件
因为我们删除了一些默认的文件,所以这个时候项目一定是报错的,先不管他,我们根据我们的需求,新建如上的项目结构。这些都是在 src 目录里面的结构。
配置 static 目录
├── css // 放一些第三方的样式文件
├── font // 放字体图标文件
├── image // 放图片文件,如果是复杂项目,可以在这里面再分门别类
└── js // 放一些第三方的JS文件,如 jquery
你可能很奇怪,我们不是把样式和 JS 都写到里面去么,为什么还要在这边放呢?
因为,如果是放在 src 目录里面,则每次打包的时候,都需要打包的。这回增加我们的打包项目的时间长度。而且,一些地方放的文件,我们一般是不会去修改的,也没必要 npm 安装,直接引用就好了。你可以根据自己的情况,对这些可以不进行打包而直接引用的文件提炼出来,放在资源目录里面直接调用,这样会大大的提高我们的项目的打包效率。
全局引用ElementUI
npm安装:
npm i element-ui -S
安装完成后,完整引入element-ui,
在 main.js 中写入以下内容:
import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import App from './App.vue';
Vue.use(ElementUI);
new Vue({
el: '#app',
render: h => h(App)
});
安装字体包fontawesome
npm 安装 font-awesome:
npm install font-awesome
然后在main.js 文件中引入
import 'font-awesome/css/font-awesome.css'
调整 App.vue 和 router 路由
调整 App.vue 文件
我们先把默认项目里面没用的东西先删除掉,把代码调整为下面的样子。
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'app'
}
</script>
<style lang="scss">
@import "./style/style";
</style>
入口,只有一个空的路由视窗,我们的项目的所有内容,都基于这个视窗来展现。
我们的样式,都将从 src/style/style.scss 这个文件中引用,因此,在 App.vue 这个文件中,直接引用 ./style/style 即可。
好,调整好了我们的 App.vue 文件后,因为我们使用了 scss 文件预编译,所以我们需要安装两个支持 scss 的 npm 包。
我们在项目终端内输入下面的两句命令来进行安装:
npm install sass-loader -D
npm install node-sass -D
调整 index.vue 和 content.vue 文件
昨天,我们在 page 文件夹下面建立了两个空文本文件 index.vue 和 content.vue 文件,是我们准备用来放列表和内容的。
这里,我们先去填写一点基础内容在里面。
index.vue
<template>
<div class="index-wrap">
<el-container>
<el-aside><navMenu></navMenu></el-aside>
<el-container id="el-container">
<el-header><my-header></my-header></el-header>
<el-main>
<router-view></router-view>
</el-main>
<el-footer><my-footer></my-footer></el-footer>
</el-container>
</el-container>
</div>
</template>
<script>
import myHeader from '../components/Header'
import myFooter from '../components/Footer'
import navMenu from '../components/NavMenu'
export default {
name: "Index" ,
components: {
myHeader, myFooter, navMenu
}
}
</script>
Header.vue
<template>
<div class="header" id="Header">
This is my Header
</div>
</template>
<script>
export default {
name: "Header"
}
</script>
<style scoped>
</style>
Footer.vue
<template>
<div class="footer" id="Footer">
This is my Footer
</div>
</template>
<script>
export default {
name: "Footer"
}
</script>
NavMenu.vue
<template>
<div class="nav-menu">
This is my NavMenu
</div>
</template>
<script>
export default {
name: "NavMenu"
}
</script>
Content.vue
<template>
<div>
This is my Content
</div>
</template>
ContentList.vue
<template>
<div>
This is my ContentList
</div>
</template>
调整 router 路由文件
在router/index.js调整路由
可以参考官方文档《动态路由匹配》
import Vue from 'vue'
import Router from 'vue-router'
import Index from '@/page/Index'
import Content from '@/page/Content'
import ContentList from '@/page/ContentList'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Index',
component: Index,
children: [
{
path: '/Content',
name: 'Content',
component: Content,
},
{
path: '/ContentList/:id',
name: 'ContentList',
component: ContentList,
}
]
}
]
})
配置 Axios api 接口调用文件
安装 axios 工具。执行下面的命令进行安装
npm install axios -D
还记得文中整理的系统结构吗?我们新建了一个 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 ,中文资料自行百度。
调整 main.js 绑定 api/index.js 文件
在main.js中,加入下代码
// 引用API文件
import api from './api/index.js'
// 将API方法绑定到全局
Vue.prototype.$api = api
这样,我们就可以在项目中使用我们封装的 api 接口调用文件了。
测试一下看看能不能调通
我们来修改一下 src/page/Content.vue 文件,将代码调整为以下代码:
<template>
<div>
This is my Content
</div>
</template>
<script>
export default {
created () {
this.$api.get('topics', null, r => {
console.log(r)
})
}
}
</script>
好,这里是调用 cnodejs.org 的 topics 列表接口,并且将结果打印出来。
我们在浏览器中打开控制台,看看 console 下面有没有输出入下图一样的内容。如果有的话,就说明我们的接口配置已经成功了。
好,如果你操作正确,代码没有格式错误的话,那么现在应该得到的结果是和我一样的。如果出错或者怎么样,请仔细的检查代码,看看有没有什么问题。
将接口用 webpack 代理到本地
我们可以注意到我们的 src/api/index.js 的第一句,就是:
// 配置API接口地址
var root = 'https://cnodejs.org/api/v1'
这里,我们将接口地址写死了。
配置 webpack 将接口代理到本地
好在,vue-cli 脚手架工具,已经充分的考虑了这个问题,我们只要进行简单的设置,就可以实现我们的目的。
我们打开 config/index.js 文件,找到以下代码:
dev: {
env: require('./dev.env'),
port: 8080,
autoOpenBrowser: true,
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {},
cssSourceMap: false
}
其中,proxyTable: {}, 这一行,就是给我们配置代理的。
根据 cnodejs.org 的接口,我们把这里调整为:
proxyTable: {
'/api/v1/**': {
target: 'https://cnodejs.org', // 你接口的域名
secure: false,
changeOrigin: false,
}
}
OK,我们这样配置好后,就可以将接口代理到本地了。
更多接口参数配置,请参考 https://github.com/chimurai/http-proxy-middleware#options
webpack 接口配置文档 https://webpack.js.org/configuration/dev-server/#devserver-proxy
重新配置 src/api/index.js 文件
好,上面已经代理成功了,但是我们的 src/api/index.js 文件,还是直接调用的人家的地址呢,我们要调整为我们的地址,调整如下:
// 配置API接口地址
var root = '/api/v1'
值得注意的事情是,配置完成后,是不会立即生效的,我们需要重启我们的项目。
我们按 ctrl + c 停止掉之前的服务,然后重新输入命令 npm run dev 重启项目,就可以了。
没有问题,数据过来了。
编辑Content.vue文件
<template>
<div>
<h1>this.is content</h1>
<ul>
<li v-for="item in list">
<time v-text="item.create_at"></time>
<router-link :to="'/ContentList/' + item.id">
{{ item.title }}
</router-link>
</li>
</ul>
</div>
</template>
<script>
export default {
name: "Content",
data(){
return {
list: []
}
},
created () {
this.getData()
},
methods: {
getData () {
let that = this
this.$api.get('topics', null, res => {
that.list = res.data
})
}
}
}
</script>
<style scoped>
</style>
css样式,我就不多说了,相信大家自己能搞定
如此,我们能得到以下的content页面:
写一个公用的时间处理工具函数
编写 src/utils/index.js 文件
直接给代码如下:
export default {
goodTime (str) {
let now = new Date().getTime()
let oldTime = new Date(str).getTime()
let difference = now - oldTime
let result = ''
let minute = 1000 * 60
let hour = minute * 60
let day = hour * 24
let month = day * 30
let year = month * 12
let _year = difference / year
let _month = difference / month
let _week = difference / (7 * day)
let _day = difference / day
let _hour = difference / hour
let _min = difference / minute
if (_year >= 1) {
result = '发表于 ' + ~~(_year) + ' 年前'
} else if (_month >= 1) {
result = '发表于 ' + ~~(_month) + ' 个月前'
} else if (_week >= 1) {
result = '发表于 ' + ~~(_week) + ' 周前'
} else if (_day >= 1) {
result = '发表于 ' + ~~(_day) + ' 天前'
} else if (_hour >= 1) {
result = '发表于 ' + ~~(_hour) + ' 个小时前'
} else if (_min >= 1) {
result = '发表于 ' + ~~(_min) + ' 分钟前'
} else {
result = '刚刚'
}
return result
}
}
在 main.js 中将我们的方法函数给绑定上。如下代码:
// 引用工具文件
import utils from './utils/index.js'
// 将工具方法绑定到全局
Vue.prototype.$utils = utils
然后,调整Content.vue代码:
<time v-text="$utils.goodTime(i.create_at)"></time>
如此,得到以下的content页面:
好,我们已经看到,时间已经搞的挺好的了。
再把内容页面渲染出来
编写内容页面ContentList.vue:
<template>
<div>
<h2 v-text="contentList.title"></h2>
<p>作者:{{contentList.author.loginname}} 发表于:{{$utils.goodTime(contentList.create_at)}}</p><hr>
<article v-html="contentList.content"></article>
<h3>网友回复:</h3>
<ul>
<li v-for="item in contentList.replies">
<p>评论者:{{item.author.loginname}} 评论于:{{$utils.goodTime(item.create_at)}}</p>
<article v-html="item.content"></article>
</li>
</ul>
</div>
</template>
<script>
export default {
name: "ContentList",
data () {
return {
id: this.$route.params.id,
contentList: {}
}
},
created () {
this.getData()
},
methods: {
getData () {
this.$api.get('topic/' + this.id, null, res => {
this.contentList = res.data
})
}
}
}
</script>
<style scoped>
</style>
好,我们这边把代码写进 src/page/content.vue 文件。然后保存,我在我们先前的列表页面随便点开一篇文章,然后我们看下结果:
好,按照我们的需求已经渲染出来了。
打包项目并发布到子目录
然后运行如下代码,进行打包:
npm run build
运行结果如下:
好,我们已经打包好了。文件打包位置于项目目录里面的 dist 文件夹内。
但是,我们从上图可以看到,我们生成了一些 .map 的文件。当我们的项目变得比较大的时候,这些文件,第一个是,非常大,第二个,编译时间非常长。所以,我们要把这个文件给去掉。
去掉 map 文件
我们编辑 /config/index.js 文件,找到其中的
productionSourceMap: true,
修改为:
productionSourceMap: false,
然后我们重新运行打包命令:
npm run build
好,我们看下运行结果:
没用的 map 文件已经没有了。
好,我们可以从上图中看出,有一个 tip 。它告诉我们,打包出来的文件,必须在 http 服务中运行,否则,不会工作。
安装 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
第一条命令是追加环境变量,第二个命令是,使我们的追加立即生效。
好,一个插曲结束。
忘记了我们要干嘛了吗?我们要把我们打包出来的东西跑起来呀!
cd dist
http-server -p 8080
如果你是严格按照我的教程来的,那么现在已经可以顺利的跑起来了。我们在浏览器中输入 http://127.0.0.1:3000 就应该可以访问了。
当然,会报错,说是接口找不到,404错误。因为我们把接口给通过代理的方式开启到了本地,但是这里我们并没有开启代理,所以就跑不起来了。很正常的。
这是因为示例的接口的问题。实际开发你还要按照我的这个做。只不过,最终代码放到真实的服务器环境去和后端接口在一个 http 服务下面的话,就不存在这个问题了。
好,我们就跑起来了。
将项目打包到子目录
刚刚,我们是将文件,打包为根目录访问的。也就是说,必须在 dist 文件夹下面启动一个服务,才能把项目跑起来。
但是我们开发的大多数项目,可能是必须跑在二级目录,甚至更深层次的目录的。怎么做呢?
我们编辑 config/index.js 文件,找到:
assetsPublicPath: '/',
把 ‘/’ 修改为你要放的子目录的路径就行了。这里,我要放到 /dist/ 目录下面。于是,我就把这里修改为
assetsPublicPath: '/dist/',
有些人,在config/index.js中,改为assetsPublicPath: ‘/dist/’,
打包后使用http-server运行项目时,浏览器就会报404错误;
但是将assetsPublicPath: ‘/dist/’改为assetsPublicPath: ‘./’,重新打包后就可以正常访问了
然后,重新运行
npm run build
进行打包。
很快,就打包好了。
还记得,我们在项目文件夹中用 npm run dev 就可以开启一个 http 服务吗?并且那里,我们还代理了接口的。
然后我们访问二级目录 /dist/ 我们就可以看到效果了。
注意,我访问的不是根目录,而是 /dist/ 这个子目录哦,这里是访问的我们打包的文件的。
├── index.html
└── static
├── css
│ └── app.d41d8cd98f00b204e9800998ecf8427e.css
└── js
├── app.8ffccad49e36e43a4e9b.js
├── manifest.7a471601ff5a8b26ee49.js
└── vendor.057dd4249604e1e9c3b5.js
好,到这里,我们的打包工作,就讲完了。
实际开发中,你只需要把 dist 文件夹中打包好的文件,给运维他们,让他们去部署到真实的服务器环境就好了。
关于项目打包时,图片等资源的处理,
请查看本博文参考的原作者的博文 http://blog.csdn.net/fungleo/article/details/77799057
本文有参考https://blog.csdn.net/fungleo/article/details/53171052
版权声明:本文由 LuviaWu参考修改作为原创,允许转载,但转载必须保留首发链接。