配置一个vue-cli3.0项目

谢谢你们指正,我以前分不清,vue3指的是vue3仍是vue-cli3,我这里讲的确实是vue-cli3,我这里订正下。以前router的代码是贴错了,也感谢网友的指正,已订正。javascript

至于评论里喷个人,本人声明下吧,本文只合适诚心学习交流的人观看,傻逼请略过。css

----分割线----html

如下是正文前端

提及来有点丢人,我已经使用vue很久了,可是怎么从0开始配置一个vue项目,每次仍是要百度。此次决定写个博客,增强下记忆,若是再记不住就直播本身的女友洗澡。vue

如下以新建一个图书管理项目为例。我使用vue3新建项目,对于建立一个项目来讲,vue3真的比vue2简单不少。java

1.初始化项目

1.1全局安装vue-cli

建立vue项目,首先要确保全局安装了vue命令行工具。node

我这边使用yarn而不用npm,由于yarn要比npm好用的多,强烈推荐使用。若是你们对yarn不熟悉,我这边免费赠送个人yarn教程。点击查看ios

yarn add global @vue/cli
复制代码

1.2 新建项目

使用vue-cli3开发项目,可使用图形化界面,也可使用命令行,还能够基于原型进行开发。我这里以常见的基于命令行的开发为例。git

我想在我D盘的test文件夹下新建一个图书管理项目,项目名叫book。执行以下命令便可。github

D:\test>vue create book
复制代码

这里能够选择咱们须要安装的预处理器preset。咱们能够直接选下图中的第一个选项,这样能够省去不少麻烦。不过这里为了讲解须要,咱们选择默认的(bable+eslint)。日后咱们再讨论怎么手动安装其余preset。我强烈建议你选择第一项,这样真的能够省去不少麻烦。

预处理器

程序执行完后,项目结构以下:

.
|-book
  |-babel.config.js
  |-package.json
  |-public
  |  |-favicon.ico
  |  |-index.html
  |-README.md
  |-src
  |  |-App.vue
  |  |-assets
  |  |  |-logo.png
  |  |-components
  |  |  |-HelloWorld.vue
  |  |-main.js
  |-yarn.lock
复制代码

将命令行路径设置为book项目所在的路径

D:\test>cd book
复制代码

启动项目

yarn serve
复制代码

执行完,我这边没有报错,就说明安装没有问题。

2.项目结构

vue已经给咱们新建了一个初始的项目结构,可是这个项目结构还不完善。咱们须要新建一下几个目录。新建的目录都是新建在src目录下。

  • views 用户存放咱们的页面
  • store 放置vuex程序
  • api 放置全部的接口程序
  • utils 放置工具函数(无关紧要)
  • router 放置路由信息
  • styles 放置全局样式(无关紧要)
  • components 这个已经有了,用来存放咱们页面中的组件。咱们能够直接把组件新建在components目录下,不过这样不太清晰,我喜欢在components目录下,再为每一个页面新建一个文件夹,把每一个页面的组件放在对应的文件下
  • assets 这个也已经有了,用来存放咱们的资源文件,视频、音频、图片等。

此时的目录结构以下:

|-book
  |-babel.config.js
  |-package.json
  |-public
  |  |-favicon.ico
  |  |-index.html
  |-README.md
  |-src
  |  |-api
  |  |-App.vue
  |  |-assets
  |  |  |-logo.png
  |  |-components
  |  |  |-HelloWorld.vue
  |  |-main.js
  |  |-router
  |  |-store
  |  |  |-index.js
  |  |-utils
  |  |-views
  |-yarn.lock
复制代码

3.项目介绍

咱们要讲解vue的使用,总的拿个项目练手。我就作一回产品经理,虚拟一个图书管理项目吧。咱们有2个页面。分别以下

  • 登陆页 ,用户输入帐号admin和密码admin,就跳转到咱们的首页
  • 首页,显示一些图书信息(我为了省事就不显示了)。

这个项目会涉及到那些操做呢:

  1. 点击跳转
  2. 请求
  3. 展现

