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

循环引用

递归组件

组件是可以在它们自己的模板中调用自身的,不过它们只能通过【name】选项来做这件事。

name: 'unique-name-of-my-component'

当你使用【Vue.component】全局注册一个组件的时候,这个全局的id就会自动设置为该组件的【name】选项。

Vue.component('unique-name-of-my-component', {
// ...
})

但是稍有不慎,递归组件就可能会导致无限循环,进而导致页面渲染引擎奔溃的情况:

name: 'stack-overflow',
template: '<div><stack-overflow></stack-overflow></div>'

类似上述的组件将会导致【max stack size exceeded】错误,所以请确保递归调用是有条件的(例如使用一个最终会得到false的【v-if】指令)。

组件之间的循环引用

假设你需要构建一个文件目录树,像资源管理器那样的,你可能就会有一个<tree-folder>组件,模板是这样的:

<p>
<span>{{ folder.name }}</span>
<tree-folder-contents :children="folder.children"/>
</p>

还会有一个<tree-folder-contents>组件,模板是这样的:

<ul>
<li v-for="child in children">
<tree-folder v-if="child.children" :folder="child"/>
<span v-else>{{ child.name }}</span>
</li>
</ul>

当你仔细观察的时候,会发现这些组件在渲染树中互为对方的后代和祖先——一个悖论!当通过【Vue.component】全局注册组件的时候,这个悖论会被自动解开。当时如果你使用的是一个模块系统依赖/导入组件,例如通过webpack或browserify,你就会遇到一个错误:

Failed to mount component: template or render function not defined.

为了解释这里发生了什么,我们先把这两个组件称为A和B。模块系统发现它需要A,但是首先A依赖B,但是B又依赖A,但是A又依赖B,如此反复,就变成了一个死循环,解析器不知道如何不经过其中一个组件而完全解析出另一个组件。因此,为了解决这个问题,我们需要给模块系统一个点,告诉模块系统:A反正是需要B的,但是我们不需要先解析B。

在上面的例子中,我们可以把<tree-folder>组件设为那个点。我们知道,那个产生悖论的子组件是<tree-folder-contents>组件,所以我们会等到生命周期钩子函数【beforeCreate】时去注册它:

beforeCreate: function () {
this.$options.components.TreeFolderContents = require('./tree-folder-contents.vue').default
}

或者,在本地注册组件的时候,你可以使用webpack的异步import(推荐):

components: {
TreeFolderContents: () => import('./tree-folder-contents.vue')
}

这样问题就解决了!

模板定义的替代品

内联模板

当【inline-template】这个特殊的属性出现在一个子组件上的时候,这个组件将会使用其里面的内容作为模板,而不是将其作为被分发的内容。这使得模板的撰写工作更加灵活:

<my-component inline-template>
<div>
<p>These are compiled as the component's own template.</p>
<p>Not parent's transclusion content.</p>
</div>
</my-component>

内联模板需要定义在vue所属的dom元素内。

但是要注意的是,【inline-template】属性会让模板的作用域变得更加难以理解。所以,作为最佳实践,请在组件内优先选择【template】选项或在【.vue】文件里的一个<template>元素来定义模板。

x-template

另一个定义模板的方式是在一个<script>元素中,并为其带上【text/x-template】的类型,然后通过一个id将模板引用过去,例如:

<script type="text/x-template" id="hello-world-template">
<p>Hello hello hello</p>
</script>
Vue.component('hello-world', {
template: '#hello-world-template'
})

要特别注意的是,x-template需要定义在vue所属的dom元素外。

上面的这两种方式可以用于模板特别大的demo或者极小型的应用,但是在其它的情况下请尽量避免使用,因为这回将模板和该组件的其他定义分离开,不利于后期的维护。

控制更新

vue的响应式系统可以知道何时进行dom更新(如果你用对了的话),不过其终究会存在局限性。因此,在一些边界情况你会想要强制更新,尽管表面上看响应式的数据没有发生改变,也有一些情况你会想要阻止不必要的更新。

强制更新

如果你发现你需要在vue中做一次强制更新,官方文档强调,99.9的情况,是你在某个地方做错了事。

你可能还没有留意到数组或对象的变更检测注意事项,或者你可能依赖了一个未被vue响应式系统追踪的状态。然而,如果你已经做到了上述的事项仍然发现在极少数的情况下需要手动强制更新的话,那么你可以通过【$forceUpdate】全局属性来做这件事。

vm.$forceUpdate()

这样会迫使vue实例重新渲染。注意它仅仅影响实例本身和插入插槽内容的子组件,而不是所有的子组件。

通过【v-once】指令创建低开销的静态组件

渲染普通的html元素在vue中是非常快速的,但有的时候你可能有一个组件,这个组件包含了大量的静态内容。在这种情况下,你可以在根元素上添加【v-once】指令以确保这些内容只计算一次然后缓存起来,就像这样:

Vue.component('terms-of-service', {
template: `
<div v-once>
<h1>Terms of Service</h1>
... a lot of static content ...
</div>
`
})

可能前面已经说过了,但是在这里还是要再说一次:要格外注意不要过度使用这个模式。当你需要渲染大量的静态内容的时候,极少数的情况下它会给你带来便利,除非你非常留意渲染变慢了,不然它完全是没有必要的——再加上它在后期会带来很多的困惑。例如,设想另一个开发者并不熟悉【v-once】指令或漏看了它在模板中,他可能会花费很多个小时去找出模板为什么无法被正确更新的原因。

