美文网首页vue
2018-06-10 Vue在线博客项目

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

作者: 彭奕泽 | 来源:发表于2018-06-25 23:43 被阅读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里导入
    methods:{
        ...mapActions([
          'isLogin',  //引入action里的方法
          'logout'
        ]),
        onLogout(){
          this.logout()
        }
    
    • 直接用store.dispatch('checkLogin')

    4. vuex的作用

    • 把user信息和isLogin(是否登陆)放在store(仓库)的state里
    • 把登陆、注销等操作放在action里,当登陆或注销时,action就用commit调用mutation里的方法来实时更新用户登陆、注销的状态
    • 这样所有页面都通过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

    相关文章

      网友评论

        本文标题:2018-06-10 Vue在线博客项目

        本文链接:https://www.haomeiwen.com/subject/smifeftx.html