所以处理,vue提供给咱们的组件外,咱们还须要手动添加一下这些组件

  • 路由组件:vue-router
  • 请求组件:axios mock
  • ui组件:element-ui sass
  • 表单验证组件:vee-validate
  • 状态:vuex js-cookie

好了如今咱们根据咱们的需求,一步步开发咱们的页面。

4. 开发项目

4.1 登陆页

  1. 在views文件夹下新建Login.vue、Index.vue 。这三个页面的代码大同小异,目前只是基本的代码,稍后还要修改。
<template>
  <!-- 这是login页面 -->
  <div>这里是login 页面</div>
  <!-- 这是index页面 -->
  <div>这里是index 页面</div>
</template>
<style> </style>
<script> export default { name: 'Login', data() { return { } }, } </script>

复制代码
  1. 修改src目录下的App.vue 文件。删掉#app文件里的内容,改成<router-view>,这里就是觉得显示其余组件的地方。删除script中的内容。修改后的App.vue代码以下:
<template>
  <div id="app">
    <router-view></router-view>
  </div>
</template>
<style> #app { font-family: "Avenir", Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>

复制代码

5.vue-router

使用vue开发任何一个项目都涉及都路由,因此咱们先讲解路由。这里须要安装的组件是vue-router

D:\test\book>yarn add vue-router
复制代码

在咱们刚刚新建的router文件夹下新建index.js文件,程序以下

import Vue from 'vue'
import Router from 'vue-router'
import Login from '../views/Login.vue'
import Index from '../views/Index.vue'
import Detail from '../views/Detail.vue'

Vue.use(Router)
const router = new Router({
  routes: [{
    path: '/',
    redirect: '/index'
  }, {
    path: '/login',
    name: 'Login',
    component: Login
  }, {
    path: '/index',
    name: 'Index',
    component: Index
  }, {
    path: '/detail',
    name: 'Detail',
    component: Detail
  }]
})

export default router
复制代码

修改main.js,引入咱们的路由。在第3行我引入了路由,在new Vue的时候还须要把router加进去了,这样才能正常使用路由。

import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false

new Vue({
  router,
  render: h => h(App),
}).$mount('#app')
复制代码

好了如今咱们能够访问咱们的页面了,忽略连接上的端口号,vue会根据你电脑端口的使用状况,自动选择一个合适的端口号,因此个人端口号可能跟你的不一样。

ok 自此咱们的路由配置成功。我这边访问页面是没有问题,若是你有问题,你就找下本身的错误在哪里。

6.element-ui

下面就进入咱们的页面开发模式,首先咱们要开发的是login页。咱们可使用原生的html开发,可是,效率低下,因此咱们仍是用vue组件吧。这里我以element-ui为例

安装

D:\test\book>yarn add  element-ui
复制代码

配置:在main.js中引入element

import Vue from 'vue'
import App from './App.vue'
import router from './router'
// 引入element-ui
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI)

Vue.config.productionTip = false

new Vue({
  router,
  render: h => h(App),
}).$mount('#app')
复制代码

修改Login.vue。

把代码修改为下面这样子后,咱们的表单就建完了。打开页面。发现咱们页面功能是有了,可是太丑了,表单占据了整个页面的宽度,所以咱们还要修改下样式。这里咱们就要用到sass

<template>
  <div class="login">
    <div class="l-form">
      <div class="l-tip">图书馆管理系统</div>
      <el-form ref="form" :model="form">
        <el-form-item>
          <el-input v-model="form.name"></el-input>
        </el-form-item>
        <el-form-item>
          <el-input v-model="form.password" type="password"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="onSubmit">登陆</el-button>
        </el-form-item>
      </el-form>
    </div>
  </div>
</template>

<script> export default { name: 'Login', data() { return { form: { name: '', password: '' } } }, methods: { onSubmit() { }, }, } </script>
<style> </style>

复制代码

7.sass

咱们能够直接用css的,可是我不推荐这样用,由于原生太丑了。咱们要使用css预处理器写css样式。css预处理器有sass和less,固然还有其余的可是我没用过。less我不推荐使用,由于功能不强、像自定义函数功能就没有,写代码特别别扭,我推荐sass。

