当前位置: 首页 > news >正文

【卷起来】VUE3.0教程-06-组件详解

============各位看官,点波关注和赞吧===========

组件允许我们将 UI 划分为独立的、可重用的部分,并且可以对每个部分进行单独的思考。在实际应用中,组件常常被组织成层层嵌套的树状结构:

这和我们嵌套 HTML 元素的方式类似,Vue 实现了自己的组件模型,使我们可以在每个组件内封装自定义内容与逻辑。Vue 同样也能很好地配合原生 Web Component(网络组件)。

🌲 定义一个组件

当使用构建步骤时,我们一般会将 Vue 组件定义在一个单独的 .vue 文件中,这被叫做单文件组件 (简称 SFC):

<script setup>
import { ref } from 'vue'const count = ref(0)
</script><template><button @click="count++">You clicked me {{ count }} times.</button>
</template>

🌲 使用组件

要使用一个子组件,我们需要在父组件中导入它。假设我们把计数器组件放在了一个叫做 Counter.vue 的文件中,这个组件将会以默认导出的形式被暴露给外部。

<script setup>import { ref } from 'vue'const count = ref(0)
</script><template><button @click="count++">You clicked me {{ count }} times.</button>
</template>

在App.vue中可以这样引用

<script setup>import ButtonCounter from './components/Counter.vue'
</script><template><h2> 下面是一个子组件</h2><ButtonCounter></ButtonCounter>
</template>

组件可以被重用任意多次:

<h1>这里是一个子组件!</h1>
<ButtonCounter />
<ButtonCounter />
<ButtonCounter />

你会注意到,每当点击这些按钮时,每一个组件都维护着自己的状态,是不同的 count。这是因为每当你使用一个组件,就创建了一个新的实例

在单文件组件中,推荐为子组件使用 驼峰命名法的标签名,以此来和原生的 HTML 元素作区分。虽然原生 HTML 标签名是不区分大小写的,但 Vue 单文件组件是可以在编译中区分大小写的。我们也可以使用 /> 来关闭一个标签。

🌲 传递Props

🌾 Props初体验

如果我们正在构建一个博客,我们可能需要一个表示博客文章的组件。我们希望所有的博客文章分享相同的视觉布局,但有不同的内容。要实现这样的效果自然必须向组件中传递数据,例如每篇文章标题和内容,这就会使用到 props。

Props 是一种特别的 attributes,你可以在组件上声明注册。要传递给博客文章组件一个标题,我们必须在组件的 props 列表上声明它。这里要用到 defineProps 宏:

<!-- BlogPost.vue -->
<script setup>const props = defineProps(['title'])console.log(props.title)
</script><template><h4>{{ title }}</h4>
</template>

defineProps 是一个仅 <script setup> 中可用的编译宏命令,并不需要显式地导入。声明的 props 会自动暴露给模板。defineProps 会返回一个对象,其中包含了可以传递给组件的所有 props.

一个组件可以有任意多的 props,默认情况下,所有 prop 都接受任意类型的值。

当一个 prop 被注册后,可以像这样以自定义 attribute 的形式传递数据给它:

<script setup>import BlogPost from './components/BlogPost.vue'
</script><template><BlogPost title="山海经"></BlogPost>
</template>

在实际应用中,我们可能在父组件中会有如下的一个博客文章数组:


<script setup>import {ref} from 'vue'import BlogPost from './components/BlogPost.vue'const posts = ref([{id:1,title:"钢铁是怎样练成的"},{id:2,title:"坏蛋是怎样练成的"},{id:3,title:"秦始皇是怎样练成的"},])</script><template><BlogPost v-for="post in posts":id="post.id":title="post.title"></BlogPost>
</template>
<!-- BlogPost.vue -->
<script setup>const props = defineProps(['id','title']) console.log(props.title)
</script><template><h4>{{ id }}--《{{ title }}》</h4>
</template>

🌾 传递Prop的细节

🍁 传递不同的值类型