"我还是很喜欢你,像无缘花了荼靡,小楼寂寂。"

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

  1. python3.4学习笔记(二十六) Python 输出json到文件,让json.dumps输出中文 实例代码

    python3.4学习笔记(二十六) Python 输出json到文件,让json.dumps输出中文 实例代码 python的json.dumps方法默认会输出成这种格式"\u535a\u ...

  2. python3.4学习笔记(二十五) Python 调用mysql redis实例代码

    python3.4学习笔记(二十五) Python 调用mysql redis实例代码 #coding: utf-8 __author__ = 'zdz8207' #python2.7 import ...

  3. python3.4学习笔记(二十四) Python pycharm window安装redis MySQL-python相关方法

    python3.4学习笔记(二十四) Python pycharm window安装redis MySQL-python相关方法window安装redis,下载Redis的压缩包https://git ...

  4. python3.4学习笔记(二十二) python 在字符串里面插入指定分割符,将list中的字符转为数字

    python3.4学习笔记(二十二) python 在字符串里面插入指定分割符,将list中的字符转为数字在字符串里面插入指定分割符的方法,先把字符串变成list然后用join方法变成字符串str=' ...

  5. python3.4学习笔记(二十) python strip()函数 去空格\n\r\t函数的用法

    python3.4学习笔记(二十) python strip()函数 去空格\n\r\t函数的用法 在Python中字符串处理函数里有三个去空格(包括'\n', '\r', '\t', ' ')的函数 ...

  6. (C/C++学习笔记) 二十四. 知识补充

    二十四. 知识补充 ● 子类调用父类构造函数 ※ 为什么子类要调用父类的构造函数? 因为子类继承父类,会继承到父类中的数据,所以子类在进行对象初始化时,先调用父类的构造函数,这就是子类的实例化过程. ...

  7. (C/C++学习笔记) 二十二. 标准模板库

    二十二. 标准模板库 ● STL基本介绍 标准模板库(STL, standard template library): C++提供的大量的函数模板(通用算法)和类模板. ※ 为什么我们一般不需要自己写 ...

  8. (C/C++学习笔记) 二十. 文件和流

    二十. 文件和流 ● 文件的概念 文件(file) 一. C/C++语言将文件作为字节序列(sequence of characters)来对待,但从编码角度,或说从对字节信息的解释来看,文件分为:文 ...

  9. vue2.x学习笔记(十二)

    接着前面的内容:https://www.cnblogs.com/yanggb/p/12592256.html. 组件基础 组件化是vue的一个重要特性,也是vue学习中非常重要的一个知识点. 基础示例 ...

  10. Java基础学习笔记二十五 MySQL

    MySQL 在dos中操作mysql 连接mysql命令: mysql -uroot -p密码 ,连接OK,会出现mysql> 对数据库的操作 创建一个库 create database 库名 ...

随机推荐

  1. Convert JS object to JSON string

    Modern browsers (IE8, FF3, Chrome etc.) have native JSON support built in (Same API as with JSON2). ...

  2. STM32CubeMx——串口使用DMA收发

    用到的是DMA发送数据,接收还是普通的串口接收. 一.代码生成 1.按以前的方法设置好时钟和调试方式,这里就不多说了. 2.设置串口1. 3.在DMA Setting里点击Add添加USART1_TX ...

  3. OpenCV-Python 轮廓特征 | 二十二

    目标 在本文中,我们将学习 如何找到轮廓的不同特征,例如面积,周长,质心,边界框等. 您将看到大量与轮廓有关的功能. 1. 特征矩 特征矩可以帮助您计算一些特征,例如物体的质心,物体的面积等.请查看特 ...

  4. iOS NSDateFormatter性能

    一.探究 NSDateFormatter * dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateFormat: ...

  5. Python命令行执行.py文件提示ModuleNotFoundError:No module named 'XXX'解决办法

    原因:在命令行执行.py文件找不到包是因为我们没有把项目路径保存,可以通过sys.path.append()保存项目路径,执行后就能成功. ############################## ...

  6. logstash用jdbc插件将数据库内容导入elasticsearch时间字段相差5小时

    logstash将mysql的数据导入elasticsearch之后发现时间字段的相差5个小时 解决办法: 在数据库连接配置后面加上?serverTimezone=UCT这个就OK了 logstash ...

  7. Vue 里面对树状数组进行增删改查 的方法

    [{"id":"5e4c3b02fc984961a17607c37712eae0", "optLock":0, "parentId ...

  8. 如何在Linux下优雅的查询日志

    做为一名合格的Java后台开发 经常需要查询线上的日志,定位线上问题 所以熟练掌握日志查询的命令 可以使你更加迅速的定位错误日志位置,及时解决问题 在此,我将介绍几个自己工作中经常使用到的日志查询命令 ...

  9. 延时对象promise的使用

    promise是ES6(ECMA Script6)的新标准,只能在支持ES6的浏览器中使用 Promise是一个延时对象,创建延时对象时需要传入一个函数类型的参数 这个函数有两个参数:resolve和 ...

  10. JS烟花案例

    html代码部分 <!DOCTYPE html> <!-- * @Descripttion: * @version: * @Author: 小小荧 * @Date: 2020-03- ...