1. 初始化项目
命令行安装vue-cli
sudo npm i -g vue-cli
sudo vue init webpack blog-client
//添加webpack模版
//一直按回车,只有在vue-router那是yes,其他都no
然后多出来一个目录blog-client,cd进入这个目录,运行npm run dev
这样会根据当前配置开启一个server,在浏览器进入这个server地址
2. 小技巧
- 在style里写scoped,则这个css只对当前组件生效
<style scoped src="./template.css"></style>
- 使用less,要在css里写lang="less"
并且要安装less-loader,在命令行<style scoped lang="less" src="template.less"></style>
npm i --save less-loader
- 命令行
npm start
,启动server - 由于header和footer都是一样的,所以直接将这两个组件放入App.vue里。而header和footer作为组件写在src里的components里
- 将一些公共样式写在assets目录里,其他文件通过
@import "./assets/common.less";
引用 - 跳转页面的方法
<router-link to="/login">登陆</router-link>
,this.$router.push({path :'/login'})
- 分页用element-ui的分页组件
-
<section class="article" v-html="markdown"></section>
,这样section里的html就是markdown这个计算属性里的东西 - 自创一个vue辅助插件,计算文章发布时间
在helpers目录里创建一个until.js,并在里面写个函数(friendlyDate)
导入时需要在main.js里写export default { install(Vue,options){ Vue.prototype.friendlyDate = friendlyDate } }
这样可以直接在外面用friendlyDate函数了import until from '@/helpers/until' Vue.use(until)
- 将Date.getTime()变为几分钟前
function friendlyDate(dateStr) { let dateObj = typeof dateStr === 'object' ? dateStr : new Date(dateStr) let time = dateObj.getTime() let now = Date.now() let space = now - time let str = '' switch (true){ case space < 60000: str = '刚刚' break case space < 1000*3600: str = Math.floor(space/60000) + '分钟前' break case space < 1000*3600*24: str = Math.floor(space/(1000*3600)) + '小时前' break default: str = Math.floor(space/(1000*3600*24)) + '天前' } return str }
- 将date变成年月日
splitDate(dateStr){
let dateObj = typeof dateStr === 'object' ? dateStr : new Date(dateStr)
return {
date: dateObj.getDate(),
month: dateObj.getMonth() + 1,
year: dateObj.getFullYear()
}
},
- 代码发布到GitHub的时候,只需将dist目录里的代码上传即可,所以可以在package.json里的"scripts"属性里添加一项
"scripts": {
"upload": "npm run build; cd dist; git init; git add .; git commit -m \"init\"; git remote add origin git@github.com:Pengyize/vue-blog.git; git push -f origin master;"
}
这样更新上传只需npm run upload
3. ElementUI组件
首先npm i element-ui -S
然后在main.js里引用
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
因为在build目录的webpack.base.conf.js文件写了
entry: {
app: './src/main.js'
},
整个项目的入口是src目录里的main.js。
引用完成后,直接用element-ui官网里的组件即可
4. 添加axios
先用npm安装,然后在src目录下创建helpers目录并在里面创建request.js文件引用import axios from 'axios'
,并且设置响应头(Content-Type)、baseUR和withCredentials(是否带上cookie)
import axios from 'axios'
import { Message } from 'element-ui'
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'
axios.defaults.baseURL = 'http://blog-server.hunger-valley.com' //默认url
axios.defaults.withCredentials = true //是否发送cookie
export default function request(url, type = 'GET', data = {}) {
return new Promise((resolve, reject)=>{
let option = {
url,
method: type
}
if(type.toLowerCase() === 'get'){
option.params = data //这是axios文档里要求的,get和post不同
}else{
option.data = data ////这是axios文档里要求的,get和post不同
}
axios(option).then(res =>{
console.log(res.data)
if(res.data.status === 'ok'){
resolve(res.data)
}else{
Message.error(res.data.msg)
reject(res.data)
}
}).catch(err=>{
Message.error('网络异常')
reject({msg:'网络异常'})
})
})
}
5. 封装后端api
在src里创建api目录,在里面创建auth.js(用户操作有关的api)和blog.js(博客操作有关api)
//auth.js
//request是封装的axios
import request from '@/helpers/request'
//URL是后端告诉的
const URL = {
REGISTER: '/auth/register',
LOGIN: '/auth/login',
LOGOUT: '/auth/logout',
GET_INFO: '/auth'
}
export default {
register({username,password}){
return request(URL.REGISTER,'POST',{username,password})
},
login({username,password}){
return request(URL.LOGIN,'POST',{username,password})
},
logout(){
return request(URL.LOGOUT)
},
getInfo(){
return request(URL.GET_INFO)
}
}
6. grid布局
7. 添加vuex
1. 安装及引用
npm install --save vuex
在src目录里创建store目录,并在里面的index.js写
import Vue from 'vue'
import Vuex from 'vuex'
import auth from './module/auth' //写相应用户的操作
import blog from './module/blog' //写相应博客的操作
Vue.use(Vuex)
export default new Vuex.Store({
modules:{
auth,
blog
}
})
2. 在其他文件用vuex
//引入
import {mapGetters,mapActions} from 'vuex'
export default {
methods:{
...mapActions([
'isLogin', //引入action里的方法
'logout'
])
},
onLogout(){
this.logout() //调用上面引入的logout方法
}
}
3. 使用action的两种方法
- 在methods里导入
methods:{
...mapActions([
'isLogin', //引入action里的方法
'logout'
]),
onLogout(){
this.logout()
}
- 直接用store.dispatch('checkLogin')
4. vuex的作用
- 把user信息和isLogin(是否登陆)放在store(仓库)的state里
- 把登陆、注销等操作放在action里,当登陆或注销时,action就用commit调用mutation里的方法来实时更新用户登陆、注销的状态
- 这样所有页面都通过vuex获取用户是否在线的信息
8. 完善路由
-
添加路由元信息
在需要检验的路由里添加一项meta属性
{
path: '/create',
component: Create,
meta: {requiresAuth:true}
}
然后在下面加上
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
store.dispatch('checkLogin').then(isLogin=>{
if (!isLogin) {
next({
path: '/login',
query: { redirect: to.fullPath }
})
} else {
next()
}
})
} else {
next() // 确保一定要调用 next()
}
})
这样加了meta的路由,每次进入的时候都会先执行这个函数
9. webpack打包
运行npm run build
会在dist目录下的static目录里打包,打包后直接浏览static目录里的index.html就是项目
10. 懒加载
把路由写成这样
const router = new Router({
routes: [
{
path: '/',
component: ()=> import('@/pages/Index/template.vue')
},
{
path: '/create',
component: ()=> import('@/pages/Create/template.vue'),
meta: {requiresAuth:true}
},
{
path: '/detail/:blogId',
component: ()=> import('@/pages/Detail/template.vue')
},
{
path: '/edit/:blogId',
component: ()=> import('@/pages/Edit/template.vue'),
meta: {requiresAuth:true}
},
{
path: '/my',
component: ()=> import('@/pages/My/template.vue'),
meta: {requiresAuth:true}
},
{
path: '/register',
component: ()=> import('@/pages/Register/template.vue')
},
{
path: '/user/:userId',
component: ()=> import('@/pages/User/template.vue')
},
{
path: '/login',
component: ()=> import('@/pages/Login/template.vue')
}
]
})
这样只有访问到当前页面时才会加载那个页面的js,加快了用户访问页面的速度,之前是一次性加载所有网页
11. 用query保留当前浏览的页面
用element-ui的分页组件
<el-pagination
layout="prev, pager, next"
:current="page"
@current-change="onPageChange"
:total="total">
</el-pagination>
onPageChange这个函数传的第一个参数是当前页面数,所以如下
onPageChange(newPage){
this.$router.push({path: '/', query: {page: newPage}})
}
这样将当前page数加入到url的查询参数里,然后在created
created(){
this.page = parseInt(this.$route.query.page) || 1
}
12. Detail页面获取当前blogId
是通过router里写的path
path: '/detail/:blogId'
所以可以通过下面这种方式获得id
this.$route.params.blogId
网友评论