除了传递简单的字符串以外,Prop还可以传递数组以及对象,具体如下:

<script lang="ts" setup>import {reactive,markRaw, ref} from 'vue'import BlogPost from './components/BlogPost.vue';const post = reactive({"likes":56,"isDisabled":true,"wifes":['苍老师','波多老师','陇泽老师']})const author = {name:'兰陵笑笑生',company:'水浒分舵'}</script><template><!-- 传入数字 --><BlogPost :likes="42"></BlogPost><!-- 根据一个变量的值动态传入 --><BlogPost :likes="post.likes"></BlogPost><!-- 传入boolean类型的值 --><!-- 仅写上 prop 但不传值,会隐式转换为 `true` --><BlogPost disabled></BlogPost>
<!--  --><BlogPost :disabled="false"></BlogPost>
<!-- 根据一个变量的值动态传入 --><BlogPost :disabled="post.isDisabled"></BlogPost><!-- 传入一个数组Array --><BlogPost :wifes="['赵丽颖','刘亦菲','景甜']"></BlogPost><!-- 传入一个数组Array变量 --><BlogPost :wifes="post.wifes"></BlogPost><!--传入一个Object对象--><BlogPost :author="author"></BlogPost>
</template><style ></style>

子组件中代码:

<!-- BlogPost.vue -->
<script setup>const props = defineProps(["likes","disabled","wifes","author"])</script><template><h4>取到的值为:{{ likes }}</h4><button :disabled="disabled"> Enlarge text</button><h2 v-for="wife in wifes">{{ wife }}</h2><h2 v-if="author">作者:{{ author.name }}  - 公司:{{ author.company }}</h2>
</template>

🍁 使用一个对象绑定多个prop

如果你想要将一个对象的所有属性都当作 props 传入,你可以使用没有参数的v-bind,即只使用 v-bind 而非 :prop-name。例如,这里有一个 post 对象:

<script lang="ts" setup>import {reactive,markRaw, ref} from 'vue'const post = {id: 1,title: '熊熊火焰'}
</script><template><BlogPost v-bind="post" />
</template>

运行起来后:

🍁 单向数据流

所有的 props 都遵循着单向绑定原则,props 因父组件的更新而变化,自然地将新的状态向下流往子组件,而不会逆向传递。这避免了子组件意外修改父组件的状态的情况,不然应用的数据流将很容易变得混乱而难以理解。

另外,每次父组件更新后,所有的子组件中的 props 都会被更新到最新值,这意味着你不应该在子组件中去更改一个 prop。若你这么做了,Vue 会在控制台上向你抛出警告:

如下面案例:

<script lang="ts" setup>import {reactive,markRaw, ref} from 'vue'import BlogPost from './components/BlogPost.vue';const post = {id: 1,title: '熊熊火焰'}
</script><template><BlogPost v-bind="post" /><BlogPost :likes="post.id"></BlogPost>
</template><style ></style>

在子组件中我们尝试去修改likes的值:

<!-- BlogPost.vue -->
<script setup>const props = defineProps(["likes","disabled","wifes","author"])props.likes = 3
</script><template><h4>取到的值为:{{ likes }}</h4></template>

保存后,浏览器会报:

如果确实想要修改props中的值,可以采取以下方式:

  • prop 被用于传入初始值;而子组件想在之后将其作为一个局部数据属性。在这种情况下,最好是新定义一个局部数据属性,从 props 上获取初始值即可:
<!-- BlogPost.vue -->
<script setup>import {ref} from 'vue'const props = defineProps(["likes","disabled","wifes","author"])// 此处的likes只是将prop.likes作为初始值// 后续对这个likes的更改就和prop无关了// let 定义变量,const定义常量let likes = ref(props.likes)likes = 1001
</script><template><h4>取到的值为:{{ likes }}</h4></template>

🍁 Prop 校验

Vue 组件可以更细致地声明对传入的 props 的校验要求。比如我们上面已经看到过的类型声明,如果传入的值不满足类型要求,Vue 会在浏览器控制台中抛出警告来提醒使用者。这在开发给其他开发者使用的组件时非常有用。

