vue项目搭建以及全家桶的使用详细教程

前言

vue是现阶段很流行的前端框架,不少人经过vue官方文档的学习,对vue的使用都有了必定的了解,但再在项目工程化处理的时候,却发现不知道改怎么更好的管理本身的项目,如何去引入一些框架以及vue全家桶其余框架的使用,如下将详细地介绍本人在处理工程文件构建的过程;对于刚开始解除vue的新手,建议使用官方脚手架vue-cli,固然,若是你对于webpack很熟悉,你也能够本身动手搭建本身的脚手架,固然若是你没把握的话,仍是推荐使用vue-cli,能更好的帮助你搭建项目:css

步骤1、安装vue-cli

首先,咱们能够经过npm安装vue-clic,前提是咱们须要有node环境,若是电脑还没安装node,先安装,可经过前端

node -v

查询node的版本号,有版本号则已经安装成功;vue

clipboard.png
接下来,咱们须要确保电脑已经安装了webpack,webpack是一个包管理工具,也是vue-cli的构建工具,安装也很简单,全局安装只须要执行node

npm install webpack -g

紧接着,开始咱们vue-cli的安装webpack

npm install --global vue-cli

查看是否安装成功,咱们能够经过在cmd中输入vue -V 查看,以下图出现版本号则说明安装已经完成;ios

clipboard.png

咱们能够打开c盘>用户>用户名>AppData>Roaming>npm查看咱们全局安装的vue-cli,以下图:web

clipboard.png

clipboard.png

步骤2、构建工程文件

安装完vue-cli后,咱们能够经过在cmd中输入vue-router

vue init webpack projectName

生成webpack脚手架,在咱们按下回车的时候,会出现一些提示问题,对应关系以下:vuex

  • 项目名称(注意名称中不要出现大写字母,不然会报错)
  • 项目描述(可写可不写,看我的须要)
  • 做者(可写可不写,看我的须要)
  • vue编译,这个选默认便可,运行加编译Runtime + Compiler
  • 是否安装vue-router是否安装vue路由工具
  • 是否使用代码管理工具ESLint管理你的代码
  • 后面几个是测试的工具,须要本身自行了解
    ......

clipboard.png

clipboard.png

紧接着,咱们使用cd squareRoot 移动到文件夹squareRoot下,执行chrome

npm install

clipboard.png

初始化项目,安装package.json 文件中描述的依赖,初始化完成后,咱们能够经过

npm run dev

运行咱们的项目,这个时候,咱们能够打开浏览器,输入http://localhost:8080/,可看到以下界面,说明咱们的项目脚手架已经初始化完成;

clipboard.png

clipboard.png

步骤3、项目结构解析

虽然咱们是经过vue-cli生成的项目结构,但仍是但愿读者可以清楚的知道每一个文件的做用,这样对于咱们学习该脚手架以及搭建本身的脚手架会有很好的帮助,以下图,是一级目录下的文件的做用:
clipboard.png

构建相关的代码主要是放在build文件夹和config文件夹下,包括了开发环境和生产环境,即dev和product,能够打开文件进行阅读,有接触过node的小伙伴应该能够很快读懂对应文件代码的做用,这里就不作详细的介绍了,须要注意的一点是,咱们须要修改打包后文件的路径的时候,能够经过修改config文件夹下的index.js文件,以下图:

clipboard.png

clipboard.png

这里,咱们须要在src目录下新增一个page文件夹,用于存放页面相关的组件,而components存在的是公共的组件,这样作有利于咱们更好的理解项目:

clipboard.png

步骤4、引入UI框架iView

该步骤并非必定要实现的,实际项目操做中,要根据具体需求而引入对应的UI框架或者不引入,鉴于指导的做用,在此处也作个示范,给与参考,可先阅读iVew官网学习;
首先,咱们应进行iView的安装,可利用npm包管理工具安装

npm install iview --save

