vue.js应用开发笔记

看vue.js有几天了,以前也零零散散的瞅过,不过一直没有动手去写过demo,这几天后台事比较少,一直在讨论各类需求(其实公司对需求仍是比较重视与严谨的,一个项目需求讨论就差很少一周了,这要搁以前,天哪。。。),因而就琢磨着把vue简单的过下,以下所讲只是我的一些理解,不到的地方还望园友指正,涉及到的东西有vue、vue-router、vuex、axios以及nodejs一些后台东西,废话不说了直接上菜吧。javascript

1、vue.jscss

一、项目搭建使用vue-cli脚手架,首先必须安装vue、vue-cli:cnpm i vue vue-cli -g,全局安装完成以后咱们即可以使用vue-cli脚手架进行项目结构搭建,具体以下:html

vue init webpack frontend,以下:前端

这里咱们环境部分选择“运行环境+编译环境”,这样,后面直接可使用webpack进行编译后部署,十分方便,再继续:vue

通常每一个团队都有本身的代码规范,这时候打开eslint,配置本身团队的代码规范就显得尤其重要,下面说下vscode编辑器下如何配置eslint,在以前项目基础上咱们配置下eslint,首先是vscode安装eslint插件:java

而后在用户设置栏配置具体的eslint规则:node

依次打开vscode的“文件”->“首选项”->“用户设置”,在右侧编辑区输入咱们定义好的eslint规则:react

{
    "editor.fontSize": 17,
    "editor.tabSize": 2,
    "editor.formatOnSave": false,
    "files.associations": {
        "*.vue": "vue"
    },
    "eslint.validate": [
        "javascript",
        "javascriptreact",
        "html",
        "vue",
        {
            "language": "html",
            "autoFix": true
        }
    ],
    "emmet.syntaxProfiles": {
        "vue-html": "html",
        "vue": [
            "css",
            "html",
            "less"
        ]
    },
    "editor.fontFamily": "Source Code Pro, 'Courier New', monospace",
    "files.autoSave": "off",
    "workbench.iconTheme": "vscode-icons"
}

这里咱们设置字体大小为17,tab缩进为2个空格,eslint的校验适用于js、html、vue,设置vscode图标为vscode-icons,其它规则能够参考下eslint官方说明。webpack

二、项目结构ios

前面经过vue-cli生成的项目结构以下:

主要是src文件夹,咱们对其进行了一些拓展,其中api文件夹用来存放前端各类请求api模块,components文件夹以下:

用来存放各类页面组件,其中base为公共组件,好比一些页头、页尾、分页组件等等,Home为主界面,该页面经过router路由来整合其它组件,Login为登陆组件。mock文件夹用来进行mock.js配置,这样前端能够独立于后端接口开发,使用虚拟数据不依赖后端从而更加高效。router文件夹用来配置vue-router下的各类前端路由,vuex文件夹主要用来配置vuex状态管理相关:

其中modules文件夹用来存放各个vuex的module,分模块配置的话有个好处就是项目比较庞大的时候便于数据查看与管理,mutation.types.js用来存放各类vuex的mutation类型常量,关于vuex后面继续介绍。

三、关于vue.js一些知识点

1)、组件概念

组件这个比较好解释,简单理解就是一个个经过vue本身的方式注册的页面(能够是公有页面也能够是单个页面),组件化开发时经过template包裹的一系列部分功能页面均可以称做组件,好比咱们的App.vue:

固然,每一个组件都有属于本身做用域,组件下的各个数据及相关操做均写在当前组件下的script标签中,以下:

能够看到如上为App.vue组件的数据结构,这里经过ES6的export default导出当前vue实例,组件下包含不少东西,好比data(data是一个function,经过return一个数据对象来表示当前组件都有哪些数据实例)、components(组件是能够被其它组件导入使用的,components就是用来声明当前组件导入的子组件)、computed(计算属性,和data相似,本质返回的是一个数据对象)、watch(监听,主要是监听数据对象的变化,有变化则执行对应的function)、mounted(钩子函数,组件初始化时调用)、methods(用得最多,当前组件下的私有方法,可经过this.methodName调用)、events(事件,当前组件下的事件函数),这里还有不少,具体能够参考官网。

固然,每一个组件都有属于本身的style样式,使用以下定义:

这里的scoped表示下方样式仅仅当前组件有效,不然全局有效,经过@import咱们能够导入外来样式文件(这里公共资源咱们通常定义在src的assets文件夹下,不用写在static文件夹下,由于assets被打包时会自动打包,为了统一仍是放在assets下面)

2)、组件间的数据交换

首先是父子组件间的数据交换:

父组件比如咱们这里的App.vue组件,子组件就比如咱们import进来的那些组件,vue.js提供了咱们很便捷的方式进行跨组件间的通讯,对于父子组件那即是:子组件dispatch事件到父组件,父组件broadcast事件到下面的全部子组件,默认事件传输为冒泡传输。什么意思呢,就是说在App.vue里面咱们能够直接经过dispatch方法向上派发事件,前提是父组件须要在methods或者events那里配置好改事件(只有配置了该事件才能接收到,推荐写在events里面),固然派发时能够传递一些数据,同理父组件也是经过broadcast广播事件到子组件。二是咱们能够经过props属性进行,子组件在script标签中写明须要prop的哪些属性,父组件在调用子组件的地方直接写上该prop(若是添加v-bind:prop则为动态prop),那么该数据便直接从父组件传递到了子组件中三是咱们能够经过全局的$emit进行事件通讯,这个能够参考官网文档。

其次是任意无关系的组件如何通讯:

这个时候须要使用中间组件进行数据传输,至关于搭建起一个中央数据总线,好比A组件须要和C组件进行通讯,那么咱们能够在定义一个空的组件为B,那么在A组件中导入B组件,同时向B组件派发事件,同时在C组件中导入B组件,并在此进行事件接收便可。固然了解vuex的话,使用vuex能够轻松解决任意组件间的通讯问题,这个后面说。

3)、vue.js实例属性

一个是$.parent和$.children,这两个一个是获取当前组件的父实例,一个是获取当前组件的全部子组件,获取到组件后即可以方便访问实例的方法、数据资源等了。$.refs是在父组件调用子组件的地方,为了区分各个子组件,能够为组件指定不一样的ref属性,而后在经过this.$refs.xxx得到该子组件实例,而后能够进行各类实例操做。

四、运行效果

刚刚说了那么多,咱们的项目差很少搭起来了,经过命令行:npm run dev,而后直接在浏览器中能够查看效果:

默认启动的是8080端口,访问下:

到这里,一切都ok了,简单的vue.js脚手架项目就搭建完毕了。

2、vue-router

看到router,顾名思义“路由”的意思,vue-router赋予SPA应用前端路由的权利,从而实现自定义页面跳转而不请求服务端,主要记录以下:

一、配置vue-router

在前面的脚手架项目里面咱们已经生成了自带vue-router的脚手架项目,下面主要是对其进行一些修改说明:

import Vue from 'vue'
import Router from 'vue-router'
// import store from '../vuex'
// import App from '../App.vue'
// import _ from 'lodash'

Vue.use(Router)

export const router = new Router({
  mode: 'history',
  routes: [
    // 组件懒加载,这样可防止组件太多时首屏打开慢的问题
    { path: '/user', component: resolve => require(['../components/user/User.vue'], resolve) },
    { path: '*', component: null }
  ]
})

router.beforeEach((to, from, next) => {
  // to and from are Route Object,next() must be called to resolve the hook
  // if (!store.getters.logined) {

  // } else {
  //   next()
  // }
  next()
})

router必须使用vue.use进行全局注册方可以使用,mode参数用来配置router的模式,默认为带“#”的hash模式,固然配置为history则使用H5的history模式,路由更像是普通url。routes用来配置各类具体路由信息,这里routes是一个对象数组,每个对象都是一个路由对象,其中包括path(路由路径,支持正则匹配)、component(该路由对应的组件实例),注意的是通常咱们会对路由组件作懒加载处理,以便加快首屏渲染速度。

二、在组件中配置使用

router-view是用来作路由视图的显示的,第一步配置了每一个路由对应的路由,那么一旦某个页面使用router-view进行视图显示的话,刚好该路由匹配了上面path,那么path对应的组件将会展现在router-view的位置,至关于路由组件的填位吧。固然一个页面或组件能够配置多个router-view,那么相应的就须要引入多个组件实例了。

router-link是一个路由跳转标签,能够理解为咱们html中的a标签,router-link标签内部包含属性to,一样能够路由配置。

关于路由方法:

router.push()、router.replace():路由跳转

router.back():路由回退

router.forward():forward跳转

其它参考官网说明,应用较多的是beforeEach方法,全部路由调用以前均执行该方法,这里咱们通常能够作一些权限判断、登陆判断之类的操做:

3、vuex状态管理

vuex主要用来进行全局状态管理,能够理解为全局的数据管理,vuex主要由几部分组成:action、mutation、getters、state组成,通常的使用流程是:组件中能够直接调用上面四个部分,好比调用action,可使用:this.$store.actionName,mutation也是同样,不一样的是action支持异步调用,mutation下的操做彻底同步,也就是说,action下能够调用各类api调用(api方法通常都是异步的,返回promise对象)。组件访问getters:this.$store.getters.gettersName,组件中调用state:this.$store.moduleName.stateName(模块化配置vuex时这样访问)。action通常commit事件到mutation,而后再在mutation中操做state中的数据,最后经过getters暴露state中的数据给组件使用,若是不涉及到异步操做的话,能够直接在组件中dispatch到相应的mutation而跳过action直接操做state。

一、配置vuex

首先是module下的user模块内容:

import * as types from '../mutation.types'
import * as http from '../../api/http'

// import _ from 'lodash'