要声明对 props 的校验,你可以向 defineProps() 宏提供一个带有 props 校验选项的对象,例如:

<!-- BlogPost.vue -->
<script setup>import {ref} from 'vue'defineProps({// 基础类型检查// (给出 `null` 和 `undefined` 值则会跳过任何类型检查)propA: Number,// 多种可能的类型propB: [String, Number],// 必传,且为 String 类型propC: {type: String,required: true},// Number 类型的默认值propD: {type: Number,default: 100},// 对象类型的默认值propE: {type: Object,// 对象或数组的默认值// 必须从一个工厂函数返回。// 该函数接收组件所接收到的原始 prop 作为参数。default(rawProps) {return { message: 'hello' }}},// 自定义类型校验函数propF: {validator(value) {// The value must match one of these stringsreturn ['success', 'warning', 'danger'].includes(value)}},// 函数类型的默认值propG: {type: Function,// 不像对象或数组的默认,这不是一个// 工厂函数。这会是一个用来作为默认值的函数default() {return 'Default function'}}
})
</script><template><h4>取到的值为:{{ propA }}</h4><h4>取到PropC的值为:{{ propC }}</h4><h4>取到PropD的值为:{{ propD }}</h4></template>
<script lang="ts" setup>import {reactive,markRaw, ref} from 'vue'import BlogPost from './components/BlogPost.vue';const post = {id: 1,title: '熊熊火焰'}
</script><template><BlogPost :propA="post.id"></BlogPost><BlogPost :propC="post.title"></BlogPost>
</template><style ></style>

这里propA要求的值是Number,当传递的值是字符串类型的时候,就会报错:

🌲 监听事件

让我们继续关注我们的 <BlogPost> 组件。我们会发现有时候它需要与父组件进行交互。例如,要在此处实现无障碍访问的需求,将博客文章的文字能够放大,而页面的其余部分仍使用默认字号。

在父组件中,我们可以添加一个 postFontSize ref 来实现这个效果:

<script setup>import {ref} from 'vue'import BlogPost from './components/BlogPost.vue'const posts = ref([{id:1,title:"钢铁是怎样练成的"},{id:2,title:"坏蛋是怎样练成的"},{id:3,title:"秦始皇是怎样练成的"},])const postFontSize = ref(1)</script>

这里我们定义了一个postFontSize这样一个值,在模板中用它来控制所有博客文章的字体大小:

<div :style="{ fontSize: postFontSize + 'em' }"><BlogPostv-for="post in posts":key="post.id":title="post.title"/>
</div>

然后,给 <BlogPost> 组件添加一个按钮:

<!-- BlogPost.vue -->
<script setup>const props = defineProps(['id','title'])console.log(props.title)</script><template><h4>{{ id }}--《{{ title }}》</h4><!--点击之后,会抛出一个名为enlarge-text的事件,这个事件名可以自定义  --><button @click="$emit('enlarge-text')"> Enlarge text</button>
</template>

在这里,我们使用了@click 点击事件,子组件可以通过调用内置的$emit方法,通过传入事件名称来抛出一个事件。 抛出事件后,父组件可以通过 v-on 或 @ 来选择性地监听子组件上抛的事件,就像监听原生 DOM 事件那样:

<template><div :style="{fontSize:postFontSize +'em'}"><BlogPost v-for="post in posts":id="post.id":title="post.title"<!-- 此处是子组件抛出来的enlarge-text 事件,事件名和子组件抛出来名字要的对应 -->@enlarge-text="postFontSize += 0.1"></BlogPost>
</div>
</template>

我们可以通过 defineEmits 宏来声明需要抛出的事件:

<!-- BlogPost.vue -->
<script setup>const props = defineProps(['id','title'])console.log(props.title)// 可以定义出这个组件可能触发的所有的事件const emit = defineEmits(['enlarge-text','event2','event3'])// 当点击 Enlarge text 的时候需要抛出的事件const large = ()=>{emit('enlarge-text')}
</script><template><h4>{{ id }}--《{{ title }}》</h4><button @click="large"> Enlarge text</button>
</template>

