Skip to content

Commit

Permalink
props通信
Browse files Browse the repository at this point in the history
  • Loading branch information
丁一鸣 authored and 丁一鸣 committed Nov 20, 2015
1 parent be703fa commit 9244676
Show file tree
Hide file tree
Showing 2 changed files with 219 additions and 0 deletions.
183 changes: 183 additions & 0 deletions demos/20151120周五笔记.md
Original file line number Diff line number Diff line change
Expand Up @@ -587,3 +587,186 @@ new Vue({
```
> 这种封装也适用于其它资源,如指令、过滤器和过渡。
### 注册语法糖
为了更简单,可以直接传入选项对象而不是构造器给`Vue.component()`和`component`选项,Vuejs在背后自动调用`Vue.extend()`:
```
// 在一个步骤中扩展与注册
Vue.component('my-component', {
template: '<div>A custom component!</div>'
})

// 局部注册也可以这么做
var Parent = Vue.extend({
components: {
'my-component': {
template: '<div>A custom component!</div>'
}
}
})
```
### 组件选项问题
传入 Vue 构造器的多数选项也可以用在 Vue.extend() 中,不过有两个特例: data and 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() 中时也须是一个函数。
### is 特性
一些 HTML 元素,如 <table>,限制什么元素可以放在它里面。自定义元素不在白名单上,将被放在元素的外面,因而渲染不正确。这时应当使用 is 特性,指示它是一个自定义元素:
```
<table>
<tr is="my-component"></tr>
</table>
```
## Props
### 使用Props 传递数据
组件实例的作用域是孤立的,这意味着不能并且不应该在子组件的模板内直接引用父组件的数据。可以使用 props 把数据传给子组件。
“prop” 是组件数据的一个字段,期望从父组件传下来。子组件需要显式地用 props 选项 声明 props:
```
Vue.component('child', {
// 声明 props
props: ['msg'],
// prop 可以用在模板内
// 可以用 `this.msg` 设置
template: '<span>{{ msg }}</span>'
})

//然后向它传入一个普通字符串:
<child msg="hello!"></child>

```
### camelCase vs.kebab-case
HTML 特性不区分大小写。名字形式为 camelCase 的 prop 用作特性时,需要转为 kebab-case(短横线隔开):
```
Vue.component('child', {
// camelCase in JavaScript
props: ['myMessage'],
template: '<span>{{ myMessage }}</span>'
})

<!-- kebab-case in HTML -->
<child my-message="hello!"></child>

```
### 动态Props
类似于绑定一个普通的特性到一个表达式,也可以用 v-bind 绑定动态 Props 到父组件的数据。每当父组件的数据变化时,也会传导给子组件:
```
<div>
<input v-model="parentMsg">
<br>
<child v-bind:my-message="parentMsg"></child>
</div>

//v-bind 的缩写语法通常更简单:
<child :my-message="parentMsg"></child>
```
### 字面量语法 vs 动态语法
初学者常犯的一个错误是使用字面量语法传递数值:
```
<!-- 传递了一个字符串 "1" -->
<comp some-prop="1"></comp> x
```
因为它是一个字面 prop,它的值以字符串 "1" 而不是以实际的数字传下去。如果想传递一个实际的 JavaScript 数字,需要使用动态语法,从而让它的值被当作 JavaScript 表达式计算:
```
<!-- 传递实际的数字 -->
<comp :some-prop="1"></comp>
```
### Prop绑定类型
prop 默认是单向绑定:当父组件的属性变化时,将传导给子组件,但是反过来不会。这是为了防止子组件无意修改了父组件的状态——这会让应用的数据流难以理解。不过,也可以使用 .sync 或 .once 绑定修饰符显式地强制双向或单次绑定:
```
<!-- 默认为单向绑定 -->
<child :msg="parentMsg"></child>

<!-- 双向绑定 -->
<child :msg.sync="parentMsg"></child>

<!-- 单次绑定 -->
<child :msg.once="parentMsg"></child>
```
双向绑定会把子组件的 msg 属性同步回父组件的 parentMsg 属性。单次绑定在建立之后不会同步之后的变化。
> 注意如果 prop 是一个对象或数组,是按引用传递。在子组件内修改它会影响父组件的状态,不管是使用哪种绑定类型。
### Prop验证
组件可以为 props 指定验证要求。当组件给其他人使用时这很有用,因为这些验证要求构成了组件的 API,确保其他人正确地使用组件。此时 props 的值是一个对象,包含验证要求:
```
Vue.component('example', {
props: {
// 基础类型检测 (`null` 意思是任何类型都可以)
propA: Number,
// 必需且是字符串
propB: {
type: String,
required: true
},
// 数字,有默认值
propC: {
type: Number,
default: 100
},
// 对象/数组的默认值应当由一个函数返回
propD: {
type: Object,
default: function () {
return { msg: 'hello' }
}
},
// 指定这个 prop 为双向绑定
// 如果绑定类型不对将抛出一条警告
propE: {
twoWay: true
},
// 自定义验证函数
propF: {
validator: function (value) {
return value > 10
}
}
}
})

```
type 可以是下面原生构造器:
String
Number
Boolean
Function
Object
Array
> type 也可以是一个自定义构造器,使用 instanceof 检测。
当 prop 验证失败了,Vue 将拒绝在子组件上设置此值,如果使用的是开发版本会抛出一条警告。
## 父子组件通信
### 父链
子组件可以用 this.$parent 访问它的父组件。根实例的后代可以用 this.$root 访问它。父组件有一个数组 this.$children,包含它所有的子元素。
尽管可以访问父链上任意的实例,不过子组件应当避免直接依赖父组件的数据,应当显式地使用 props 传递数据。另外,在子组件中修改父组件的状态是非常糟糕的做法,因为:
这让父组件与子组件紧密地耦合;
只看父组件,很难理解父组件的状态。因为它可能被任意子组件修改!理想情况下,只有组件自己能修改它的状态。
36 changes: 36 additions & 0 deletions demos/demo16.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>父子组件传毒数据 用Props</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<link rel="stylesheet" href="assets/boot4/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/css/base.css">
</head>
<body>
<div id="demo">
<child msg="hello!xxx"></child>
</div>

<script src="assets/boot4/jquery.min.js"></script>
<script src="assets/boot4/bootstrap.min.js"></script>
<script src="assets/vuejs/vue.min.js"></script>

<script>
Vue.component('child',{
//声明props
props:['msg'],

//prop 可以用在模板内
//可以用 this.msg 设置
template : '<span>{{msg}}</span>'
})

new Vue({
el:'#demo'
})
</script>

</body>
</html>

0 comments on commit 9244676

Please sign in to comment.