月度归档:2016年06月

vue 介绍

  这两天把玩了一个vue 这个前端小框架。作为一个面向前端展示层的框架,vue的表现确实出众。本系列文章将会简单介绍一下这个技术栈。本文第一篇,介绍一下vue的基本概念。

  vue的基本思想是: 采用 数据驱动 + 组件化 的方式进行前端界面开发, 特点是面向视图层,轻量级,方便与其他库结合使用。同时存在的一些不足有成熟的组件较少;而本身比较轻量,默认不包含路由、ajax等功能,需要开发人员造一些轮子,同时也缺少一些大型项目经验的分享(对比angular)。另提一点,作者是个国内小伙,在国内社区(知乎、V2、微博等)比较活跃,方便交流。

  首先介绍下数据驱动,vue的数据驱动采用来MVVM的模型结构,通过VM(ViewModel)连通前端view和数据层model,图示如下:

举例说明, 首先定义一个view层(你可以定义一个1.html):

<div id="example-1">
  Hello {{ name }}
</div>

然后定义数据model层:(你可以定义一个1.js)

var indexData = {
    name: 'Vue.js'
}

然后定义VM层来连接数据和页面,达到通过数据控制页面展示的效果:(下面的同样放入到1.js)

var indexVM = new Vue({
    el: ‘#example-1,
    data: indexData
})

这样就完成了我们第一个入门demo。 后继如果需要更改数据的内容, 只需要直接更改model的值即可,当然,推荐使用VM开放出来的方法和属性来进行修改:

方式1: indexData.name = 'liyj'   
方式2:  indexVM.$data.name = 'good'  (其中 indexVM.$data === indexData)
方式3(推荐): indexVM.$set("name", "exp")

简单了解完数据驱动、VM数据连接和绑定后,我们开始详细介绍数据驱动的一些知识点,只要分以下四个方面:数据控制、表单、动画效果 和 消息传递。

一、 数据控制

首先就是通过控制model中的数据,可以改变view层显示的内容,这点上面已经介绍了(通过VM的set方法来改变model的数据值).然后在VM中也定义了很多方法来改变视图层的相关内容,常用的方法如下:

data: Object或者Function, 数据model,Vue实例的数据对象。定义组件时类型为函数,返回原始数据对象。

props:Array 或者Object, 包含期望使用的父组件数据的属性,用于类型检查、验证,默认值等。

methods: Object类型, 实例方法。

computed: Object类型,实例计算属性值。getter和setter的this自动绑定到实例。

watch: Object类型,键是观察表达式,值是对应回调,主要功能是值发生变化时做一些触发性的动作,类似angular中使用watch定义的一些方法。

还有一些组特有的方法比如 filters,components 等,在示例中可以慢慢体会。

二、表单

view层比较重要的一块是表单,所以主要是单向数据绑定(注意这个单向指的是数据是由上到下,由父到子的,而子节点的数据改动不会影响到父节点)的vue也定义了v-model这个指令来在表单控件元素上创建双向数据绑定(关于双向数据绑定可以看一篇文章 AngularJS的数据双向绑定是怎么实现的,他的实现是事件触发的,而不是定时检测的。这种设计是一个比较优雅的理念,永远不要让我们的架构引入一堆不可控的组件比如定时器、消费队列等,相反,我们可以通过消息驱动、任务驱动和事件驱动等达到这一目的,后继会开一篇文章来介绍一下任务系统聊聊这个话题)。然后表单组件还会有一些事件触发的绑定,属性更新的绑定(普通组件也会需要到),vue中使用v-on和v-bind 这些指令来实现: v-bind 绑定属性: v-bind:href / :href, v-bind:class / :class, v-on 绑定事件: v-on:click / @click, v-on:submit / @submit。 绑定示例如下:

1. <input type="text" v-model="name" />
2. <div
      :class="{bold: isFolder}"
      @click="toggle"
      @dblclick.stop="changeType">
      {{model.name}}
      <span v-if="isFolder">[{{open ? '-' : '+'}}]</span>
    </div>
