首页 > 其他分享 >054_末晨曦Vue技术_处理边界情况之组件之间的循环引用

054_末晨曦Vue技术_处理边界情况之组件之间的循环引用

时间:2022-08-22 09:58:24浏览次数:84  
标签:Vue name HelloWorld 组件 vue 054 import 晨曦

组件之间的循环引用

点击打开视频讲解更详细

假设你需要构建一个文件目录树,像访达或资源管理器那样的。你可能有一个 <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')

若对您有帮助,请点击跳转到B站一键三连哦!感谢支持!

标签:Vue,name,HelloWorld,组件,vue,054,import,晨曦
From: https://www.cnblogs.com/mochenxiya/p/16611804.html

相关文章

  • vue3项目-小兔鲜儿笔记-01-项目初始化
    1.pinia基础store/modules/user.tsimport{defineStore}from'pinia'//用户模块constuseUserStore=defineStore('user',{state:()=>{return{......
  • vue中的EL理解
    el的作用:用于指明Vue实例的挂载目标。那么什么是挂载?虚拟dom与真实dom建立关系,让Vue实例控制页面中的某个区域的过程,称之为挂载。挂载的方式有:1、通过“el:'css选择器......
  • vue中打包的时候,如何将console.log去掉
    问题:打包完成后,项目启动后还有打印语句?1.开发环境,生产环境,是2套不同的环境开发环境需要console.log使用生产环境不需console.log使用让一套代码,在2个环境自......
  • Vue生命周期及基本语法(一)
    一、初体验<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewpor......
  • vue生命周期
      ---------------vuex......
  • vue学习笔记:组件
    组件是Vue.js最强大的功能之一。组件可以扩展HTML元素,封装可重用的代码,说白了就是一组可以重复使用的模板。组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任......
  • Linux虚拟机Nginx代理vue前端与SpringBoot后端资源
    1.Nginx安装配置详细参见菜鸟教程:https://www.runoob.com/linux/nginx-install-setup.html2.nginx.conf内容usernginx;worker_processes1;#设置值和CPU核心数......
  • VUE+SpringBoot环境准备
    一、nodejs下载地址官网:https://nodejs.org/zh-cn/其它版本:https://nodejs.org/zh-cn/download/releases/源码地址:https://github.com/nodejs二、vscode下载地......
  • 关于Vue路由懒加载问题
    今天刚开始新建一个vue项目,就在路由这卡死了,经过多次查找对比,发现了问题竟然是出现在一个括号上,如下所示constroutes=[//正确写法{path:'/',na......
  • vue 引入echars 亲测版
    网上找了很多例子,其中有修改main.js的配置的,反正我没搞成功,最后实验成功的步骤如下 1、首先创建一个VueCLI的工程。   注:具体步骤查看以前的博客https://www.c......