系列目录地址

  • 一、基础知识概览

    • 第一章 - 一些基础概念(posted at 2018-10-31)
    • 第二章 - 常见的指令的使用(posted at 2018-11-01)
    • 第三章 - 事件修饰符的使用(posted at 2018-11-02)
    • 第四章 - 页面元素样式的设定(posted at 2018-11-05)
    • 第五章 - 计算属性与监听器(posted at 2018-11-08)
    • 第六章 - 按键修饰符的使用(posted at 2018-11-15)
    • 第七章 - Vue 实例的生命周期(posted at 2018-12-13)
  • 二、深入了解 Vue
    • 第八章 - 组件的基础知识(posted at 2019-01-03)
    • 第九章 - 组件基础再探(data、props)(posted at 2019-03-09)

前言

在上一章的学习中,我们学习了 Vue 中组件的基础知识,知道了什么是组件,以及如何创建一个全局/局部组件。不知道你是否记得,在上一章中,我们提到组件是一个可以复用的 Vue 实例,它与 Vue 实例也只是拥有些许的差异。本章,我们将继续学习组件的相关基础知识,了解 Vue 的组件中的 data、prop 选项的使用。

仓储地址:Chapter02-Bronze Component Advance

干货合集

一、 组件中的 data 选项

当一个 Vue 实例被创建之后,实例中的 data 选项的属性值就与页面的视图做了一个“绑定”,当我们修改 data 中的属性值时,视图就会产生“响应”,同时,页面上使用到属性值的地方也会同步更新。那么,组件作为一个特殊的 Vue 实例,对于 data 选项的使用上是不是和在 Vue 实例中的使用方式相同呢。

首先,我们还是先创建一个全局组件,按照 Vue 实例中使用 data 选项的使用方法,将 data 选项添加到组件的定义中,同时,使用插值表达式在页面中显示出属性值,示例代码如下。

<div id="app"><tmpl></tmpl>
</div><template id="tmpl"><div><h3>这是全局组件,啊啊啊啊啊啊</h3><h4>{{name}}</h4></div>
</template><script>Vue.component('tmpl', {template: '#tmpl',data: {name: 'zhangsan'}});var vm = new Vue({el: '#app',data: {}});
</script>
复制代码

运行我们的代码,发现页面上并没有显示出数据,看下控制台,嗯,报错了。我们一条条的看报错信息。

第一条报错信息,在创建组件实例中的 data 选项时,返回的应该是一个实例对象的方法。什么意思呢?回想一下我们在创建 Vue 实例时添加 data 选项,我们创建的是一个 data 对象,而根据控制台的报错信息提示,当我们在组件中使用 data 选项时,我们需要返回包含实例对象的方法,我们可以按照这个提示修改试试。

<script>Vue.component('tmpl', {template: '#tmpl',data: function () {return {name: 'zhangsan'}}});
</script>
复制代码

可以看到,在组件的 data 选项中,我们将 data 选项定义成一个方法,并在这个方法中返回了一个对象实例,此时,刷新页面,可以看到两条错误信息已经都不见了,页面也已经可以正常显示出数据。

为什么会这样呢,查看 Vue 的官方文档后,我们可以找到这样一句解释:一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝。

返回对象的独立的拷贝,再联系上面报错信息提到的,在方法中返回对象实例,是不是说,当我们在方法中返回的是一个定义好的对象,会出问题呢?

我们来继续试试。这里,我们将在 data 选项中返回的对象改成在外部定义,同时,多次调用这个组件,完整的示例代码如下。

<div id="app"><counter></counter><hr /><counter></counter>
</div><template id="counter"><div><button @click="add"> Add </button><h3>count:{{count}}</h3></div>
</template><script>var dataObj = {count: 0}Vue.component('counter', {template: '#counter',data: function () {return dataObj},methods: {add() {dataObj.count++}},})var vm = new Vue({el: '#app',data: {}});
</script>
复制代码

可以看到,因为我们在 data 中返回的对象并不是一个新的对象实例,当我们修改返回对象中的属性值时,所有使用到当前组件的地方都会发生变更,这无疑是无法接受的。因此,为了避免这一情况,当我们需要在创建组件时需要添加 data 选项,我们需要在 data 方法中返回对象实例,而不是一个已经定义好的对象。

二、 组件中的 props 选项

组件的 Props 选项是我们可以在组件上注册的一些自定义特性,当我们将一个值传递给一个 props 选项中的特性时,那个 prop 特性就变成了组件实例的一个属性,这时候,我们当然就可以获取到这个值了,因此,组件中的 props 经常用于将我们的父组件值传递到子组件或是将 Vue 实例中的属性值传递到组件中使用。

在父组件/Vue实例引用子组件的时候,通过属性绑定的方式(v-bind),将需要传递给子组件的数据进行传递,从而在子组件内部,通过绑定的属性值获取到父组件/Vue实例的数据。

