Props 传递数据
在 Vue 中每个组件都是独立的,不能也不应该直接访问父类的data。所以我们通过 props 来向子组件传递数据,是不是和 React 的方式很像?
不同于 React,在 Vue 中子组件需要先声明自己的 props 才行:
rush:js;">
var Profile = Vue.extend({
props: ["name"],template: `
{{name}}'s Todo List
{{name}} is a good girl
`
});
然后我们可以在使用 Profile 的时候这样传递参数:
这种是通过字面量传递参数,所以传递的值一定是字符串。还有一种方式是动态传参,通过 v-bind 来传递参数,可以双向绑定数据或者传非字符串参数:
v-bind 如果是一个字符串,则是绑定父组件的data中对应的字段,比如上面就是双向绑定了 input 的值。如果是一个数字则就是绑定了一个数字。
Vue 还可以显式指定单向还是双向的数据绑定:
rush:js;">
<child :msg.sync="parentMsg">
<child :msg.once="parentMsg">
Props 校验
一个好的组件总是应该先验证参数是否正确,另外可能还需要设置一些参数的默认值:
rush:js;">
var Profile = Vue.extend({
input: {
type: String
}
});
父子组件通信
上面讲到的 props 其实就是父组件向子组件传递消息的一种方式。
在子组件中有一个 this.$parent 和 this.$root 可以用来方法父组件和根实例。不过,现在我们应该避免这么做。因为组件本身就是为了封装独立的逻辑,如果又去直接访问父组件的数据就破坏了组件的封装性。
所以我们应该还是应该通过父组件向子组件传递 props 的方式来通信。
当然 props 其实只能做回调。在 React 中就探讨过这个问题,React 的做法就是通过 props 来做,传一个回调函数给子组件。其实我不是很喜欢这种把回调函数传来传去的方式,我更喜欢的是事件的方式。Vue 中子组件可以通过通过事件和父组件进行通信的。向父组件发消息是通过 this.$dispatch,而向子组件发送消息是通过 this.$boardcast,这里都是向所有的父亲和孩子发送消息,但是一旦执行一个回调之后就会停止,除非这个回调函数显式返回了 true。
我们把之前的Todo List拆成不同的组件来实现,这样可以体验下如何进行组件的双向通信,我们拆分出两个组件,分别是 List 和 Form 。
Form 负责处理用户输入,并在提交表单的时候向父组件发送一个 add 消息,代码如下:
rush:js;">
var Form = Vue.extend({
props: {
username: {
type: String,default: "Unnamed"
}
},data: function() {
return {
input: "",};
},template: `
{{username}}'s Todo List
`,methods: {
add: function() {
this.$
dispatch("add",this.input); //这里就是向父组件发送消息
this.input = "";
}
}
});
List 只负责展示列表和处理用户勾选操作,它接收到 add 消息之后会在自己上添加一个条目:
rush:js;">
var List = Vue.extend({
template: `
`,props: {
initList: {
type: Array
}
},data: function() {
return {
list: []
}
},events: {
add: function(input) {
if(!input) return false;
this.list.unshift({
title: input,done: false
});
}
}
});
然后,因为这是两个组件,当然需要一个 Vue 实例来引导启动,我们的实例如下:
rush:js;">
var vm = new Vue({
el: "#t
odo",components: {
"t
odo-form": Form,"t
odo-list": List
},events: {
add: function(input) {
this.$
broadcast("add",input);
}
}
});
注意,其实 Form 和 List 在逻辑上是平级的组件,所以他们没有父子关系,他们共同都是 vm 的孩子。这里 vm 接到 Form 的消息之后会转发给 List。
html 代码就更简单了:
Slot
通过 Slot 可以实现把父组件渲染出来的HTML插入到子组件中,目前还不清楚什么时候会需要这样做,而且这么做对子组件的侵入性太大。
动态切换组件
这个功能感觉有点多余,感觉很多情况下我们应该是通过逻辑代码来实现切换,而不是通过Vue内置的动态组件来切换。不过用来实现一个类似 tab 切换的功能还是很方便的。
我们这里给 Todo List 增加一个 about 页面。那么首先我们需要把 vm 改成一个组件,这个组件叫 Todo,它就是整个 Todo 页面:
rush:js;">
var T
odo = Vue.extend({
template: `
odo">
not show
`,input);
}
}
});
其实改动就第一行。
然后我们需要创建一个 About 组件:
rush:js;">
var About = Vue.extend({
template: `
About T
odo List V0.1.0
Content here
`
});
接下来是重点了,我们要创建一个实例 vm,这vm要负责切换这两个页面:
rush:js;">
var vm = new Vue({
el: "body",data: {
currentView: "t
odo"
},components: {
"t
odo": T
odo,"about": About
}
});
这里我们定义了一个 currentView 字段,当然可以是任意名称,然后通过特殊的 component 标签来进行组件切换:
上面的代码有两处需要注意:
•通过 component这个特殊标签,然后用 :is 属性来进行组件的切换。
•radio 通过双向绑定来修改 currentView 字段,从而实现点击之后就可以进行切换。
数据绑定的实现原理
Vue 把双向绑定称作 reactive,可以翻译为响应式数据绑定。内部是通过 ES5 定义的 getter 和 setter 方法实现的,所以不支持 IE8 及以下浏览器,这种实现方式有两个容易犯错的地方:
•如果在 data 上直接添加和删除属性是无法被检测到的,一般删除是不会的,但是可能会动态添加,这个时候应该通过 vm.$set(“name”,value) 的方式来添加。
•无法检测到对象内部的变化,也就是只能检测 data 的属性变化,如果 data.a 是一个对象,那么 data.a.b = 1 这种变化是无法被检测到的。这种情况下应该创建一个新的对象并赋值给 data.a 就行了。
异步更新机制
Vue 对DOM的更新是异步的! 这个异步是在一个异步队列中进行的,不过这个异步队列会在当前的 Event Loop 中执行完,所以如果修改了 Data 立刻去DOM中做查询操作是不对的,这个时候DOM还没有更新,正确的做法是这样做:
rush:js;">
vm.msg = 'new message' // change data
vm.$el.textContent === 'new message' // false
Vue.nextTick(function () {
vm.$el.textContent === 'new message' // true
})
或者这样:
rush:js;">
vm.$nextTick(function () {
this.$el.textContent === 'new message' // true
})
花了半天时间才看完组件,下面应该去看一下另一个重点:
本文已被整理到了《》,欢迎大家学习阅读。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程之家。
相关文章
可以通过min-width属性来设置el-table-column的最小宽度。以...
yarn dev,当文件变动后,会自动重启。 yanr start不会自动重...
ref 用于创建一个对值的响应式引用。这个值可以是原始值(如...
通过修改 getWK005 函数来实现这一点。这里的 query 参数就是...
<el-form-item label="入库类型" ...
API 变动 样式类名变化: 一些组件的样式类名有所变动,可能需...