vue.js应用开发笔记

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

一、vue.js

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

vue init webpack frontend,如下:

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

一般每个团队都有自己的代码规范,这时候打开eslint,配置自己团队的代码规范就显得尤为重要,下面说下vscode编辑器下如何配置eslint,在之前项目基础上我们配置下eslint,首先是vscode安装eslint插件:

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

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

{
    "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官方说明。

2、项目结构

前面通过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后面继续介绍。

3、关于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获得该子组件实例,然后可以进行各种实例操作。

4、运行效果

刚刚说了那么多,我们的项目差不多搭起来了,通过命令行:npm run dev,然后直接在浏览器中可以查看效果:

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

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

二、vue-router

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

1、配置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(该路由对应的组件实例),注意的是一般我们会对路由组件做懒加载处理,以便加快首屏渲染速度。

2、在组件中配置使用

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方法,所有路由调用之前均执行该方法,这里我们一般可以做一些权限判断、登录判断之类的操作:

三、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。

1、配置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实例中:

2、actions

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

然后可以直接进行相关操作,也可以在此将payload数据commit到mutation中在此进行处理。

3、mutation

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

4、getters

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

5、最后看下要操作的state

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

6、组件辅助函数

辅助函数是干嘛的呢,比如之前我们定义好的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的:

四、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,表示无权限信息,那么这里可以直接进行相关错误信息展示,或者直接跳转至登录或其它页面。

五、一个简单应用

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

六、最后想多说几句

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

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏雨过天晴

转 PHP下的session的生存周期

1163
来自专栏葡萄城控件技术团队

Asp.Net Forms认证在移动平台中遇到的一个问题以及调查过程

我们项目的网站的移动版是基于Asp.Net平台开发的,用户登录也是基于Asp.Net的Forms认证,在整个开发和测试过程中没有发现任何客户登录异常,但是发布后...

1817
来自专栏腾讯Bugly的专栏

打造“微信小程序”组件化开发框架

导语 Bugly 之前发了一篇关于微信小程序的开发经验分享,小伙伴们在公众账号后台问了很多关于小程序开发方面的问题,精神哥在查阅相关内容的时候,发现了龚澄同学自...

4263
来自专栏java思维导图

博客项目Tale思维导图,让项目不再难懂

写在前面 这次介绍的这个博客项目可以说有点另类,因为它使用的技术大部分都不是主流的技术,从前端到后端框架再到数据库的选择。当然,麻雀虽小但五脏俱全。技术的运用需...

3874
来自专栏SDNLAB

ONOS编程系列(四)Provider开发

在学习本篇文章的时候,笔者假设读者已经读过该系列的前几篇文章,或者对于ONOS整个项目的架构有一定的了解,并且电脑上已经有onos-1.1的源程序,能熟练使用O...

3175
来自专栏小特工作室

Navi.Soft31.WinCE框架.开发手册(含下载地址)

1.概述 1.1应用场景 随着物联网的普及,越来越多的制造商对货品从原料配备,加工生产,销售出库等环节的要求和把控越来越高.在此情况之下,传统的ERP软件已经无...

1835
来自专栏恰同学骚年

CMS项目实践学习总结

  这个暑假把ITCAST的2011年2月的.NET就业班的视频看了一遍,因为以前把免费的2010版和2011版的视频都看了一遍,所以这次选择了其中的几个部分作...

1085
来自专栏竹清助手

Love beautiful code? We do too.

Laravel是一个有着美好前景的年轻框架,它的社区充满着活力,同时提供了完整而清晰的文档,而且为快速、安全地开发现代应用提供了必要的功能。

772
来自专栏主机笔记

centos安装ab工具给网站进行压力测试

在配置好网站服务器后,我们可以进行压力测试看一看实际环境中的效果怎么样,判断服务器质量、网站程序设计是否合理、提前预防突发事件。今天就介绍一款开源免费的压力测试...

24810
来自专栏SDNLAB

SDNLAB群分享(四):利用ODL下发流表创建VxLAN网络

今天想跟大家分享如何通过ODL控制器下发流表来创建VxLAN网络。ODL作为当前流行的控制器,已经有广泛的应用。基于ODL提供了丰富的北向接口,使得应用对网络有...

27710

扫码关注云+社区