这声明了一个组件可能触发的所有事件,父组件中还是按照之前的方式监听子组件抛出的事件。

<script setup>import {ref} from 'vue'import BlogPost from './components/BlogPost.vue'const posts = ref([{id:1,title:"钢铁是怎样练成的"},{id:2,title:"坏蛋是怎样练成的"},{id:3,title:"秦始皇是怎样练成的"},])const postFontSize = ref(1)</script><template><div :style="{fontSize:postFontSize +'em'}"><BlogPost v-for="post in posts":id="post.id":title="post.title"@enlarge-text="postFontSize += 0.1"></BlogPost>
</div>
</template>

🌲 通过插槽来分配内容

🌿 插槽初体验

一些情况下我们会希望能和 HTML 元素一样向组件中传递内容:

<AlertBox>Something bad happened.
</AlertBox>

我们期望能渲染成这样:

这可以通过 Vue 的自定义 <slot> 元素来实现:

<template><div class="alert-box"><div>老弟!这里发生了一个状况!</div><div ><!-- slot 这是一个占位符,父组件传过来的值,会渲染在这个地方 --><slot /></div></div>
</template><style >.alert-box{width: 500px;height: 80px;border-radius: 10px;border: 1px solid red;background-color: antiquewhite;}.alert-box div{display: block;margin-top: 10px;margin-left: 20px;} 
</style>

如上所示,我们使用 <slot> 作为一个占位符,父组件传递进来的内容就会渲染在这里。在父组件中可以引入子组件,并插入值。

<AlertBox>你的老婆跟别人跑了!
</AlertBox>

🌿 插槽的出口与内容

在上面的案例中:

<AlertBox>你的老婆跟别人跑了!
</AlertBox>

父组件中提供了子组件中显示的内容,这个内容成为插槽内容,而在子组件中我们写了一个

 <div ><!-- slot 这是一个占位符,父组件传过来的值,会渲染在这个地方 --><slot /></div>

这个地方的<slot> 元素,我们称为插槽出口,标识了父元素提供的插槽内容将在哪里被渲染。

🌲 动态组件

有些场景会需要在两个组件间来回切换,比如 Tab 界面:

动态组件是通过Vue 的 <component> 元素和特殊的 is attribute 实现的:


<template><div class="gz">这里是关注页面</div>
</template><style>.gz{width: 100%;height: 800px;background-color: red;}
</style>
<template><div class="TJ">这里是推荐页面</div>
</template><style>.TJ{width: 100%;height: 800px;background-color: blue;}
</style>
<template><div class="cp">这里是测评页面</div>
</template><style>.cp{width: 100%;height: 800px;background-color: yellow;}
</style>

然后在App.vue中导入所有的组件,并使用<component :is="指定组件名">来选择引用哪个组件

<script setup>import {reactive,markRaw, ref} from 'vue'import TJ from './components/TJ.vue';import GZ from './components/GZ.vue';import CP from './components/CP.vue';
</script><template><component :is="CP"></component>
</template>

如果想要实现选项卡操作,可以将App.vue修改成如下代码

<script setup>import {reactive,markRaw, ref} from 'vue'import TJ from './components/TJ.vue';import GZ from './components/GZ.vue';import CP from './components/CP.vue';const comId = ref(GZ)const switchTab=(tab,index)=>{comId.value = tab.com}const tabData = reactive([{"name":"关注",com:GZ},{"name":"推荐",com:TJ},{"name":"测评",com:CP}])
</script><template><!-- 组成选项卡div --><div class="tabs-content" @click="switchTab(tab)" v-for="(tab, index) in tabData" :key="index">{{ tab.name }}</div><!-- 动态选择组件 --><component :is="comId"></component>
</template><style >
.tabs-content {display: inline-block;width: 100px;border: 1px solid #ccc;background: rgb(175, 96, 96);color: white;
}
</style>

