接着前面的内容:https://www.cnblogs.com/yanggb/p/12629705.html

处理边界情况

这里记录的都是和处理边界情况有关的功能,即一些需要对vue的规则做一些小调整的特殊情况。不过要注意的是,这些功能都是有劣势或危险的场景的。官方文档中在每个案例中都有注明,所以当你使用每个功能的时候要稍加留意。

访问元素&组件

在绝大多数的情况下,我们最好不要触达另一个组件实例的内部或手动操作dom元素。不过因为vue本身的局限性,也确实需要在一些情况下做这些事情。

访问根实例

在每个【new Vue】实例的子组件中,其根实例可以通过【$root】全局属性进行访问。例如,在这个根实例中:

// Vue 根实例
new Vue({
data: {
foo: 1
},
computed: {
bar: function () { /* ... */ }
},
methods: {
baz: function () { /* ... */ }
}
})

所有的子组件都可以将这个实例作为一个全局的store来访问或使用。

// 获取根组件的数据
this.$root.foo // 写入根组件的数据
this.$root.foo = 2 // 访问根组件的计算属性
this.$root.bar // 调用根组件的方法
this.$root.baz()

对于demo或者非常小型的有少量组件的应用来说,这是很方便的语法,不过这个模式扩展到中大型的应用的话就不然了。因此在绝大多数的情况下,官方文档强烈推荐使用vuex来管理应用的状态。

访问父级组件实例

和【$root】全局属性类似,【$parent】全局属性也可以用来从一个子组件中访问父组件的实例。它提供了一种机会,可以在后期随时触达父级组件,以替代将数据以prop的方式传入子组件的方式。

要注意的是,在绝大多数的情况下,触达父级组件会使得你的应用难以调试和理解,尤其是当你变更了父级组件的数据的时候。当你后期维护那个组件的时候,就会很难找出变更是从哪里发起的。

另外在一些可能适当的时候,你会需要特别地共享一些组件库。举个例子,在和javascript api进行交互而不渲染html的抽象组件内,诸如这些假设性的google地图组件一样:

<google-map>
<google-map-markers v-bind:places="iceCreamShops"></google-map-markers>
</google-map>

这个<goole-map>组件可以定义一个map属性,所有的子组件都需要访问它。在这种情况下<google-map-markers>可能想要通过类似【this.$parent.getMap】的方式访问那个地图,以便为其添加一组标记。请留意,尽管如此,通过这种模式构建出来的那个组件的内部仍然是容易出现问题的。比如,设想以下我们添加了一个新的<google-map-region>组件,当<google-map-markers>在其内部出现的时候,只会渲染那个区域内的标记:

<google-map>
<google-map-region v-bind:shape="cityBoundaries">
<google-map-markers v-bind:places="iceCreamShops"></google-map-markers>
</google-map-region>
</google-map>

那么这时候在<google-map-markers>的内部你可能发现自己需要一些类似这样的hack:

var map = this.$parent.map || this.$parent.$parent.map

很快它就会失控。因此官方文档针对需要向更深层级的组件提供上下文信息的时候推荐使用【依赖注入】的方式,在后面有相关知识。

访问子组件实例或子元素

尽管存在prop和事件,有的时候你仍可能需要在javascript里直接访问一个子组件。为了达到这个目的,你可以通过ref这个属性为子组件赋予一个id引用。例如:

<base-input ref="usernameInput"></base-input>

现在在你已经定义了这个ref的组件里,你就可以使用【$.ref】全局属性来访问这个<base-input>实例:

this.$refs.usernameInput

在这个案例中,如果你想要程序化地从一个父级组件聚焦这个输入框,你就可以这么做。此外,这个<base-input>组件也可以使用一个类似的【ref】属性提供对内部这个指定元素的访问:

<input ref="input">

然后可以定义方法给父级组件使用:

methods: {
// 用来从父级组件聚焦输入框
focus: function () {
this.$refs.input.focus()
}
}

这样就允许了父级组件通过下面的代码聚焦<base-input>里的输入框:

this.$refs.usernameInput.focus()

当【ref】属性和【v-for】指令一起使用的时候,你所得到的引用将会是一个包含了对应数据源的这些子组件的数组。