例如,在下面的代码中,我在 Vue 实例中定义了一个局部组件,将实例的 title 属性绑定到组件的 parenttitle 属性上,同时,将 parenttitle 属性赋值给组件的 content 属性,从下面的代码中不难看出,我们希望的是可以实时获取到父组件的 title 属性值。

PS:这里和之前定义组件名称一样,因为在 HTML 中,对于大小写是不敏感的,因此,如果这里你采用了 camelCase (驼峰命名法) ,在使用时,依然需要将属性名称用其等价的 kebab-case (短横线分隔命名) 来指明。

<div id="app"><h4>请输入需要传递给子组件的值:<input type="text" v-model="title" /></h4><child-node v-bind:parenttitle="title"></child-node>
</div><template id="child"><div><h4>Vue 实例中的属性值为:{{content}}</h4></div>
</template><script>var vm = new Vue({el: '#app',data: {title: ''},components: {'childNode': {template: '#child',props: ['parenttitle'],data() {return {content: this.parenttitle}}}},});
</script>
复制代码

可以看到,结果似乎和我们想的不一样,虽然可以在绑定的 parenttitle 属性上实时获取到 Vue 实例的属性值,可是,这里却无法同步更新组件的 content 属性。仔细分析下可以我们就不难看出,组件的 data 选项中的 content 属性是一个 String 类型的变量,也就是 js 中的基本数据类型,在创建时就已经将数据值写入到内存栈中,之后与初始赋值的数据就没有任何的关系,因此,后面对于 Vue 实例的 title 属性的任何变更,都不会引起对于实例 content 属性的变化。

因此,如果我们想完成最开始的需求的话,有两种可行的解决办法:

1、将 Vue 实例中的 title 属性改为一个对象,输入的值作为对象中的一个属性,因此,我们在实例中绑定的 parenttitle 也将为一个对象。因为 js 中的对象为引用类型,赋值时,是将存储数据的地址进行拷贝,因此,title 对象和 parenttitle 对象将指向同一地址,这时,任何对于 title 对象的属性值的修改,都会引起 parenttitle 对象中属性值得改变。

2、采取 watch 监听 parenttitle 的方式来同步更新实例的 content 属性。

这里,我采用第二种方式,使用 watch 监听器来同步变更组件中的 content 属性值,修改代码如下。

<script>var vm = new Vue({el: '#app',data: {title: ''},components: {'childNode': {template: '#child',props: ['parenttitle'],data() {return {content: this.parenttitle}},watch: {parenttitle() {this.content = this.parenttitle}},}},});
</script>
复制代码

既然可以将 Vue 实例的数据传递到子组件中进行使用,那么,我们是不是可以在子组件进行修改绑定的属性值,从而影响到 Vue 实例呢?我们来继续尝试。

在上面的实例代码的基础上,我们为子组件的 h4 标签添加一个点击事件 change,通过 change 事件,我们来修改绑定的属性值 parenttitle,看看会不会造成对于 Vue 实例中的 title 属性的影响。

<div id="app"><h4>请输入需要传递给子组件的值:<input type="text" v-model="title" /></h4><child-node v-bind:parenttitle="title"></child-node>
</div><template id="child"><div><h4 @click="change">Vue 实例中的属性值为:{{content}}</h4></div>
</template><script>var vm = new Vue({el: '#app',data: {title: ''},components: {'childNode': {template: '#child',props: ['parenttitle'],data() {return {content: this.parenttitle}},watch: {parenttitle() {this.content = this.parenttitle}},methods: {change() {this.parenttitle = '9999999999999'}}}},});
</script>
复制代码

可以看到,我们虽然修改了组件的 parenttitle 属性值,却没有影响到 Vue 实例中的 title 属性,所以我们可以得出,所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。

总结

本章,主要是介绍了我们如何在组件中使用 data 选项和 props 选项,以及在使用过程中一些与 Vue 实例中使用方式不同的地方,同时,介绍了如何将父组件中的属性值传递到子组件中。既然父组件可以将属性值传递到子组件中,毫无疑问,我们也可以将子组件的属性传递到父组件中,父子组件之间进行属性传递的方式,我将放在下一章中进行介绍。

参考

1、Vue.js——60分钟组件快速入门(上篇)

2、认识Vue组件

3、Vue 2.0学习笔记:组件的使用

4、初学vue2.0-组件-文档理解笔记v1.0

5、Vue组件选项props

占坑

作者:墨墨墨墨小宇
        个人简介:96年生人,出生于安徽某四线城市,毕业于Top 10000000 院校。.NET程序员,枪手死忠,喵星人。于2016年12月开始.NET程序员生涯,微软.NET技术的坚定坚持者,立志成为云养猫的少年中面向谷歌编程最厉害的.NET程序员。
        个人博客:yuiter.com
        博客园博客:www.cnblogs.com/danvic712