安装sass

D:\test\book>yarn add node-sass sass-loader
复制代码

vue-cli3 对sass简直是0配置,上面咱们安装好处理器后,直接在style标签上加上lang="scss"就可使用sass了。

修改Login.vue中的style

<style lang="scss"> .login { width: 100%; height: 100%; background: #000; .l-form { position: fixed; top: 50%; left: 50%; transform: translateY(-50%) translateX(-50%); width: 300px; margin: auto; border-radius: 8px; background: #fff; padding: 20px; .l-tip { text-align: center; font-size: 24px; font-weight: bold; } .el-form { width: 100%; margin: auto; margin-top: 20px; .el-form-item { button { width: 100%; } } } } } </style>

复制代码

样式跟咱们想要的还有点差异,这是是由于父元素的样式问题引发的,修改App.vue中的style。主要是给html,body还有#app元素设置了宽和高和边距。

<template>
  <div id="app">
    <router-view></router-view>
  </div>
</template>


<style lang="scss"> html, body, #app{ width: 100%; height: 100%; margin: 0px; padding: 0px; } </style>

复制代码

再打开浏览器,看咱们的页面,已经很好看了。页面长下面这样。

登陆页

8.normalize.css

安装normalize.css 其实这个安不安装均可以,我是有强迫症就安装了。

安装

yarn add normalize.css
复制代码

修改main.js引入normalize.css。

配置

import 'normalize.css'
复制代码

9.axios

咱们在登陆页要登陆,这就涉及到了发ajax请求,这个咱们使用axios

安装

D:\test\book>yarn add axios
复制代码

使用

在api文件夹下新建config.js文件,配置一些请求的通用选项,同时还对gei和post请求进一步封装。其实封装不封装都无所谓,我我的感受封装后会省事一点。代码以下:

import axios from "axios"
import { Message } from "element-ui"

// 这个baseUrl要根据实际状况进行改变
axios.defaults.baseURL = "/"
axios.defaults.headers.common["Content-Type"] =
  "application/json; charset=UTF-8"
axios.defaults.headers.common["Access-Control-Allow-Origin"] = "*"

// 请求拦截器 添加token
axios.interceptors.request.use(
  config => {
    return config
  },
  error => {
    return Promise.reject(error)
  }
)

// 响应拦截器即异常处理
axios.interceptors.response.use(
  response => {
    return response
  },
  error => {
    Message({
      message: error.message,
      type: "error",
      duration: 5000,
    })
    return Promise.resolve(error)
  }
)

export default {
  // get请求
  get(url, param) {
    return new Promise((resolve, reject) => {
      axios({
        method: "get",
        url,
        params: param,
      })
        .then(res => {
          resolve(res)
        })
        .catch(error => {
          Message({
            message: error,
            type: "error",
            duration: 5000,
          })
          reject(error)
        })
    })
  },
  // post请求
  post(url, param) {
    return new Promise((resolve, reject) => {
      axios({
        method: "post",
        url,
        data: param,
      })
        .then(res => {
          resolve(res)
        })
        .catch(error => {
          Message({
            message: error,
            type: "error",
            duration: 5000,
          })
          reject(error)
        })
    })
  },
  // all get
  allGet(fnArr) {
    return axios.all(fnArr)
  },
}

复制代码

在api的文件夹下新建login.js文件。这个函数的做用就是请求后台的login接口。

代码以下:

import service from './config'
class Login {
  login(params) {
    return service.post('login', params)
  }
}
export default new Login()
复制代码

axios不用特别配置的,引入就能够用。如今问题来了,有了接口了,可是咱们没有后台啊。咱们无法作登陆的功能。不过不用担忧,如今的咱们的前端已经很强大了。没有后端,咱们可使用mock来模拟后端。

10.设置eslint

在安装mock前,咱们还有一个小问题要解决,就是设置eslint的规则,默认的eslint的规则很严格的,咱们在页面甚至不能使用console.log() 这就会给咱们的调试带来困难。所以咱们要禁用一些eslint规则。

打开package.json,找到eslintConfig项,在找到其下的rules。配置"no-console": "off"。就能够关闭eslint对console的限制。

"eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/essential",
      "eslint:recommended"
    ],
    "rules": {
      "no-console": "off"
    },
    "parserOptions": {
      "parser": "babel-eslint"
    }
  },