安装成功后,咱们要将对应的框架引入到项目中,这个时候,官网上有两种方法能够实现,第一种是直接在main.js中作以下配置:

import Vue from 'vue'
import App from './App'
import router from './router'
import iView from 'iview';
import 'iview/dist/styles/iview.css';

Vue.config.productionTip = false
Vue.use(iView);
/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
})

这种方式是一种全局引入的方式,引入后就在具体的页面或者组件内不须要再进行其余的引入,但缺点是不管是否须要该组件,都将所有引入,对于性能优化不是很好,这里推荐第二种用法,按需引入,这里须要借助插件babel-plugin-import实现按需加载组件,减少文件体积。首先须要安装,并在.babelrc中配置:

npm install babel-plugin-import --save-dev
// .babelrc
{
  "plugins": [["import", {
    "libraryName": "iview",
    "libraryDirectory": "src/components"
  }]]
}

而后这样按需引入组件,就能够减少体积了,这里须要注意的是,由于咱们修改了.babelrc文件,这将致使咱们第一种引入方法失效了,若是再使用那种方式引入,会致使代码报错;

<template>
  <div class="content">
    <div class="title">患者接诊</div>
    <div>
      <Button type="primary" shape="circle" class="btn-time">临时保存</Button>
      <Button type="primary" shape="circle" class="btn-cancel">取消就诊</Button>
      <Button type="primary" shape="circle" class="btn-done">完成就诊</Button>
    </div>
  </div>
</template>

<script>
  import {Button} from 'iview'
  export default {
    name: "fHeader",
    components:{
      Button
    }
  }
</script>

运行结果以下图
clipboard.png

步骤5、vue-router的使用

若是没有阅读过官方文档,建议大伙先阅读,官网上的教程已经足够详细,受益不浅;学习的过程当中,须要了解路由配置的基本步骤,命名规则,嵌套路由,路由传参,具名视图以及路由守卫,滚动行为和懒加载,这里咱们就不一一详细介绍了,官网已有,咱们这里是作构建是的配置和懒加载处理:
首先,咱们应该是安装vue-router,这个在咱们生成项目的时候,已经将该依赖加载进来了,下一步要作的是在router文件下index.js进行配置:

import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)

export default new Router({
  scrollBehavior (to, from, savedPosition) {
    return { x: 0, y: 0 }
  },
  routes: [
    {
      path:'/',
      redirect:'/root'
    },
    {
      path: '/root',
      name: 'root',
      components: {
        Left:() => import('@/page/rootLeft.vue'),
        Middle: () =>import('@/page/rootMiddle.vue'),
        Right: ()=>import('@/page/rootRight.vue')
      }

    }

  ]
})

上面的代码中,咱们应用到了几个知识点,首先是滚动行文,这里咱们配置了当路由跳转的时候,默认是滚动到(0,0)位置,即页面开始位置,其次咱们用到的redirect是一个路由重定向的配置,接下来,在路由"/root"下,配置了具名视图,加载对应组件到对应视图,咱们引入组件的方式使用到了箭头函数,这样写的目的是为了实现路由的懒加载,这样构建,只有在路由被执行的时候,才有引入对应的组件,对于页面性能的优化有很大的帮助;这里还须要注意的是,咱们在引入的这些组件中,其实默认都是打包到一个文件下的,这样就会致使一次性引入的文件过大,为此,咱们能够利用webapck打包工具,咱们在build>webpack.base.conf.js文件下,增长以下代码,用于配置输出文件的模块名称,[name]是文件的名称,[chunkhash]是打包文件的哈希值,加上这个是为了将其做为版本号,以解决浏览器缓存机制带来的问题:

clipboard.png

而后在路由文件中引入组件的代码以下:

{
      path:"/test",
      name:"test",
      component: ()=>import(/*webpackChunkName:"test"*/'@/page/test.vue')
}