【Vue.js 牛刀小试】:第九章 - 组件基础再探(data、props)相关推荐

  1. Vue.js 牛刀小试(持续更新~~~)

    一.前言 这个系列的文章开始于今年9月从上一家公司辞职后,在找工作的过程中,觉得自己应该学习一些新的东西,从前几章的更新日期也可以看出,中间隔了很长的时间,自己也经历了一些事情,既然现在已经稳定了,就 ...

  2. 前端-Vue.js从入门到精通基础笔记(理论+实操+知识点速查)

    #[2022.3]尚硅谷Vue.js从入门到精通基础笔记(理论+实操+知识点速查) 前言 本文完全基于 参考资料:加工整理而成,包括其代码,案例,资源等.前置知识是学习尚硅谷的视频教程,本文配合其教程 ...

  3. vue.js路由配置vue-router的基础学习 - 概念篇

    文章目录 引言 · 相关问题小结: 一.动态路由匹配 (两种情况) A. 两种情况,代码对比: B. 两种情况,效果图对比: C. 提醒 · 仔细体会: D. 优先级的问题: 二.嵌套路由 引言 · ...

  4. 基于Vue.js的表格分页组件

    转载自 基于Vue.js的表格分页组件 有一段时间没更新文章了,主要是因为自己一直在忙着学习新的东西而忘记分享了,实在惭愧. 这不,大半夜发文更一篇文章,分享一个自己编写的一个Vue的小组件,名叫Bo ...

  5. 移动端cube界面设计html,滴滴开源基于 Vue.js 的移动端组件库 cube-ui

    原标题:滴滴开源基于 Vue.js 的移动端组件库 cube-ui 开源最前线(ID:OpenSourceTop) 猿妹 整编 综合自:https://didi.github.io/cube-ui/ ...

  6. iView 3.3.0 发布,基于 Vue.js 的企业级 UI 组件库

    iView 3.3.0 发布了,代号 Transistor ,iView 是一套基于 Vue.js 的企业级 UI 组件库,主要服务于 PC 界面的中后台产品. 本次更新如下: https://www ...

  7. Vue.js父与子组件之间传参 父向子组件传参   例子:App.vue为父,引入componetA组件之后,则可以在template中使用标签(注意驼峰写法要改成componet-a写法,因为ht

    Vue.js父与子组件之间传参 父向子组件传参 例子:App.vue为父,引入componetA组件之后,则可以在template中使用标签(注意驼峰写法要改成componet-a写法,因为html对 ...

  8. iView 3.4.0 发布,基于 Vue.js 的企业级 UI 组件库

    百度智能云 云生态狂欢季 热门云产品1折起>>>   iView 3.4.0 发布了,iView 是一套基于 Vue.js 的企业级 UI 组件库,主要服务于 PC 界面的中后台产品 ...

  9. Mint UI —— 基于 Vue.js 的移动端组件库

    写文章登录 Mint UI -- 基于 Vue.js 的移动端组件库 杨奕 8 个月前 Mint UI GitHub:https://github.com/ElemeFE/mint-ui 项目主页:h ...

最新文章

  1. springboot处理参数再转发请求_SpringBoot图文教程6—SpringBoot中过滤器的使用
  2. 通过设置Ionic-Cli代理解决ionic serve跨域调试问题
  3. mac下mysql的安装
  4. Truffle 4.0、Geth 1.7.2、TestRPC在私有链上搭建智能合约
  5. 两块 硬盘 主从盘跳线详解
  6. DDNS For RHEL5
  7. 设计模式学习笔记——命令模式
  8. 服务器文件地址怎么写,服务器里的文件链接地址怎么写
  9. 360mysql连接池_自己动手写个数据库连接池
  10. 螃蟹保存方法保存时间_螃蟹吃不完怎么保存?学会这4招,不论是海蟹、河蟹通通都不愁...
  11. python抢购软件/插件/脚本附完整源码
  12. kubernetes Pod驱逐机制
  13. 洛谷P1039 侦探推理
  14. OneNote用完画笔怎么从绘图模式回到打字模式
  15. TSGCTF 2021 Welcome to TSG CTF! WP
  16. 吐血!解决vmware中虚拟机开机黑屏的最终方法
  17. ngnix配置及实例
  18. 基于多特征的技术融合关系预测及其价值评估
  19. 英雄联盟世界的地图抓取与分析
  20. 北京Linux运维培训怎么选?

热门文章

  1. 音频数据文件格式(PCM,WAV,MIDI)简记
  2. JNDI学习总结(1)——JNDI入门
  3. Android使用Apache HttpClient发送GET、POST请求
  4. 用户控件中动态加入脚本引用
  5. 如何定位cpu占用率高的java线程
  6. 在if里赋值要注意=和==的优先级,==优先于=
  7. 构建之法第四、第五章读后感
  8. 【UML】状态图Statechart diagram(转)
  9. vue.js 多图上传,并可预览
  10. iOS-APP提交上架流程(新手必看!2016年3月1日最新版)