复制代码

好了,如今咱们就能够愉快的在vue写console了。

11. mock

mock是啥呢?mock是一个测试工具。mock会拦截ajax请求并能够按照必定规则返回数据。之前须要后台返回给咱们的数据,如今咱们可使用mock返回了。mock的功能很强大,能够模拟出后端的增删改查等功能。很是方便咱们前端进行测试.

安装

D:\test\book>yarn add mockjs
复制代码

使用

在main.js的同级目录下新建mock.js。咱们在mock.js里定义刚刚咱们须要的login接口。代码以下:

import Mock from 'mockjs'

Mock.mock('/login', 'post', (options) => {
  // console.log('options:', options)
  let data = JSON.parse(options.body)
  let name = data.name
  let password = data.password
  if (name === 'admin' && password === 'admin') {
    return {
      status: 1,
      message: '登陆成功'
    }
  } else {
    return {
      status: 0,
      message: '帐号或者密码错误'
    }
  }
})
复制代码

这段代码的做用即便拦截login接口请求,当帐号和密码是admin的时候,就返回请求成功,不然返回‘帐号密码错误’

如今问题来了?咱们写好程序了,怎么使用mock呢,其实很是简单,简单到我都不敢相信。咱们直接在main.js文件中引入mock.js既可。

配置

在main.js中添加以下代码。

// 引入mock
import './mock.js'
复制代码

ok,如今再打开咱们的login页。输入帐号和密码。若是不是admin,则弹窗报错.

帐号密码错误

若是帐号密码正确,则跳转到index页面。

index页面

自此大致工做都完成了,接下来,咱们继续完成项目(好累)。

12.vee-validate

咱们的登陆表单还有个问题,就是怎么加验证。表单不验证,一来不容易发现问题,二来会频繁的骚扰后端。本身写验证也能够,可是每次都要重复写不少代码,键盘都受不了。so,仍是用组件吧,我使用的是vee-validate。

安装

yarn add vee-validate
复制代码

配置

在main.js中引入vee-validate

// 引入表单验证
import VeeValidate, {
  Validator
} from 'vee-validate'
Vue.use(VeeValidate, {
  fieldsBagName: 'vee-fields'
})

// 汉化表单验证
import zhCN from 'vee-validate/dist/locale/zh_CN'
Validator.localize('zh_CN',
  zhCN)
复制代码

修改login.vue 添加表单验证,以用户名为例,个人要求是用户名不能为空,添加的规则以下:

<el-input v-model="form.name" v-validate="{required:true}" name="name" :class="{'is-danger':errors.has('name')}" data-vv-as="用户名" placeholder="请输入用户名" ></el-input>
复制代码
  • v-validate 里配置的是验证规则
  • name 是字段名称,这个名称能够本身定
  • is-danger 是我为报错的字段配置的一个class名,若是erros.has(字段名)不为空,则说明验证没经过,就添加该class。

is-danger 样式以下,把错误表单的边框设置成红色,目的是为了突出显示错误信息。至于为何加/deep/前缀,是由于el-input组件是element组件,咱们在style中设置的样式是局部的,无法应用的到element子组件上,因此须要加上/deep/。需不须要加你本身视状况而定。

/deep/ .is-danger input {
  border-color: #ff3860;
}
复制代码

接下来,咱们要考虑错误信息怎么显示。个人作法是直接在表单下显示错误信息就能够,缺点是若是错误信息不少,每一个输入框都有一个错误信息的话,表单就会变得很高。

由于每一个输入框都要显示错误信息,因此我以为把显示错误信息的功能作成组件比较好,这样能够通用,省了不少重复代码。

在components文件夹下新建common文件夹,再在commen文件夹下新建FormErrorMessage.vue组件