const state = {
  userinfo: JSON.stringify(localStorage.getItem('userinfo') || {})
}

const actions = {
  setUserInfo ({ commit }, userinfo) {
    localStorage.setItem('userinfo', userinfo)
    commit(types.SET_USERINFO, userinfo)
  },
  login ({dispatch, commit, getters}, plyload) {
    return http.get('/user/caiya', {})
  }
}

const mutations = {
  [types.SET_USERINFO] (state, userinfo) {
    state.userinfo = userinfo
  },
  [types.LOGOUT] (state) {
    localStorage.setItem('userinfo', '')
    state.userinfo = ''
  }
}

const getters = {
  logined (state) {
    return state.userinfo !== '' && state.userinfo !== '{}'
  },
  userinfo (state) {
    if (state.userinfo !== '' && state.userinfo !== '{}' && typeof state.userinfo === 'string') {
      return JSON.parse(state.userinfo)
    } else if (typeof state.userinfo === 'object') {
      return state.userinfo
    }
    return null
  }
}

export default {
  state,
  actions,
  mutations,
  getters
}

每一个module都有相应的四个组成部分,分别定义如上,而后再在index.js中配置出该模块:

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

import user from './modules/user'

Vue.use(Vuex)

export default new Vuex.Store({
  modules: {
    user
  }
})

最后再将该store配置到全局的vue实例中:

二、actions

actions接收键值对函数,该函数第一个参数为vuex的context对象,其中包括dispatch、commit、getters对象函数,经过ES6结构的方式能够直接取到:

而后能够直接进行相关操做,也能够在此将payload数据commit到mutation中在此进行处理。

三、mutation

mutation通常用来对state中的数据进行修改操做,其中第一个参数为state对象,后面参数不定,均为action传过来的参数或者页面经过dispatch直接传过来的参数

四、getters

能够看到getters其实就是用来过滤处理state中的数据的,每一个getters函数第一个参数为当前module下的state对象,定义好getters后组件中直接获取getters便可获取到state中的过滤后的数据:

五、最后看下要操做的state

其实state就是json对象,用来保存任意状态的:

六、组件辅助函数

辅助函数是干吗的呢,好比以前咱们定义好的action、mutation、getters、state后,在组件中想使用他们要怎么作呢?必须使用this.$store.getters.xxx来获取getters xxx,要调用action必须使用this.$store.actionName来调用,mutation同理,获取state要使用this.$store.state.moduleName.stateName获取指定moduleName下的stateName这个state数据,这样调用比较麻烦,因此辅助函数就出现了。

好比咱们Login.vue组件须要调用actions中的Login方法,以下:

一样地方式咱们能够这样直接调用mutation:

再来看个getters的:

4、axios

axios是一个http请求包,相似于vue-resource(该包已中止维护),vue官网推荐使用axios进行http调用,由于axios压缩后体积更小,支持restful方法调用,关于axios的使用看以下代码,其中有详尽介绍:

import axios from 'axios'

axios.defaults.baseURL = 'https://cnodejs.org/api/v1'
// axios.defaults.headers.common['Authorization'] = AUTH_TOKEN
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'

const ACCESS_TOKEN = 'accesstoken=ed20aac8-9fd8-45bf-8112-62fd2425b4a5'

// 添加请求拦截器
axios.interceptors.request.use(config => {
  // 在发送请求以前作些什么
  config.url = `${config.url}?${ACCESS_TOKEN}`
  return config
}, error => {
  // 对请求错误作些什么
  return Promise.reject(error)
})

// 添加响应拦截器
axios.interceptors.response.use(response => {
  // 对响应数据作点什么
  return response
}, error => {
  // 对响应错误作点什么
  return Promise.reject(error)
})

export function fetch (url, params) {
  return new Promise((resolve, reject) => {
    axios.post(url, params).then(res => {
      resolve(res)
    }).catch(err => {
      reject(err)
    })
  })
}

export function get (url, params) {
  return new Promise((resolve, reject) => {
    axios.get(url, {
      params: params
    }).then(res => {
      resolve(res)
    }).catch(err => {
      reject(err)
    })
  })
}

这样将该http.js文件导出后,能够直接在action中调用,不用全局vue配置,十分方便。axios.interceptors.request方法主要用来给全部的请求添加拦截器,这里能够进行各类请求权限校验、方法重写等操做,axios.interceptors.response主要是对响应作拦截处理,好比说咱们服务端返回状态码为403,表示无权限信息,那么这里能够直接进行相关错误信息展现,或者直接跳转至登陆或其它页面。

5、一个简单应用

闲暇时间作了个简单的登陆及后台管理系统(ps:刚开始作),简单效果以下,github地址:https://github.com/caiya/frontend

 

6、最后想多说几句

一、任何技术,想学就得多动手去作,实践出真知啊,光看不作经不起实战的考验

二、多写博客仍是不错的哈哈哈,不光是练文笔,陶冶情操也是有的,更别提那些大无畏的分享精神了

相关文章
相关标签/搜索