大概有小半年没更新文章了,一直忙于公司的各种项目开发。期间也踩了不少坑,最近终于算是暂时忙完一个段落,有时间来继续写博客了。vue从零开始学系列?#22987;牽?#20043;前断断续续写了有三篇?#22987;牽?#20294;是内容不是很多,做项目的这半年多时间,也在带一些新人做开发。之前电脑里存的一些系列?#22987;牽?#22238;头去看,感觉缺少一些实战的内容。所以还是决定推翻重写之后再发出来给大?#20063;?#32771;。

之前发布的三篇?#22987;牽?#22823;概算是让对vue一点都不了解的童鞋能够配合vue-cli去快速构建一个vue的项目。从这篇文章开始,就进入实战阶段了。


定个小目标

其实很多时候我们在学习一个新的技术的时候,大多都停留在知识点,小demo的层次,一旦放到项目中,多少还是有些不会应用。所以这次我们就先定一个小目标,做一个任务清单应用,让自己的时间得到规划,并以此为基础,去扩展。?#27604;唬?#25972;个应?#27809;?#38656;要我们自己一步一步去实现。

那就先列一些功能点吧:

  1. 欢迎页面(根据每日不同时段展示不同的欢迎语和日期)
  2. 记录页面(分为进行?#23567;?#24050;完成、未完成三个列表,用于展示当前的任务状况。 进行中的任务可以进行状态变更)
  3. 添加页面(添加一些新任务)

先来看看我们要实现什么样的一个效果吧

欢迎页

编写第一个页面

既然小目标已经确定好了,那我们就开始编写第一个页面吧。在src目录下面创建我们小目标的相关目录与文件。修改之前的项目文件,这里我们将页面统一放到views文件夹下,在根据功能来划分不同模块(之前的demo页面写在了pages文件夹下,这里我们用不到之前的小demo了,可以删掉)。让我们得小目标在项目初级就有一个比较明显的层次结构。

?#25193;ぉ?src
│   ?#25193;ぉ?assets
│         ?#25193;ぉ?images   ---- 图片文件夹
│   ?#25193;ぉ?components
│   ?#25193;ぉ?router   ----- 路由文件夹
│        ?#25193;ぉ?routes ---路由配置文件夹
│        ?#25193;ぉ?index.js
│   ?#25193;ぉ?views    ------ 视图层
│       ?#25193;ぉ? todo  ---- 任务模块
│       │   ?#25193;ぉ? add.vue ---- 新建任务
│       │   ?#25193;ぉ?  list.vue  ----- 任务列表
│       └── index.vue   ---- 欢迎页

打开index.vue页面,这个页面我?#21069;?#23427;定位欢迎页,接着我们编写以下内容(html和css的知识大家自己学习,这里默认为大家都有html、css的基础)。

<template>
 <div class="index">
  <img class="index-bg" src="../assets/images/banner.jpg">
  <div class="index-topbox">
   <div class="index-topbox-radius">
    <div class="index-topbox-text">
     <h3>下午好</h3>
     <p>
      <span>May.</span><span>14</span><span>Mon</span><span>2018</span>
     </p>
    </div>
   </div>
  <router-link class="button button-error" :to="{ name: 'todoList' }">Do it</router-link>
  <span class="tip">习惯就是人生的最大指导</span>
  </div>
 </div>
</template>
<scrpt>
 export default {
  data () {
     return {}
    }
 }
</script>
<style>
.index, .index .index-topbox {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}
.index>img.index-bg {
    width: 100%;
    height: 100%;
}
.index .index-topbox{
    position: absolute;
    background: rgba(206, 202, 202, 0.2);
}
.index .index-topbox-radius{
    margin: 3rem auto 0;
    width: 5.5rem;
    height: 5.5rem;
    border-radius: 50%;
    border: .08rem solid rgba(255, 255, 255, 0.5);
}
.index .index-topbox .index-topbox-text {
    margin-top: 1.4rem;
    margin-left: 1.4rem;
    width: 2.7rem;
    height: 2.7rem;
}
.index .index-topbox h3 {
    padding: .25rem 0;
    font-family: "宋体";
    font-size: .75rem;
    color: #fff;
    text-align: center;
    letter-spacing: .1rem;
}
.index .index-topbox .button-error {
    display: block;
    margin: .8rem auto 0;
    width: 2.7rem;
    height: .7rem;
    line-height: .7rem;
    border-radius: .7rem;
    box-shadow: 1px -1px #ff1a1a;
    font-size: .34rem;
    color: #fff;
}
.index .index-topbox p {
    padding: .15rem 0;
    border-top: .02rem solid #fff;
    border-bottom: .02rem solid #fff;
    font-size: .24rem;
    text-align: center;
    color: rgba(255, 255, 255, 0.7);
}
.index .index-topbox p span {
    margin-right: .05rem;
}
.index .index-topbox span.tip {
    padding: 0 .25rem;
    margin-top: 1.2rem;
    display: block;
    font-size: .22rem;
    color: rgba(255, 255, 255, 0.8);
    text-align: center;
}
.index .index-topbox p span:last-child {
    margin-left: .1rem;
    color: #fff;
}
</style>

这样,欢迎页的大概布局就出来了,接下来我们就该写功能了,我们希望在下午好的这个地方,根据打开页面的当前时间去展示不同的问候。在日期上面展示英文的缩写(别问为啥用英文,因为逼格高)然后在最下面展示一条随机的名人名言。点击按钮的时候,能够进入任务列表页面。

ok,在正式编写功能之前,希望你先对vue的整个生命周期有一个初步了解,因为网上关于生命周期的详解有不少了,这里就不多做赘述,直接挂链接vue生命周期,如果你对vue的生命周期有过了解,那我们接着往下看。

首先我们来写日期转换的函数,通过获取当前时间和我们预设好的数组,获取日期格式。

data () {
 return {
  date: {
   year: '',
   month: '',
   week: '',
   day: ''
  }
 }
},
methods: {
 setDate () {
  const now = new Date()
    const Month = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Spt', 'Oct', 'Nov', 'Dec' ]
    const Week = [ 'MON', 'TUSE', 'WED', 'THUR', 'FRI', 'SAT', 'SUN' ]
    this.date.month = Month[now.getMonth()] + '.'
  this.date.day = now.getDate()
  this.date.week = Week[now.getDay() - 1]
  this.date.year = now.getFullYear()
 }
}

在vue中,方法一般写在methods里面,我们将转换好的日期通过this.data的方式赋值给data,然后就可以通过{{}}双括号的?#38382;劍?#23637;示到模板里了。

<div class="index-topbox-text">
 <h3>下午好</h3>
 <p>
  <span>{{ date.week }}</span><span>{{ date.day }}</span><span>{{ date.month }}</span><span>{{ date.year }}</span>
 </p>
</div>

然后,我们希望这个函数在一进入页面就执行,通过前面生命周期的了解,我?#21069;?#23427;放入created方法里。(这里我给setDate包了一层init方法用作初始化)

created () {
 this.init()
},
methods: {
 init () {
  this.setDate()
 }
}

接下来我们通过同样的方式处理欢迎语和经典语句(记得同样加到init方法里面,或created方法里)

setWelcomeWord () {
 const now = new Date()
 const hh = now.getHours()
 const time = [ 3, 6, 8, 11, 13, 17, 19, 23 ]
 const text = [ '深夜咯', '早上好', '上午好', '中午好', '下午好', '日暮里', '晚上好', '夜深了' ]
 time.map((item, index, arr) => {
  if (arr[0] <= hh && hh <= arr[arr.length - 1]) {
   if (item <= hh && hh <= arr[index + 1]) {
    this.welcomeWord = text[index]
   }
  } else {
   this.welcomeWord = text[arr.length - 1]
  }
 })
},
setTips () {
 const now = new Date()
 const tips = [
  '习惯就是人生的最大指导',
  '我们坚持一件事情,并不是因为这样做了会有效果,而是坚信,这样做是对的',
  '凡不能杀死你的,终使你更加强大',
  '要从容地着手去做一件事,但一旦开始,就要坚持到底',
  '向着某一天终于要达到的那个终极目标迈步还不够,还要把每一步骤看成目标,使它作为步骤而起作用',
  '一个人只要强烈地坚持不懈地追求,他就能达到目的',
  '要在这个世界上获得成功,就必须坚持到底:?#20102;?#37117;不能放手'
 ]
 this.tips = tips[now.getDay() - 1]
}

在设置提示语的时候,我们使用了map方法去遍历time数组,说起循环来,JS中的循环方法还是蛮多的,感兴趣的童鞋可以去参考小萌写的JS 循环遍历方法的对比一文。

这样下来,欢迎页的页面部分我们就完成了,但是如何才能看到我们的页面呢?调整我们的router路由文件夹

?#25193;ぉ?src
│   ?#25193;ぉ?router   ----- 路由文件夹
│        ?#25193;ぉ?routes  ----- 路由配置文件夹
│             ?#25193;ぉ?routes.js
│             ?#25193;ぉ?todo.js
│        ?#25193;ぉ?index.js

打开routes.js文件,写入以下内容

import App from '../../App.vue'
const Index = resolve => require.ensure([], () => resolve(require('../../views/index.vue')), 'index')
import ToDo from './todo.js'

export const appRouter = [ // 定义我们的主应用路由
 { path: '', name: 'index', component: Index },
 {
  path: '/todo',   // 路径
  component: App,  // 页面使用的模板
  children: [  // 子路由
   ...ToDo
  ]
 }
]

export const routes = [ // 将路由暴露出去
 ...appRouter
]

我们通过定义路由的方式,来配置我们应用的页面访?#23454;?#22336;,最后我们将配置好的路由暴露出去。这里需要注意的是

import App from '../../App.vue'
// require.ensure 是webpack的特殊语法,用来设置code-split point  最后面的参数'index' 意思是代码分块(chunk)
const Index = resolve => require.ensure([], () => resolve(require('../../views/index.vue')), 'index')

这个语法跟我们引入app.vue文件不同,他们有什么区别呢?我们在前面的?#22987;?#20013;说过,Vue的项目其实是单页面应用,可以避免页面跳转过程中的白屏现象,但是由于是单页面应用,所以所有的文件都会在一进入应用中就全?#32771;?#36733;,如果资源很大,首页响应就会很慢,导致首页白屏现象。于是我们通过懒加载的模式,让应用只有进入到对应页面时,才加载相关资源,达到优化的效果。

这里我们结合Vue的异?#38454;?#20214;和webpack的code splitting feature,把路由对应的组件定义成异?#38454;?#20214;,这里我们只需要明白这?#20174;?#23601;可以实现路由懒加载就好了。

同理,我们将todo.js的路由也编写好。

const ToDoList = resolve => require.ensure([], () => resolve(require('../../views/todo/list.vue')), 'todoList')

export default [
  { path: '/list', name: 'todoList', meta: { title: '任务列表' }, component: ToDoList }
]

最后我们在router/index.js中配置路由并在main.js中引用:

//index.js
import Vue from 'vue'
import Router from 'vue-router'
import {routes} from './routes/routes.js'

Vue.use(Router)

const RouterConfig = {
 routes
}
export const router = new Router(RouterConfig)

//main.js
import Vue from 'vue'
import App from './App.vue'
import {router} from './router/index.js'  // 引入路由
import './assets/css/global.css'  // 引入全局样式
import './assets/css/animate.css' // 引入css动画

Vue.config.productionTip = false

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

接着让我们在todo/list.vue中,加点文字

<!-- 任务列表页面 -->
<template>
 <div class="">
  任务列表
 </div>
</template>

OK,到这里我们小目标的第一个页面就完成啦。回顾一下这篇?#22987;?#30340;内容,消化一下吧。

  1. vue的生命周期以及数据渲染的方式
  2. map循环函数
  3. 定于路由
  4. 路由懒加载