相关文章:

【卷起来】VUE3.0教程-06-组件详解

各位看官&#xff0c;点波关注和赞吧 组件允许我们将 UI 划分为独立的、可重用的部分&#xff0c;并且可以对每个部分进行单独的思考。在实际应用中&#xff0c;组件常常被组织成层层嵌套的树状结构&#xff1a; 这和我们嵌套 HTML 元素的方式类似&#xff0c;Vue 实现了自己的…...

JS Web

Web API 元素通用属性 元素自身属性 事件处理...

【Linux】传输层协议——UDP

零、传输层的作用是负责数据能够从发送端传输到接收端 一、再来认识一下端口号 端口号&#xff08;Port&#xff09;标识了一个主机进行通信的不同的应用程序。在TCP/IP协议中&#xff0c;用“源IP”&#xff0c;“源端口号”&#xff0c;“目的IP”&#xff0c;“目的端口号”…...

算法学习攻略总结 : 入门至进阶,通关之路指南

❃博主首页 &#xff1a; <码到三十五> ☠博主专栏 &#xff1a; <mysql高手> <elasticsearch高手> <源码解读> <java核心> <面试攻关> ♝博主的话 &#xff1a; <搬的每块砖&#xff0c;皆为峰峦之基&#xff1b;公众号搜索(码到…...

《卷积神经网络 CNN 原理探秘》

CNN基本原理详解 卷积神经网络&#xff08;Convolutional Neural Network&#xff0c;简称CNN&#xff09;&#xff0c;是一种前馈神经网络&#xff0c;人工神经元可以响应周围单元&#xff0c;可以进行大型图像处理。卷积神经网络包括卷积层和池化层。 卷积神经网络是受…...

C#获取计算机信息

目录 效果 项目 代码 下载 效果 项目 代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Management; n…...

派遣函数 - 通过设备链接打开设备

利用文件IO相关的Wn32API对设备进行“打开”和“关闭”操作。要打开设备&#xff0c;必须通过设备的名字才能得到该设备的柄。前面介绍过&#xff0c;每个设备都有设备名称&#xff0c;如HelloDDK驱动程序的设备名为“Device\\MyDDKDevice”&#xff0c;但是设备名无法被用户模…...

Vue 2 中的 `$set` 方法详解

在 Vue 2 中&#xff0c;响应式数据的更新非常重要&#xff0c;因为它确保了当数据改变时&#xff0c;视图能够自动更新。Vue 使用一套高效的机制来追踪依赖并在数据变化时更新视图。然而&#xff0c;在某些情况下&#xff0c;直接修改对象的属性可能不会触发视图更新。这时&am…...

掌握Hive函数[2]:从基础到高级应用

目录 高级聚合函数 多进一出 1. 普通聚合 count/sum... 2. collect_list 收集并形成list集合&#xff0c;结果不去重 3. collect_set 收集并形成set集合&#xff0c;结果去重 案例演示 1. 每个月的入职人数以及姓名 炸裂函数 概述 案例演示 1. 数据准备 1&#xff09;表…...

水壶问题记录

https://leetcode.cn/problems/water-and-jug-problem/description/?envTypestudy-plan-v2&envId2024-spring-sprint-100...

spring综合性利用工具-SpringBootVul-GUI(五)

项目地址 https://github.com/wh1t3zer/SpringBootVul-GUI 0x01简介 本着简单到极致的原则&#xff0c;开发了这么一款半自动化工具&#xff08;PS&#xff1a;这个工具所包含了20个漏洞&#xff0c;开发不易&#xff0c;有任何问题可提issue&#xff09; 尽管是一个为懒人量…...

2024年9月12日(k8s环境及测试 常用命令)

一、环境准备及测试 1、报错处理&#xff1a; kube-system calico-node-5wvln 0/1 Init:0/3 0 16h kube-system calico-node-d7xfb 0/1 Init:0/3 0 16h ku…...