另外要特别注意的是,【$refs】全局属性只会在组件渲染完成之后生效,并且它们并不是响应式的。这样的语法只是作为一个用于直接操作子组件的不得已措施,开发者应该尽量避免在模板或计算属性中访问【$refs】。

依赖注入

在此之前,在描述访问父级组件实例的时候,展示过这样一个类似的例子:

<google-map>
<google-map-region v-bind:shape="cityBoundaries">
<google-map-markers v-bind:places="iceCreamShops"></google-map-markers>
</google-map-region>
</google-map>

在这个组件里,所有的<goole-map>组件的后代都需要访问一个getMap方法,以便知道要跟哪个地图进行交互。不幸的是,使用【$parent】属性无法很好地拓展到更深层次的嵌套组件上。这就是依赖注入的用武之地,它提供了两个新的实例选项:【provide】和【inject】。

【provide】选项允许我们指定我们想要提供给给后代组件的数据/方法。在这个例子中,就是<google-map>内部的getMap方法。

provide: function () {
return {
getMap: this.getMap
}
}

然后在任何的后代组件里,我们都可以使用【inject】选项来接收指定的我们想要添加在这个示例上的属性:

inject: ['getMap']

相比于【$parent】全局属性来说,这个用法可以让我们在任意的后台组件中访问getMap方法,而不需要暴露整个<google-map>实例。这样的语法允许我们更好地持续研发该组件,而不需要担心我们可能会改变/移除一些子组件依赖的东西。同时,这些组件之间的接口是始终明确定义的,就和props一样。而实际上呢,我们是可以把依赖注入看作一部分【大范围有效的prop】,除了:

1.祖先元素不需要知道哪些后代组件使用它提供的属性(不需要像props那样在引用的子组件实例中显式传递)。

2.后代组件不需要知道被注入的属性来自哪里(可能来自爸爸,可能来自爸爸的爸爸,可能来自爸爸的爸爸的爸爸...)。

然而,依赖注入还是有负面影响的。它会将你的应用程序中的组件与它们当前的组织方式耦合起来,使得重构变得更加困难。与此同时,其所提供的属性也是非响应式的(getMap方法不会随着父组件数据变化自动实时触发)。这是出于设计的考虑,因为使用它们来创建一个中心化规模化的数据和使用【$root】全局属性来做这件事都是不够好的。如果你想要共享的这个属性式你的应用特有的,而不是铜汞化的,或者你想要在祖先组件中更新所提供的数据,那么这意味着你可能需要换用一个像vuex这样真正的状态管理方案。

"我还是很喜欢你,像萋萋野草生故里,荒芜四季。"