在引入组件的时候,加上/ webapckChunkName: "文件名" /,就这能够将对于的组件打包到指定名称的文件下,这样能够减小首次加载的文件的大小,对于一些没有联系的功能,好比不一样页面,咱们能够把对应的组件放在同一个文件,这样,既能够减小首次加载文件达大小,同时也能够将文件实现一个按需加载,提升页面性能;

clipboard.png

经过控制台,咱们能够查看当前加载的文件资源,当咱们点击测试按钮的时候,页面发生的跳转,这时候,咱们会发现,在Network下,会加一条新的资源加载信息,这一条就是咱们的分块打包后请求的资源;

clipboard.png

步骤6、全局过滤器filter和全局注册组件的引入

写到这里的时候,可能不少人都会以为,全局注册filter和全局组件组件不是很简单吗,直接Vue.filter()和Vue.component()不久解决了吗,其实这么讲也没错,可是你可曾想过,注册全组件是挂载在Vue对象下的,这意味这按照正常思路,咱们要写在main.js文件下,这样就会形成,咱们所写的mian文件过于冗长,你能够想一下,把全局的过滤器,和组件都写进去,着实丑陋,很不优雅,下面跟你们说一个优雅的实现方法:
首先,咱们在src>assets目录下新建一个js文件夹,再该文件夹下再建立一个filters.js的文件,以下图:

clipboard.png

接下来,咱们在filters.js文件下写咱们的全局过滤器,再将其抛出,写一个时间过滤器做为例子:

const fullTime = val => {
  var dateObj = new Date(Number(val));
  var year = dateObj.getFullYear();
  var month =
    dateObj.getMonth() + 1 > 9
      ? (dateObj.getMonth() + 1).toString()
      : "0" + (dateObj.getMonth() + 1).toString();
  var date =
    dateObj.getDate() > 9
      ? dateObj.getDate().toString()
      : "0" + dateObj.getDate().toString();
  var hour =
    dateObj.getHours() > 9
      ? dateObj.getHours().toString()
      : "0" + dateObj.getHours().toString();
  var minutes =
    dateObj.getMinutes() > 9
      ? dateObj.getMinutes().toString()
      : "0" + dateObj.getMinutes().toString();

  return year + "/" + month + "/" + date + "  " + hour + ":" + minutes;
};
module.exports={
  fullTime
}

作完这一步,其实咱们的过滤器还没写完,还须要在main.js中写一个注册函数:

import Vue from 'vue'
import App from './App'
import router from './router'
import filters from './assets/js/filters'
import 'iview/dist/styles/iview.css';

Object.keys(filters).forEach(key =>{
  Vue.filter(key,filters[key])
})

Vue.config.productionTip = false

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

这样,咱们就把filters文件下的过滤器函数注册到Vue全局下,一样道理,咱们能够按照一样的思路注册全局组件,咱们在src>assets>js下新建一个components.js文件,在其中引入咱们想注册的全局组件,export出一个对象,使用Object.keys获取后注册到全局下:

//components.js下
import testInput from '@/components/testInput.vue'

export default{
  testInput:testInput
}
//main.js下
import components from './assets/js/components'

Object.keys(components).forEach(key => {
  Vue.component(key,components[key])
})

优雅的注册全局组件和全局过滤器已经讲完,接下来就是API管理阶段了。

步骤7、请求api管理

这里咱们使用axios发起异步的请求,安装很简单,npm install axios 便可,一开始的时候,我使用的是直接在每一个组件内使用axios,到后面发现,但当我须要修改api接口的时候,须要查找的比较麻烦,只由于没有集中的对全部的api进行管理,并且每一个请求回来的接口都须要写对应的报错处理,着实麻烦,这里我新建一个fecth文件夹并在其下新建一个api.js用来存放全部的axios处理和封装,:

//fetch/api.js
import axios from 'axios'