代码以下:

<template>
  <div class="help is-danger">
    <slot></slot>
  </div>
</template>
<script> export default { name: 'FormErrorMessage' } </script>
<style scoped> .help { font-size: 0.75rem; margin-top: 0.25rem; line-height: 0.75rem; } .help.is-danger { color: #ff3860; } </style>

复制代码

在Login.vue中引入

import FormErrorMessage from '../components/common/FormErrorMessage.vue'
复制代码

在components中配置

name: 'Login',
  components: {
    FormErrorMessage
  },
  data() {
    return {
      form: {
        name: '',
        password: ''
      }
    }
  },
复制代码

使用

<el-form-item>
    <el-input v-model="form.name" v-validate="{required:true}" name="name" :class="{'is-danger':errors.has('name')}" data-vv-as="用户名" placeholder="请输入用户名" ></el-input>
</el-form-item>
<el-form-item>
    <FormErrorMessage v-if="errors.has('name')">{{ errors.first('name') }}</FormErrorMessage>
</el-form-item>
复制代码

表单验证添加了,错误显示的组件也添加了,如今只差怎么触发表单验证了。很简单,修改onSubmit函数,代码以下,若是result为true,则说明表单验证经过了,不然就是有错。

onSubmit() {
      this.$validator.validate().then(result => {
        if (result) {
          login.submit(this.form).then(res => {
            // console.log('res:', res);
            if (res.data.status === 1) {
              // 若是登陆成功则跳转我index页面
              this.$router.push('/index')
            } else {
              // 使用element-ui的message组件,显示登陆报错信息
              this.$message({
                message: res.data.message,
                type: 'error',
                duration: 5000
              })
            }
          }).catch(error => {
            this.$message({
              message: error,
              type: 'error',
              duration: 5000
            })
          })
        }
      })
    },
复制代码

添加错误提示后,表单样式还须要调整下,我就不调了,结果以下:

验证错误

完整Login.vue代码以下:

<template>
  <div class="login">
    <div class="l-form">
      <div class="l-tip">图书馆管理系统</div>
      <el-form ref="form" :model="form">
        <el-form-item>
          <el-input v-model="form.name" v-validate="{required:true}" name="name" :class="{'is-danger':errors.has('name')}" data-vv-as="用户名" placeholder="请输入用户名" ></el-input>
        </el-form-item>
        <el-form-item>
          <FormErrorMessage v-if="errors.has('name')">{{ errors.first('name') }}</FormErrorMessage>
        </el-form-item>

        <el-form-item>
          <el-input v-model="form.password" type="password" v-validate="{required:true}" name="password" :class="{'is-danger':errors.has('password')}" data-vv-as="密码" placeholder="请输入密码" ></el-input>
        </el-form-item>
        <el-form-item>
          <FormErrorMessage v-if="errors.has('password')">{{ errors.first('password') }}</FormErrorMessage>
        </el-form-item>

        <el-form-item>
          <el-button type="primary" @click="onSubmit">登陆</el-button>
        </el-form-item>
      </el-form>
    </div>
  </div>
</template>

<script> import login from '../api/login.js' import FormErrorMessage from '../components/common/FormErrorMessage.vue' export default { name: 'Login', components: { FormErrorMessage }, data() { return { form: { name: '', password: '' } } }, methods: { onSubmit() { this.$validator.validate().then(result => { if (result) { login.submit(this.form).then(res => { // console.log('res:', res); if (res.data.status === 1) { // 若是登陆成功则跳转我index页面 this.$router.push('/index') } else { // 使用element-ui的message组件,显示登陆报错信息 this.$message({ message: res.data.message, type: 'error', duration: 5000 }) } }).catch(error => { this.$message({ message: error, type: 'error', duration: 5000 }) }) } }) }, }, } </script>
<style lang="scss" scoped> .login { width: 100%; height: 100%; background: #000; .l-form { position: fixed; top: 50%; left: 50%; transform: translateY(-50%) translateX(-50%); width: 300px; margin: auto; border-radius: 8px; background: #fff; padding: 20px; .l-tip { text-align: center; font-size: 24px; font-weight: bold; } .el-form { width: 100%; margin: auto; margin-top: 20px; .el-form-item { button { width: 100%; } } } } } .is-danger input { border-color: #ff3860; } </style>

复制代码

13. js-cookie

原本接下来该讲vuex了,这里插播一个组件js-cookie

地址:js-cookie

安装

yarn add js-cookie
复制代码

至于这个怎么用,咱们稍后讲vuex的时候再讲解。

14.vuex

先在咱们终于讲到最后一个知识点vuex了。为何要用vuex,在本项目里,使用vuex是为了保持网站的登陆状态。好比咱们index页面要求用户必须登陆才可以访问,这里就要用vuex了。vuex实例化后叫store。

地址:vuex

安装

D:\test\book>yarn add vuex
复制代码

在store文件夹下,新建index.js文件

代码以下:

import Vue from 'vue'
import Vuex from 'vuex'
// 引入js-cookie
import Cookies from 'js-cookie'
Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    name: ''
  },
  mutations: {
    loginIn(state, name) {
      state.name = name
      // 设置过时时间为1天
      Cookies.set('name', name, {
        expires: 1
      })
    },
    loginOut(state) {
      state.name = ''
      Cookies.remove('name')
    }
  }
})
export default store
复制代码

咱们定义了一个loginIn方法,调用这个方法,咱们就能够把用户的用户名存在store中,同时也存在cookie里,cookie的有效期是1天。

配置

修改main.js,把store引入进去main.js中,而后在new Vue函数中配置

import store from './store/index.js'
……
new Vue({
  router,
  store,
  render: h => h(App),
}).$mount('#app')
复制代码

好啦,这时候咱们就能够愉快的使用store了。

修改Login.vueonSubmit方法,用户登陆成功后,就把用户信息存在store中。

if (res.data.status === 1) {
    // 将用户信息存储在vuex中
    this.$store.commit('loginIn', this.form.name)
    // 若是登陆成功则跳转我index页面
    this.$router.push('/index')
} else {
    ……
}
复制代码

修改Index.vue页面,咱们就能够在这个页面获取登陆用户的用户名了。

Index.vue代码以下:

<template>
  <div>这里是Index 页面,此时登陆的用户是{{userName}}</div>
</template>
<style> </style>
<script> export default { name: 'Index', data() { return { } }, computed: { userName() { return this.$store.state.name } }, } </script>

复制代码

自此,一个咱们经常使用vue项目基本上配置完成了。固然不一样的项目,还有不一样的组件须要安装,到时候大家再根据状况肯定吧。

最后再讲一个关于路由拦截的问题。

15.路由拦截

如今咱们的项目已经有登陆功能了,可是并无对用户进行限制。好比个人Index.vue页面要求只有登陆用户才能访问。这时该怎么办呢? 这就要用路由拦截了,凡是没有登陆的用户要访问Index.vue的时候,统一让他重定向到Login页面,让其登陆。

修改main.js。添加以下代码:

// 设置路由拦截
router.beforeEach((to, from, next) => {
  let name = Cookies.get('name') || store.state.name
  // 若是cookie没有过时或者store中有name值,则容许访问直接经过。不然就让用户登陆
  if (name) {
    store.commit('loginIn', name)
    next()
  } else {
    if (to.path == '/login') {
      next()
    } else {
      next({
        name: 'Login'
      })
      store.commit('loginOut')
    }
  }
})

router.afterEach(() => {})
复制代码

ok,如今咱们访问Index页面的时候就要求用户必须登陆了。

终于,终于关于配置一个vue.3.0项目的全部内容,大概讲完了。在写这篇博客以前,我还一直发愁该怎么讲,这么多内容。没想到一点点讲,终于把本身想讲的都讲完了。

固然我讲的都是简单的使用,入门而已。若是真的作项目还须要对每一个组件都深刻了解,好比element和mock和vee-validate。大家本身去研究吧。

为了方便查看代码,我把整个项目上传到了githubl了。整个项目的github地址以下:book