vue

2018-06-10 Vue在线博客项目

2018-06-25  本文已影响78人  彭奕泽

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. 小技巧

  1. 在style里写scoped,则这个css只对当前组件生效
    <style scoped src="./template.css"></style>
    
  2. 使用less,要在css里写lang="less"
    <style scoped lang="less" src="template.less"></style>
    
    并且要安装less-loader,在命令行npm i --save less-loader
  3. 命令行npm start,启动server
  4. 由于header和footer都是一样的,所以直接将这两个组件放入App.vue里。而header和footer作为组件写在src里的components里
  5. 将一些公共样式写在assets目录里,其他文件通过@import "./assets/common.less";引用
  6. 跳转页面的方法<router-link to="/login">登陆</router-link>this.$router.push({path :'/login'})
  7. 分页用element-ui的分页组件
  8. <section class="article" v-html="markdown"></section>,这样section里的html就是markdown这个计算属性里的东西
  9. 自创一个vue辅助插件,计算文章发布时间
    在helpers目录里创建一个until.js,并在里面写个函数(friendlyDate)
    export default {
      install(Vue,options){
        Vue.prototype.friendlyDate = friendlyDate
      }
    }
    
    导入时需要在main.js里写
    import until from '@/helpers/until'
    
    Vue.use(until)
    
    这样可以直接在外面用friendlyDate函数了
  10. 将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
    }
    
  11. 将date变成年月日
splitDate(dateStr){
      let dateObj = typeof dateStr === 'object' ? dateStr : new Date(dateStr)
      return {
        date: dateObj.getDate(),
        month: dateObj.getMonth() + 1,
        year: dateObj.getFullYear()
      }
    },
  1. 代码发布到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:{
    ...mapActions([
      'isLogin',  //引入action里的方法
      'logout'
    ]),
    onLogout(){
      this.logout()
    }

4. vuex的作用

8. 完善路由

  1. 添加路由元信息
    在需要检验的路由里添加一项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

上一篇 下一篇

猜你喜欢

热点阅读