卫生间漏水原因很多,切莫病急乱投医

有位业主说他家卫生间背面的墙湿了&#xff0c;邻居家正好在装修&#xff0c;把家具拆掉以后发现墙面上有一片已经湿了。      和业主相约去现场看看&#xff0c;去楼下业主家看了看&#xff0c;顶面是干燥的&#xff0c;这就说明不往楼下漏水。      这就奇怪了&#…...

IEEE 802.11a OFDM系统的仿真(续)

&#xff08;内容源自详解MATLAB&#xff0f;SIMULINK 通信系统建模与仿真 刘学勇编著第九章内容&#xff0c;有兴趣的读者请阅读原书&#xff09; clear all %%%%%%%参数设计部分%%%%%%%Nsp52;%系统子载波数&#xff08;不包括直流载波&#xff09; Nfft64;%FFT长度 Ncp16;…...

Linux cut命令详解使用:掌握高效文本切割

cut 是 Linux 中一个用于从文本文件或标准输入中提取指定字段的命令。它根据分隔符或者字符位置来裁剪文本&#xff0c;是处理文本文件中的字段、列和子字符串的常用工具。 基本语法 cut [选项] 文件或 命令 | cut [选项]常用选项 -b&#xff1a;按字节位置切割&#xff08…...

c++11新特性——endable_shared_from_this

文章目录 一.解决场景代码示例原因 二.解决办法代码 三.底层原理 一.解决场景 一个share_ptr管理的类&#xff0c;如果从类的函数里返回类对象&#xff08;this指针&#xff09;&#xff0c;导致share_ptr引用计数错误&#xff0c;析构时异常问题 代码示例 #include <mem…...

小程序的右侧抽屉开关动画手写效果

<template><view><button click"openDrawer">打开抽屉</button><view v-if"showDrawer" class"drawer" :style"{ backgroundColor: bgColor }" click"closeDrawer"><view class"draw…...

vue3中el-table中点击图片放大时,被表格覆盖

问题&#xff1a;vue3中el-table中点击图片放大时&#xff0c;被表格覆盖。 解决方法&#xff1a;el-image 添加preview-teleported <el-table-column label"封面图" prop"coverUrl"><template #default"scope"><el-imagestyle&q…...

GO学习笔记(4) strconv/time

目录 strconv包1、string与bool之间的转换2、string与int之间的转换 time包1、常用常量定义2、Now&#xff08;&#xff09;获取当前年月日时分秒3、Format&#xff08;&#xff09;时间格式化4、Parse&#xff08;&#xff09;/ ParseInLocation&#xff08;&#xff09;解析时…...

课程管理系统-数据库-基于MySQL的数据库课程设计

目录 前言一、需求分析二、设计数据库模型1.实体关系图(ERD)2.表结构设计三、创建数据库和表四、插入数据五、查询数据六、更新和维护七、安全性与性能优化总结前言 设计一个数据库课程(或任何课程管理系统)时,我们首先需要明确系统的需求和目标。以下是一个基于MySQL的数…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能&#xff0c;本节首先介绍如何通过 Docker 快速体验 TDengine&#xff0c;然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker&#xff0c;请使用 安装包的方式快…...

【Linux】shell脚本忽略错误继续执行

在 shell 脚本中&#xff0c;可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行&#xff0c;可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令&#xff0c;并忽略错误 rm somefile…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

2021-03-15 iview一些问题

1.iview 在使用tree组件时&#xff0c;发现没有set类的方法&#xff0c;只有get&#xff0c;那么要改变tree值&#xff0c;只能遍历treeData&#xff0c;递归修改treeData的checked&#xff0c;发现无法更改&#xff0c;原因在于check模式下&#xff0c;子元素的勾选状态跟父节…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下&#xff0c;知识图谱凭借其高效的信息组织能力&#xff0c;正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合&#xff0c;探讨知识图谱开发的实现细节&#xff0c;帮助读者掌握该技术栈在实际项目中的落地方法。 …...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...