export function fetch(url, params) {
  return new Promise((resolve, reject) => {
    axios.post(url, params).then(
      response => {
        resolve(response.data)
      }
    ).catch(error => {
      console.log(error)
      reject(error)
    })
  })
}

getDefaultData=()=>{
  return fetch('/api/getBoardList');
}
export default {
  getDefaultData
}

这样作的好处是集中化的管理了全部的api接口,当咱们须要修改接口相关的代码,只须要在api.js中修改,包括路由修改以及路由拦截等,可读性更好;在不一样的组件内,咱们只须要把对应的接口用解构赋值的思想把它引入对应的组件内便可使用。

import {getDefaultData} from '@/fetch/api.js'

步骤8、代理服务器的配置

这个功能主要是咱们在调试接口的时候使用,由于当咱们运行npm run dev 的时候,实际上咱们的项目已经挂载在一个本地服务端运行了,端口号为咱们配置的8080,当咱们想在该项目下访问服务端接口数据的时候,就会产生跨域的问题,这个时候,咱们就须要使用到proxy代理咱们的数据请求,在vue-cli中已有配置相关的代码,咱们仅须要把对应的代理规则写进去便可,这里以一个通用配置例子实现;
首先,咱们在fetch文件夹下新建一个config.js的文件,用于存放咱们的代理路径配置:

const url = 'http://www.dayilb.com/';
let ROOT;
if (process.env.NODE_ENV === 'production') {
  //生产环境下的地址
  ROOT = url;
} else {
  //开发环境下的代理地址,解决本地跨域跨域,配置在config目录下的index.js dev.proxyTable中
  ROOT = "/"
}

exports.PROXYROOT = url; //代理指向地址
exports.ROOT = ROOT;

接下来,咱们要在config目录下新建一个proxyConfig.js,存放代理服务器的配置规则:

var config= require("../src/fetch/config");
module.exports = {
  proxy: {
    [config.ROOT]: {    //须要代理的接口,通常会加前缀来区分,但我我的是没加,即‘/’都转发代理
      target: config.PROXYROOT,  // 接口域名
      changeOrigin: true,  //是否跨域
      pathRewrite: {
        [`^/`]: ''   //须要rewrite的,针对上面的配置,是不须要的
      }
    }
  }
}

最后,咱们在config目录下的index.js文件中,引入咱们的代理规则,并在,即

var proxyConfig=require('./proxyConfig')
...//省略号表示省略其余代码
module.exports = {
...
proxyTable: proxyConfig.proxy,
...
}

从新启动项目,咱们就能够作到代理转发来实现跨域请求了。

步骤9、vuex状态管理引入

终于,来到了最后一步,那就是咱们的状态管理vuex,其实这个东西不是说全部项目都须要引入,看项目的具体需求,但须要对同一个数据源进行大量的操做的时候,建议使用,若是每一个组件的数据均可以轻易的在data中管理,那实际上是不必引进去的,该管理工具是更友好的解决了组件间传值的问题,包括了兄弟组件;
首先,咱们须要安装vuex,老规矩就是

npm install vuex

安装完成后,咱们须要对咱们的项目进行一些修改,首先是咱们的目录,咱们须要src下新增一个store文件夹做为vuex数据存放位置,在开始搭建前,咱们须要有vuex的相关知识,我就不一一说明,自行百度一下vuex官方文档;众所周知,vuex有state,getter,mutation,action等关键属性,state主要是用于存放咱们的原始数据结构,相似与vue的data,不过它是全局的,getter相似于计算属性computed,mutation主要用于触发修改state的行为,actions 也是一种触发动做,只不过与mutation的区别在于异步的操做咱们只能在action中进行而不能在mutation中进行,目的是为了浏览器更好的跟踪state中数据的变化。
接下来,咱们来看一下store文件夹中都有什么:

clipboard.png

从上图可知,我建立了一个index.js入口文件,getters.js,mutation.js和mutationtypes.js,以及actions.js,下面咱们先看看index.js的源码:

import Vue from 'vue'
import Vuex from 'vuex'

import actions from '@/store/actions.js'
import getters from '@/store/getters.js'
import mutations from '@/store/mutations.js'

Vue.use(Vuex)
const state = {
  recipeList:[],
  currRecipe:0
};
if (module.hot) {
  // 使 action 和 mutation 成为可热重载模块
  module.hot.accept(['./mutations'], () => {
    // 获取更新后的模块
    // 由于 babel 6 的模块编译格式问题,这里须要加上 `.default`
    const newMutations = require('./mutations').default;
    // 加载新模块
    store.hotUpdate({
      mutations: newMutations,
    })
  })
}
export default new Vuex.Store({
  state,
  mutations,
  getters,
  actions
})

首先,咱们把Vuex插件引入vue中,并新建了一个Vuex.Store()对象,其中各项属性值来自咱们前面所建立的文件夹,中间module.hot是配置咱们的action和mutation成为可热重载的模块,对于咱们的调试更方便,当咱们建立为Vuex.store对象后,咱们还须要把它声明到main.js的页面Vue对象中

import store from './store/index'

...
new Vue({
  el: '#app',
  router,
  store,
  components: {App},
  template: '<App/>'
})

在使用mutation的时候,咱们是推荐你们把全部的行为常量保存到一个.js文件中,这样更有利于管理咱们的项目,由于咱们的mutation每每是须要使用action进一步封装的,这样咱们在使用的时候,只须要修改常量对象里的属性值,就能够达到同时修改mutation和action的对应关系,一箭双雕,下面举例给你们参考:

//mutationType.js
export default {
  ADD_NEW_RECIPT:'ADD_NEW_RECIPT',
  CHANGE_CURR_TAB:'CHANGE_CURR_TAB'
}
//mutations.js
import mutationTypes from '@/store/mutationTypes.js'

const mutations = {
    [mutationTypes.ADD_NEW_RECIPT](state, item) {
      state.recipeList.push(item);
    },
    [mutationTypes.CHANGE_CURR_TAB](state, index) {
      state.currRecipe=index;
    }
  }
;
export default mutations
import mutationTypes from '@/store/mutationTypes.js'

const actions = {
  add_new_recipt:({commit,state}, type)=>{
    commit(mutationTypes.ADD_NEW_RECIPT,type);
  },
  change_curr_tab:({commit},index)=>{
    commit(mutationTypes.CHANGE_CURR_TAB,index)
  }
};

export default actions

从上面的例子能够看出,action和mutation使用的是同一个常量表,能够更好的管理咱们的修改动做,而不会出现对不上的错误;
最后,咱们在组件内引入vuex中存放的state和action,以下

import {mapActions, mapState} from 'vuex'
...
computed: {
      ...mapState({
        recipeList: state => state.recipeList,
        currRecipe: state => state.currRecipe
      })
    },
methods: {
      ...mapActions([
        'add_new_recipt',
        'change_curr_tab'
      ]),
      addNewRecipt(type) {
        this.add_new_recipt(type)
      }
    }

这里是推荐你们按照例子中,使用mapActions和mapState以及利用三点扩展符来引入state 和action,state最好存放在组件的computed 属性内,这样当state中的数据发生改变的时候,也会实时的修改computed里定义的变量值,来实现数据的绑定,同时,当咱们修改了某些数据的时候,也要同步到state中去,这样数据源才能够保持一致性与准确性;

总结

写这个的时候,只是给个思路去搭建本身的工程文件,并非说把全部相关知识点都讲一遍,须要有必定的相关知识,不过相信还没本身搭建过工程文件的小伙伴会不知道如何去安排,能够参考参考,这里推荐你们安装chrome的扩展插件Vue.js devtools,能够颇有效的帮助咱们追踪数据,定位错误。

clipboard.png

相关文章
相关标签/搜索