vue2.x学习笔记(十八)的更多相关文章

  1. python3.4学习笔记(十八) pycharm 安装使用、注册码、显示行号和字体大小等常用设置

    python3.4学习笔记(十八) pycharm 安装使用.注册码.显示行号和字体大小等常用设置Download JetBrains Python IDE :: PyCharmhttp://www. ...

  2. (C/C++学习笔记) 十八. 继承和多态

    十八. 继承和多态 ● 继承的概念 继承(inheritance): 以旧类为基础创建新类, 新类包含了旧类的数据成员和成员函数(除了构造函数和析构函数), 并且可以派生类中定义新成员. 形式: cl ...

  3. Java基础学习笔记十八 异常处理

    什么是异常?Java代码在运行时期发生的问题就是异常. 在Java中,把异常信息封装成了一个类.当出现了问题时,就会创建异常类对象并抛出异常相关的信息(如异常出现的位置.原因等). 异常的继承体系 在 ...

  4. MYSQL进阶学习笔记十八:MySQL备份和还原!(视频序号:进阶_37)

    知识点十九:MySQL的备份的还原(38) 一.mysql的备份 1.通过使用mysqldump的命令备份 使用mysqldump命令备份,mysqldump命令将数据库中的数据备份成一个文本文件.表 ...

  5. vue2.x学习笔记(八)

    接着前面的内容:https://www.cnblogs.com/yanggb/p/12577433.html. 列表渲染 vue提供了一个[v-for]指令用于列表渲染(循环). 用[v-for]指令 ...

  6. JavaScript权威设计--事件冒泡,捕获,事件句柄,事件源,事件对象(简要学习笔记十八)

    1.事件冒泡与事件捕获 2.事件与事件句柄   3.事件委托:利用事件的冒泡技术.子元素的事件最终会冒泡到父元素直到跟节点.事件监听会分析从子元素冒泡上来的事件. 事件委托的好处:     1.每个函 ...

  7. python 学习笔记十八 django深入学习三 分页,自定义标签,权限机制

    django  Pagination(分页) django 自带的分页功能非常强大,我们来看一个简单的练习示例: #导入Paginator>>> from django.core.p ...

  8. SharpGL学习笔记(十八) 解析3ds模型并显示

    笔者设想的3D仿真中的元件,是不可能都是“画”出来的.这样就玩复杂了,应该把任务分包出去,让善于制作模型的软件来制作三维模型,我们只需要解析并且显示它即可. 3dsmax制作三维模型的方便,快捷,专业 ...

  9. PHP学习笔记十八【构造函数】

    <?php class Person{ public $name; public $age; //定义构造函数 function 空格__construct 构造方法没有返回值,对象自动调用 p ...

  10. Python3学习笔记十八

    1.    MTV M:   model     与数据库相关 T:   Template    与html相关 V:   views      与逻辑相关 一.    URL配置 启动:python ...

随机推荐

  1. [暴力] Educational Codeforces Round 71 (Rated for Div. 2) B. Square Filling (1207B)

    题目:http://codeforces.com/contest/1207/problem/B   B. Square Filling time limit per test 1 second mem ...

  2. java获取近几天的日期

    最近在写接口的时候老遇见从mysql中获取近几天数据的需求,获取日期这块不是很熟,网上看了很多但是代码量都太大,还是问了下别人,写了三行代码就解决了,不多说 贴代码了 下面是我获取近十天,每天的日期: ...

  3. mysql系列-⼀条SQL查询语句是如何执⾏的?

    ⼀条SQL查询语句是如何执⾏的? ⼤体来说,MySQL 可以分为 Server 层和存储引擎层两部分 Server 层 Server 层包括连接器.查询缓存.分析器.优化器.执⾏器等,涵盖 MySQL ...

  4. 生日Party 玄学多维DP

    题目描述 今天是hidadz小朋友的生日,她邀请了许多朋友来参加她的生日party. hidadz带着朋友们来到花园中,打算坐成一排玩游戏.为了游戏不至于无聊,就座的方案应满足如下条件:对于任意连续的 ...

  5. JDK的sql设计不合理导致的驱动类初始化死锁问题

    问题描述 当我们一个系统既需要mysql驱动,也需要oracle驱动的时候,在并发加载初始化这些驱动类的过程中产生死锁的可能性非常大,下面是一个模拟的例子,对于Thread2的实现其实是jdk里jav ...

  6. coding++:高并发解决方案限流技术--计数器--demo

    1.它是限流算法中最简单最容易的一种算法 计数器实现限流 每分钟只允许10个请求 第一个请求进去的时间为startTime,在startTime + 60s内只允许10个请求 当60s内超过十个请求后 ...

  7. [noip模拟]心<并查集>

    背景描述: 不是一切深渊都是灭亡 不是一切灭亡都覆盖在弱者的头上 ——<这也是一切> 舒婷 有N个透明的盒子, 每个盒子里面有两个不同颜色的球, 总共有M种颜色. Alice和Bob又在玩 ...

  8. IdentityServer 部署踩坑记

    IdentityServer 部署踩坑记 Intro 周末终于部署了 IdentityServer 以及 IdentityServerAdmin 项目,踩了几个坑,在此记录分享一下. 部署架构 项目是 ...

  9. js函数基础回顾

    回头又跑去看了下尚硅谷的js基础视频 https://www.bilibili.com/video/av22958172/?p=51. 便做了如下笔记: 1.函数也是一个对象 2.函数可以封装一些功能 ...

  10. 码云客户端Gitee使用1上传项目

    目前主流的源码仓库有GitHub,这是微软公司的全球最大的代码仓库.里面有来自全世界开发者提供的开源项目或者个人私有项目.它分为个人免费与企业收费两种模式,对于个人学习或者项目开发小组来说个人免费版完 ...