现在每次访问 vm.example 时,时间戳都是新的。但是,只是在 JavaScript 中访问是这样的;数据绑定仍是依赖驱动的。如果在模块中这样绑定计算属性 {{example}} ,只有响应依赖发生变化时才更新DOM。
组件系统
组件(Component)是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能。在有些情况下,组件也可以是原生 HTML 元素的形式,以 is 特性扩展。
1.创建和注册组件:
可以用 Vue.extend() 创建一个组件构造器:
var MyComponent = Vue.extend({ template : '<div>A custom component!</div>' })
要把这个构造器用作组件,需要用 Vue.component(tag, constructor) 注册(这个注册是全局的):
//全局注册组件,tag 为 my-component Vue.component('my-component', MyComponent)
组件在注册之后,便可以在父实例的模块中以自定义元素 <my-component> 的形式使用。要确保在初始化根实例之前注册了组件:
<div> <my-component></my-component> </div>
最后渲染为:
<div> <div>A custom component!</div> </div>
当然,可以让组件只能用在其它组件内,用实例选项 components 注册,比如:
var Child = Vue.extend({ /* ... */ }) var Parent = Vue.extend({ template : '...', components : { // <my-component> 只能用在父组件模板内 'my-component': Child } })
这种局部注册的方式也适用于其它资源,比如指令、过滤器和过渡。他们都支持全局和局部组件注册。
前面提到组件是可以被复用的,多个实例可能会共享一个组件构造器,那么请注意一个组件选项的问题:
传入 Vue 构造器的多数选项也可以用在 Vue.extend() 中,不过有两个特例: data 和 el。试想如果我们简单地把一个对象作为 data 选项传给 Vue.extend() :
var data = {a : 1} var MyComponent = Vue.extend({ data : data })
这么做的问题是 MyComponent 所有的实例将共享同一个 data 对象!因为对象是引用传递的,这基本不是我们想要的,因此我们应当使用一个函数作为 data 选项,让这个函数返回一个新对象:
var MyComponent = Vue.extend({ data : function (){ return {a : 1} } })
同理,el 选项用在 Vue.extend() 中时也须是一个函数。
2.使用props传递数据
当一个组件内部还有一个子组件的时候,由于组件实例的作用域是孤立的,这意味着不能并且不应该在子组件的模板内直接引用父组件的数据。这时,父组件可以使用props把数据传给子组件:
“prop” 是组件数据的一个字段,期望从父组件传下来。子组件需要显式地用 props 选项 声明 props:
Vue.component('child', { //camelCase in JavaScript props : ['myMessage'], template : '<span>{{ myMessage }}</span>' })
然后向它传入一个普通字符串:
<child my-message="hello!"></child>
子组件的渲染结果:
由于命名的习惯,请注意camelCase和kebab-case:HTML 特性不区分大小写。名字形式为 camelCase 的 prop 用作特性时,需要转为 kebab-case(短横线隔开)。
根据vue响应的特性,props也可以是动态的:
类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 绑定动态 Props 到父组件的数据。每当父组件的数据变化时,也会传导给子组件:
<div> <input v-model="parentMsg"> <br/> <child v-bind:my-message="parentMsg"></child> </div>
也可以使用v-bind的缩写语法来简化绑定:
<child :my-message="parentMsg"></child>
渲染结果:
改变输入框的值,子组件的文本会跟着改变
关于props的其他介绍,请参考 :props
3.父子组件的通信
子组件可以用 this.$parent 访问它的父组件。根实例的后代可以用 this.$root 访问它。父组件有一个数组 this.$children ,包含它所有的子元素。