054_末晨曦Vue技术_处理边界情况之组件之间的循环引用
组件之间的循环引用
假设你需要构建一个文件目录树,像访达或资源管理器那样的。你可能有一个 <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')
}
案例:
<template>
<div id="app">
<li v-for="(folder,index) in folders" :key="index">
<HelloWorld :folder="folder"></HelloWorld>
</li>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
data(){
return {
folders: [
{
name: '末晨曦吖',
children: [{
name: '末晨曦吖 - 1',
children: [{
name: '末晨曦吖 - 1 - 1'
}]
}]
},
{
name: '满天星辰',
children: [{
name: '满天星辰 - 2',
children: [{
name: '满天星辰 - 2 - 2'
}]
}]
}
]
}
},
mounted() {
},
components:{
HelloWorld
},
methods:{
}
}
</script>
<style scoped>
</style>
src\components\HelloWorld.vue
<template>
<div class="hello">
<span>{{ folder.name }}</span>
<Category :children="folder.children"></Category>
</div>
</template>
<script>
import Category from './Category.vue'
export default {
name: 'HelloWorld',
props: ['folder'], //接收的是对象
data(){
return{
}
},
mounted(){
},
components:{
Category
},
methods:{
}
}
</script>
<style scoped>
</style>
src\components\Category.vue
<template>
<div id="app">
<ul>
<li v-for="(child,index) in children" :key="index">
<HelloWorld v-if="child.children" :folder="child"></HelloWorld>
<span v-else>{{ child.name }}</span>
</li>
</ul>
</div>
</template>
<script>
// import HelloWorld from './HelloWorld.vue'
export default {
name: 'Category',
props: ['children'], //接收的是数组
data(){
return {
name:'Category'
}
},
// 第二个解决组件之间的循环引用方式
// beforeCreate: function () {
// this.$options.components.HelloWorld = require('./HelloWorld.vue').default
// },
mounted() {
},
components:{
// HelloWorld
// 第三个解决组件之间的循环引用方式
HelloWorld: () => import('./HelloWorld.vue')
},
methods:{
}
}
</script>
<style scoped>
</style>
src\main.js
import Vue from 'vue'
import App from './App.vue'
//引入ElementUI组件库
import ElementUI from 'element-ui';
//引入ElementUI全部样式
import 'element-ui/lib/theme-chalk/index.css';
//插件引入
// import {Plugin1,Plugin2} from './plugins/plugins.js'
// 全局组件注册 // 第一个解决组件之间的循环引用方式
// import HelloWorld from './components/HelloWorld'
// import Category from './components/Category'
// Vue.component('HelloWorld',HelloWorld)
// Vue.component('Category',Category)
Vue.config.productionTip = false
//使用ElementUI
Vue.use(ElementUI)
// Vue.use(Plugin1,'参数1')
// Vue.use(Plugin2,'参数2')
new Vue({
render: h => h(App),
}).$mount('#app')
054_末晨曦Vue技术_处理边界情况之组件之间的循环引用的更多相关文章
- 048_末晨曦Vue技术_处理边界情况之使用$root访问根实例
处理边界情况之使用$root访问根实例 点击打开视频教程 在每个 new Vue 实例的子组件中,其根实例可以通过 $root property 进行访问. 例如,在这个根实例中: src\main. ...
- 056_末晨曦Vue技术_处理边界情况之X-template
处理边界情况之X-template 点击打开视频讲解更加详细 另一个定义模板的方式是在一个<script>元素中,并为其带上 text/x-template 的类型,然后通过一个 id 将 ...
- 051_末晨曦Vue技术_处理边界情况之provide和inject依赖注入
provide和inject依赖注入 点击打开视频讲解更详细 在此之前,在我们描述访问父级组件实例的时候,展示过一个类似这样的例子: <google-map> <google-map ...
- 057_末晨曦Vue技术_处理边界情况之强制更新($forceUpdate)与通过 v-once 创建低开销的静态组件
强制更新($forceUpdate) 点击打开视频讲解更加详细 在vue中,如果data中有基本数据类型变量:age,修改他,页面会自动更新. 但如果data中的变量为数组或对象(引用数据类型),我们 ...
- 057_末晨曦Vue技术_处理边界情况之强制更新和创建低开销的静态组件
强制更新和创建低开销的静态组件 点击打开视频讲解更加详细 强制更新 如果你发现你自己需要在 Vue 中做一次强制更新,99.9% 的情况,是你在某个地方做错了事. 你可能还没有留意到数组或对象的变更检 ...
- 052_末晨曦Vue技术_处理边界情况之程序化的事件侦听器
程序化的事件侦听器 点击打开视频讲解更详细 现在,你已经知道了 $emit 的用法,它可以被 v-on 侦听,但是 Vue 实例同时在其事件接口中提供了其它的方法.我们可以: 通过 $on(event ...
- 066_末晨曦Vue技术_过渡 & 动画之多个元素的过渡
多个元素的过渡 点击打开视频讲解更加详细 我们之后讨论多个组件的过渡,对于原生标签可以使用 v-if/v-else.最常见的多标签过渡是一个列表和描述这个列表为空消息的元素: <transiti ...
- 058_末晨曦Vue技术_过渡 & 动画之过渡的类名
进入/离开 & 列表过渡 点击打开视频讲解更加详细 概述 Vue 在插入.更新或者移除 DOM 时,提供多种不同方式的应用过渡效果.包括以下工具: 在 CSS 过渡和动画中自动应用 class ...
- Vue(基础四)_总结五种父子组件之间的通信方式
一.前言 这篇文章主要总结了几种通信方式: 1.方式一:使用props: [ ]和$emit() (适用于单层通信) 2.方式二:$attrs和$listeners(适用于多层) 3.方式三:中央处 ...
随机推荐
- 《Unix 网络编程》14:高级 I/O 函数
高级 I/O 函数 ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ...
- JavaScript之创建八个对象过520
马上又到了一年一度的520了,程序猿们赶紧创建对象过520吧!!! JavaScript创建对象的几种方式: 一:字面量方式: var obj = {name: '程序猿'}; 二:通过new操作符: ...
- 清除 GitHub 历史记录的隐私信息
清理 github 敏感信息 有的时候我们在提交到github上的内容不小心含有敏感代码,比如密码,公司的服务器IP等.这个时候就要通过一些手段清除这些信息. GitHub官方方案比较码放,所以推荐使 ...
- 技术分享 | 想做App测试就一定要了解的App结构
本文节选自霍格沃兹测试开发学社内部教材 app 的结构包含了 APK 结构和 app 页面结构两个部分 APK结构 APK 是 Android Package 的缩写,其实就是 Android 的安装 ...
- 开发工具-Unix时间戳转换
更新日志 2022年6月10日 初始化链接. https://toolb.cn/timestamp
- 使用PowerShell下载文件
更新记录 本文迁移自Panda666原博客,原发布时间:2021年7月12日. 使用Invoke-WebRequest指令下载文件 [Net.ServicePointManager]::Securit ...
- 记一次grpc server内存/吞吐量优化
背景 最近,上线的采集器忽然时有OOM.采集器本质上是一个grpc服务,网络设备通过grpc协议将数据上报后,采集器进行格式等整理后,发往下一个系统(比如分析,存储). 打开运行环境,发现特性如下: ...
- MVVM,MVC,MVP的区别
MVC.MVP 和 MVVM 是三种常见的软件架构设计模式,主要通过分离关注点的方式来组织代码结构,优化开发效率. 在开发单页面应用时,往往一个路由页面对应了一个脚本文件,所有的页面逻辑都在一个脚本文 ...
- WPF开发随笔收录-自定义图标控件
一.前言 1.在以前自学的过程中,软件需要使用到图标的时候,总是第一个想法是下载一个图片来充当图标使用,但实际得出来的效果会出现模糊的现象.后来网上学习了字体图标库的用法,可以在阿里云矢量图网站那里将 ...
- 【RPA之家转载】苏桦 华为RPA 企业财务实践:RPA与AI结合,实现百万级票据、合同处理自动化
[RPA之家转载]苏桦 华为RPA 企业财务实践:RPA与AI结合,实现百万级票据.合同处理自动化 看到大会的主题,说每一位开发者都了不起,说白了我也非常的感触,因为我自己本身也是一个开发者,我从01 ...