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.方式三:中央处 ...
随机推荐
- 使用 Nocalhost 开发 Rainbond 上的微服务应用
本文将介绍如何使用 Nocalhost 快速开发 Rainbond 上的微服务应用的开发流程以及实践操作步骤. Nocalhost 可以直接在 Kubernetes 中开发应用,Rainbond 可以 ...
- 优先队列STL
引入 优先队列是一种特殊的队列,它的功能是--自动排序. 基本操作: q.size(); //返回q里元素个数 q.empty(); //返回q是否为空,空则返回1,否则返回0 q.push(k); ...
- .NET中获取Windows的常见路径
更新记录 本文迁移自Panda666原博客,原发布时间:2021年6月30日. 一.说明 每种平台都其预定义的规则,比如Windows平台有自己的规定.公司也有预定义的规章制度.那么在平台上开发和干活 ...
- 一文搞懂Kafka的基本原理及使用
Kafka的基本原理及使用 一.基本概念及原理 1.Kafka特点 Kafka 是一个分布式的流式平台,流式平台包括以下三个特点: 发布和订阅消息(流),类似于一个消息队列或企业消息系统 持久化收到的 ...
- JavaScript 语言入门
目录 JavaScript 介绍 JavaScript 和 和 html 代码的结合方式 第一种方式 第二种方式 4.变量 关系(比较)运算 逻辑运算 数组(重点) 函数(重点) 函数的二种定义方式 ...
- supervisor的安装与使用
Ubuntu安装使用supervisor 进程管理工具 安装 apt-get install supervisor 查看是否安装成功 pgrep supervisord # 返回进程号则成功 改配置文 ...
- RPA应用场景-考勤审批
场景概述 考勤审批 所涉系统名称 考勤系统,微信 人工操作(时间/次) 5分钟 所涉人工数量 43 操作频率 不定时 场景流程 1.客户领导长期出差,又不想对考勤系统做深度开发: 2.员工请假后,领导 ...
- WPF 视频硬解码渲染播放(无空域)(支持4K、8K、高帧率视频)
MediaWPF 基于 .NET 6 实现视频硬解码渲染Demo(无空域问题) 代码实现仅供学习参考 本项目视频渲染通过显卡进行视频解码,CPU几乎不参与工作,并且不存在令人烦躁的空域问题. 在播放摄 ...
- 写for循环快捷生成方式
在编写代码过程常常会使用到for循环,这里给大家介绍一种快捷写法len.fori+回车键(其中len为循环长度)举个栗子,编写10次循环 8.fori
- 纪念我逝去的n个小时
纪念我逝去的n个小时 某人的惨案要我擦屁股=.= #include <bits/stdc++.h> using namespace std; template<class T> ...