vue2初学体验

继上次reactangular1学习体验之后,隔了四个月,最近有空就入门起了vue2了,其实一开始有稍微看一下的,一开始给我感觉跟angular有点像,而我感觉angular总有那么点复杂感,于是就没继续看,等到vue2出来了,既然有空就学习一下,给我感觉,还是比较轻快简便的一个框架,文档详尽,多到我还没看完,就看了语法那块就开始动手写demo了,也翻查了好些入门内容,遇到不少坑。

所用工具

学习vue,首先要看文档,这是必须的。看这里,中文版

在看完文档,写了几个demo之后,开始使用官方脚手架vue-cli来写demo,加入vue-router(路由)和vue-resource(http请求库)。

说起脚手架,看到刚安装完vue-cli,然后开始建立一个demo的时候,看生成的npm包,好多啊,可怕。一种新手恐惧感就来了,还好一切按照运行起来正常。

我的demo就是在vue-cli生成的demo上做改动的,demo提供了服务器的启动,看代码似乎用的是express来承载。

再者,web下异步需要接口等,可以用‘mock-api’来模拟接口,方便,而且vue-cli也提供了接口代理。

安装

vue-cli

脚手架的安装也不麻烦:全局安装,要求node版本>=4.x

$ npm install -g vue-cli

安装后执行命令:

$ vue init webpack demo

即在demo目录下生成项目。

(update) 只是生成了一个项目轮廓,项目中需要的依赖包,还需要在项目目录里执行 npm install(读取package.json的依赖包并下载到项目中,感谢评论提醒)

然后在demo目录下执行

$ npm run dev

即启动本地开发模式

vue-router | vue-resource

安装到demo目录中

$ npm install vue-router –save-dev

$ npm install vue-resource –save-dev

mock-api

安装方式:

npm install -g mock-api

使用方式:

比如建立一个目录api,在api里建立一个json文件,json文件内容为一个数组,例子:

[
	{
        "method": "get",
        "url": "/api/bug/:id",
        "response": {
            "result":{
            	"id": "",
            	"title":"暴露代码",
            	"desc":"页面显示出了代码",
            	"level":"5",
            	"author":"hoverq",
            	"responser":"blong"
            }
        }
    }
]

示例代码写了一个配置对象,意为get请求/api/bug/id时,响应内容则是response对象的值,其中:id可以实现url含诸如id之类的动态数字,而response内容里可以用``来执行js代码,如访问url上的id可以是this.params.id

写完配置文件,启动mock-api即可

$ mock-api serve api

启动时默认端口为10086,更多命令配置可以看github

配置

脚手架生成demo之后,基本可以进行开发,但对于接口部分的对应,需要改一下配置内容,由于vue-cli本地开发模式启动了一个服务,而mock-api又启动一个服务,双方接口交互势必属于跨域行为,vue-cli对这方面也做了支持,在config目录下index.js, 本地开发的相关配置dev如下:

dev: {
    env: require('./dev.env'),
    port: 8080,//本地开发启动服务的端口
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    proxyTable: {//接口代理
        '/api': {
            target: 'http://localhost:10086',
            changeOrigin: true,
            pathRewrite: {
              '^/api': '/api'
            }
          }
    },

如上配置,proxyTable为项目本地开发提供了代理接口,这里配置了当url为/api时,请求代理到target指向的域名去,changeOrigin设置跨域。

这样,我们的vue项目在本地启动时,访问接口/api就可以直接访问到mock-api模拟的接口了 ,也就是http://localhost:8080/api直接代理到http://localhost:10086/api去。

业务编码

我这里demo实现一个简单的增改查,这里就随便弄了个bug管理列表

项目页面结构: 主页面承载 index.html, 入口js main.js, 模板组件 components/xxx.vue

index.html

主要负责页面布局内容设置,其body标签部分代码如下:

<body>
	<div id="app">
	  <section class="column sidebar-left">	
	  	<h1>bug管理工具</h1>  	
		<ul>
			<li>
				<router-link to="/bugs">Bug 列表</router-link>
			</li>
			<li>
				<router-link to="/members">成员列表</router-link>
			</li>
			<li>
				<router-link to="/projects">项目列表</router-link>
			</li>
			<li>
				<router-link to="/addBug">有bug啦</router-link>
			</li>
		</ul>
	  </section>
	  <section class="column main">
		  <transition name="slide">
			  <router-view></router-view>
		  </transition>
	  </section>
	</div>
</body>

router-link标签为vue-router组件,默认渲染成一个a标签, router-view则为路由匹配到的组件渲染目的地,transition为过渡动画组件,需要配合加入样式以达到过渡效果。

入口 main.js

将各个路由模块页面设为独立的.vue文件,而main.js主要负责init初始化部分内容。代码很简单:

import Vue from 'vue'
import BugList from './components/BugList'
import ProjectList from './components/ProjectList'
import MemberList from './components/MemberList'
import BugItem from './components/BugItem'
import BugForm from './components/BugForm'

import VueResource from 'vue-resource'
import VueRouter from 'vue-router'

//组件注入
Vue.use(VueRouter);
Vue.use(VueResource);

//路由配置
const routes = [
	{ path: '/bugs', component: BugList },
	{ path: '/members', component: MemberList },
	{
		path:'/projects', 
		component: ProjectList
	},
	{
		path:'/bug/:id',
		component: BugItem
	},
	{
		path:'/addbug',
		component: BugForm
	},
	{
		path:'/editbug/:id',
		component: BugForm
	},
	{path:'*', redirect: '/bugs'}
]

//vueRouter设置
const router = new VueRouter({
  routes // (缩写)相当于 routes: routes
})

// 记得要通过 router 配置参数注入路由,
// 从而让整个应用都有路由功能
const app = new Vue({
  router
}).$mount('#app')

如上代码,即可在主页面配置好几个子页面的配置,对应的组件模板通过import传入(es6语法)

业务页面组件

列表页组件代码:主要包括模板template 以及 脚本 script

<template>
  <div class="bug-list div-for-slide table-list">
    <table class="table table-striped table-bordered" style="text-align:left;">
      <thead>
            <tr>
              <th>Bug标识</th>
              <th>标题</th>
              <th>发起者</th>
              <th>处理者</th>
              <th>所属项目</th>
              <th>详情</th>
            </tr>
            </thead>
            <tbody>
            <tr v-for='bug in bugs'>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td><router-link :to="'/bug/'+bug.id">Bugs</router-link></td>
              <td><router-link :to="'/bug/'+bug.id">详情</router-link></td>
            </tr>
            </tbody>
    </table>
    <button @click.prevent="$router.push({path:'/addbug'})" class="btn btn-info">新增bug</button>
  </div>
</template>
<script>
export default {
  name: 'buglist',
  data:function(){
      return {
        bugs:{

        }
      }
  },
  created:function(){
    this.fetchData();
  },
  methods:{
    fetchData:function(){
      //vue-resource 在vm实例中注入了$http方法,可直接用
      this.$http.get('/api/getBugs').then((response) => {
        
        this.bugs = response.body.result.data;
        
      }, (response) => {
        console.log('error');
      });
    }
  },
  watch:{
    '$route':'fetchData'
  }
}
</script>

在index.html我们通过router-link标签来渲染出链接,也可以通过js来实现编程路由,vue-router同样在vm内注入了$router$route变量,前者为路由实例,可以通过调用$router.push({path:'/addbug'})来实现跳转到/addbug页面,跟点击 <router-link to="/addBug">有bug啦</router-link>是等价的。 具体可以查看router文档, 后者提供当前路由的基本信息,如当url为/aa/:id的形式,我们就可以通过$route.params.id来得到id值。

这里说明一下,路由的数据异步获取,这点也在router文档有描述,这里用了导航加载后获取数据渲染的方式,通过created和监听$route来调用异步接口设置data数据以更新渲染页面。

初次体验给我感觉,vue2的上手不算太难,代码量少,不过文档内容详尽,还是照着写写demo,有助于理解vue语法和结构,可能还不太适应新模式的开发方式,有些思维碰撞上,开发起来需要思考很多。有机会再深入一下其他官方组件,以实践应用开发。