3. <ul v-show="open" v-if="isFolder">
      <item
        class="item"
        v-for="model in model.children"
        :model="model">
      </item>
      <li @click="addChild">+</li>
    </ul>

三、动画效果

页面展示要实现一些绚丽效果,动画是必不可少的。vue中使用过渡的概念来定义动画,通过在目标元素上添加transition属性来实现过渡的效果。定义过渡效果时主要关系enter 和 leave 这两个特性。然后我们就可以通过常用的几种前端动画实现方式来定义动画了:1. 通过class切换组件入和出。2. 设置CSS帧动画。3.通过JS动画实现。 示例如下:

1. 切换class
Vue.transition('expand', {
	enterClass: 'ex_in',
	leaveClass: 'ex_out'
});
css 定义:
.expand-transition {
	  transition: all .3s ease;
	  height: 30px;
	  padding: 10px;
	  background-color: #eee;
	  overflow: hidden;
}
.ex_in, .ex_out {
	  height: 0;
	  padding: 0 10px;
	  opacity: 0;
}
2. css帧动画:
.bounce-transition {
	  display: inline-block; /* 否则 scale 动画不起作用 */
	}
	.bounce-enter {
	  animation: bounce-in .5s;
	}
	.bounce-leave {
	  animation: bounce-out .5s;
	}
	@keyframes bounce-in {
	  0% {
	    transform: scale(0);
	  }
	  50% {
	    transform: scale(1.5);
	  }
	  100% {
	    transform: scale(1);
	  }
	}
	@keyframes bounce-out {
	  0% {
	    transform: scale(1);
	  }
	  50% {
	    transform: scale(1.5);
	  }
	  100% {
	    transform: scale(0);
	  }
	}
3. JS 动画:
Vue.transition('fade', {
	css: false,
	enter: function(el, done){
		$(el)
      		.css('opacity', 0)
      		.animate({ opacity: 1 }, 1000, done);
	},
	enterCancelled: function(el){
		$(el).stop();
	},
	leave: function(el, done){
		$(el).animate({ opacity: 0 }, 1000, done);
	},
	leaveCancelled: function(el){
		$(el).stop();
	}
})

四、数据传递

这里说的数据传递主要是组件间的数据传递。vue中组件在父子之间是单向传递的(广播的方式),由父到子,而在不同组件之间,作用域是孤立的。子组件的数据默认是不能流向父组件的,在程序中可以定义成消息触发的方式来传递到父组件(消息分发的方式),这样就消除了数据传递混乱的现象(父组件的数据可能被未知的子组件改变)。总结下来就是:

•1. 组件之间作用域是孤立的

•2. 父组件可以通过props 传递数据到子组件

•3. 子组件可以通过 this.$parent 和 this.$root 来访问父组件和根实例,但是尽量避免这样做

•4. 子组件可以通过事件和父组件通信

说完数据驱动,就很有必要在说一说今天的另一个重头:组件化。

vue中,我们希望页面是由一个个组件构成的(当然,组件中可以包含组件,比如一般我们会定义一个大的组件叫app,里面再包含页面上的其他组件),每个组件定义自己的VM,然后程序中通过控制VM来完成前端的逻辑。

组件可以定义为全局的或者局部的,建议公共组件定义为全局的,其他的定义为局部的。示例如下:

// global
// define global component:
var MyComponent = Vue.extend({
	template: '<p>{{msg}}</p>',
	props: ['msg']
});
// register component global
Vue.component('my-component', MyComponent);
// define VM:
new Vue({
	el: '#example-4'
})


// local
// define VM and component:
new Vue({
    el: ‘#example-4’,
    components : {
         “myComponent”: {
            props: ['msg'],
            template: '<span>{{ msg }}</span>'
        }
    }
})

然后页面上就可以通过 

<my-component msg="Hello World!"></my-component>

来引入了。

关于vue的介绍就基本到这里了,本篇文章的ppt和代码见github: https://github.com/liyj144/vue_introduction .