vue 数据树结构 无限递归 组件调用本身 父组件监听子组件 高亮
作者:互联网
- 传入的数据结构 需要这种数据类型 使用父组件向子组件传值
-
{ "id": 0, "name": "", "children": [ { "children": [ { "children": [ { "fid": 2, "id": 3, "levar": null, "name": "python自动化", "params": "0" }, { "fid": 2, "id": 4, "levar": null, "name": "python web开发", "params": "0" } ], "fid": 1, "id": 2, "levar": null, "name": "python歌词", "params": "0" }, { "fid": 1, "id": 11, "levar": null, "name": "lang课程", "params": "{\"lanuage\":\"语言\",\"editor\":\"编辑器\",\"pc\":\"电脑型号\"}" } ], "fid": 0, "id": 1, "levar": null, "name": "编程课程", "params": "0" }, { "children": [ { "children": [ { "fid": 6, "id": 8, "levar": null, "name": "炒菜类", "params": "0" } ], "fid": 5, "id": 6, "levar": null, "name": "粤菜", "params": "0" }, { "fid": 5, "id": 7, "levar": null, "name": "鲁菜", "params": "0" } ], "fid": 0, "id": 5, "levar": null, "name": "烹饪课程", "params": "0" }, { "children": [ { "fid": 9, "id": 10, "levar": null, "name": "黄老师", "params": "{\"lanuage\":\"盆\",\"editor\":\"碗\",\"pc\":\"锅\"}" } ], "fid": 0, "id": 9, "levar": null, "name": "瑜伽课程", "params": "0" } ] }
-
2 子组件 递归调用自己
<template>
<div>
<div
v-if="data.id != 0"
@click="getfid(data.id)"
:id="data.id"
:class="cid == data.id?'bg':''"
>
{{ data.name }}
</div>
<li>
<ul v-if="data.children && data.children.length > 0">
<Reply v-for="child in data.children" :key="child.id" :data="child" />
</ul>
</li>
</div>
</template>
<script>
import axios from "axios";
import bus from "./bus.js";
export default {
//声明名称
name: "Reply",
props: ["data"],
components: {},
data() {
return {
fid:0,
cid:0
};
},
// 声明方法
methods: {
//点选分类id
getfid: function (fid) {
this.fid = fid;
// console.log(fid)
bus.$emit("msg", fid);
// 取消说有高亮
var divs = document.getElementsByClassName("bg");
// 遍历选择器
for (var i = divs.length - 1; i >= 0; i--) {
//取消高亮
divs[i].classList.remove("bg");
}
//首先将当前元素高亮显示
var mydiv = document.getElementById(fid);
// 动态添加高亮类选择器
mydiv.classList.add("bg");
},
},
mounted() {
this.cid = localStorage.getItem("cateid")
},
created() {},
};
</script>
<style scoped>
ul {
padding-left: 10rem;
list-style: none;
}
.bg {
background: orange;
color: white;
}
</style>
3 实现父住键点击子组件数据高亮 显示颜色
首先创建一个bus.js文件(文件名随意)
文件写入
import Vue from "vue"
export default new Vue();
在子组件导入bus.js文件 利用子传参传给bus.js
bus.$emit("msg", fid);
父组件用on监听
created() {
// 监听
bus.$on("msg", (target) => {
this.fid = target;
});
},
我的父组件效果
父组件代码:
<template>
<div>
<myheader />
<Repel :data="mydata" />
<van-cell-group>
<van-field label="课程标题" v-model="title" />
<van-field label="课程描述" v-model="desc" rows="5" type="textarea" />
<van-field
v-show="show_course"
v-for="(item, index) in params"
:label="item.label"
:key="index"
v-model="info[item.key]"
/>
<van-field
v-show="show_cate"
v-for="(value, key, index) in params_cate"
:label="value"
:key="index"
v-model="info_cate[key]"
/>
<van-button color="pink" @click="editcourse">保存修改课程</van-button>
单视频上传<van-uploader :after-read="afterRead" /> 多视频上传<van-uploader
v-show="cid"
multiple
:after-read="afterRead_list"
/>
</van-cell-group>
<van-button
color="yellow"
@click="
show_choice == false ? (show_choice = true) : (show_choice = false)
"
>多选</van-button
>
<van-button v-show="show_choice" color="red" @click="delvideos()"
>批量删除</van-button
>
<div v-for="(item, index) in srcs" :key="index">
<van-button @click="play(item, index)">
第 {{ index + 1 }} 集
</van-button>
<input
v-show="show_choice"
type="checkbox"
:value="item"
v-model="checkbox_list"
/>
</div>
<div v-if="src !== ''">
<!-- 视频展示 -->
<video
v-show="src"
width="400rem"
height="200rem"
:src="upload_dir + src"
controls="controls"
autoplay="autoplay"
muted
></video>
修改:<van-uploader :after-read="newafterRead" />
<van-button color="red" @click="delvideo()">删除视频</van-button>
</div>
<footers />
</div>
</template>
<script>
//导入头部尾部组件
import myheader from "./myheader.vue";
import footers from "./footers.vue";
import Repel from "./Reply.vue";
import bus from "./bus.js";
import axios from "axios";
export default {
//声明组件
components: {
myheader: myheader,
footers: footers,
Repel: Repel,
},
data() {
return {
title: "", // 标题
desc: "", // 描述
cid: 0, // 课程id
fid: 0, // 分类id
mydata: [], //数据展示
params: [], // 特定参数
info: [], // 字典容器,动态生成容器
info_cate: [],
srcs: [], // 商品展示列表
video_item: "", // 选中视频集
video_index: 0, // 视频下标
src: "", // 视频
params_cate: {},
show_course: true,
show_cate: false,
checkbox_list: [], // 删除商品列表
show_choice: false, // 删除 多选 展示
};
},
methods: {
// 根据value进行删除
myremove: function (vals, val) {
//拿到删除目标删除的下标
var index = vals.indexOf(val);
if (index > -1) {
// 删除操作
this.srcs.splice(index, 1);
}
},
// 批量删除
delvideos: function () {
var videolist = JSON.stringify(this.checkbox_list);
this.$dialog
.confirm({ title: "删除视频操作,删除后不可恢复" })
.then(() => {
this.axios
.delete("http://localhost:5000/delvideos/", {
params: {
id: this.cid,
uid: localStorage.getItem("id"),
token: localStorage.getItem("token"),
videolist: videolist,
},
})
.then((result) => {
for (let i = 0; i < this.checkbox_list.length; i++) {
this.myremove(this.srcs, this.checkbox_list[i]);
}
this.$toast.success(result.data.msg);
});
});
},
// 删除视频
delvideo: function () {
this.$dialog
.confirm({ title: "删除视频操作,删除后不可恢复" })
.then(() => {
this.axios
.delete("http://localhost:5000/delvideo/", {
params: {
id: this.cid,
uid: localStorage.getItem("id"),
token: localStorage.getItem("token"),
index: this.video_index,
},
})
.then((result) => {
this.$toast.success(result.data.msg);
// 删除
this.srcs.splice(this.srcs[this.video_index], 1);
});
});
},
// 封装,解析字符串
myparse: function (mystr) {
var myparams = mystr;
if (myparams == "") {
myparams = null;
}
// 解析
myparams = JSON.parse(myparams);
return myparams;
},
// 修改视频
newafterRead: function (file) {
// 声明表单
let data = new FormData();
data.append("file", file.file);
data.append("uid", localStorage.getItem("id"));
data.append("id", localStorage.getItem("cid"));
data.append("index", this.video_index);
const myaxios = this.axios.create({ withCredentials: false });
myaxios({
method: "post",
url: "http://localhost:5000/updatavideo/",
data: data,
}).then((result) => {
if (result.data.code == 200) {
//视频替换
this.srcs[this.video_index] = result.data.filename;
this.$toast.success(result.data.msg);
} else {
this.$toast.fail(result.data.msg);
}
});
},
//选集
play: function (src, index) {
this.src = this.upload_dir + src;
this.src = src;
this.video_index = index;
},
// 获取我的视频
get_video() {
//发送请求
this.axios
.get("http://localhost:5000/mycourse/", {
params: {
id: localStorage.getItem("id"),
cid: localStorage.getItem("cid"),
token: localStorage.getItem("token"),
},
})
.then((result) => {
// 解析
this.srcs = this.myparse(result.data.video);
});
},
// 修改
editcourse: function () {
var lists = [];
//遍历取值
for (var key in this.info) {
lists.push({
key: key,
value: this.info[key],
label: this.params[key],
});
}
//序列化操作
var lists_str = JSON.stringify(lists);
var data_post = {
fid: this.fid,
title: this.title,
desc: this.desc,
id: localStorage.getItem("cid"),
};
//判断是否有特需参数
if (lists.length > 0) {
var data_post = {
fid: this.fid,
title: this.title,
desc: this.desc,
id: localStorage.getItem("cid"),
params: lists_str,
};
}
//发送请求
this.axios
.put(
"http://localhost:5000/modifycourse/",
this.qs.stringify(data_post)
)
.then((result) => {
console.log(result);
if (result.data.code == 200) {
this.$toast.success("课程修改成功");
} else {
this.$toast.fail(result.data.msg);
}
});
},
//获取课程分类
get_cate: function (fid) {
//判断展示表单
if (fid === localStorage.getItem("cateid")) {
//选择的分类和默认课程的分类,一致,展示课程回填表单
this.show_course = true;
this.show_cate = false;
} else {
this.show_course = false;
this.show_cate = true;
}
//发送请求
this.axios
.get("http://localhost:5000/getcate/", { params: { fid: fid } })
.then((result) => {
// 解析
this.params_cate = this.myparse(result.data.params);
//动态生成data对应表单变量
for (var key in this.params_cate) {
//动态声明
this.$set(this.info_cate, key, "");
}
});
},
//获取分类数据递归展示数据
get_data: function () {
this.axios.get("http://localhost:5000/catelist/").then((result) => {
//声明根节点
var mytree = { id: 0, name: "" };
mytree["children"] = result.data;
this.mydata = mytree;
//获取课程详情
this.axios
.get("http://localhost:5000/getcourse/", {
params: {
fid: this.cid,
token: localStorage.getItem("token"),
},
})
.then((result) => {
//赋值操作
this.title = result.data.title;
this.desc = result.data.desc;
this.fid = result.data.cid;
// 课程分类id
localStorage.setItem("cateid", this.fid);
this.params = this.myparse(result.data.params);
// 生产动态data对应表单遍历
if (this.params != null) {
for (let i = 0; i < this.params.length; i++) {
// 动态声明
this.$set(
this.info,
this.params[i]["key"],
this.params[i]["value"]
);
}
}
});
});
},
// 多视频上传
afterRead_list: function (file) {
// 遍历文文件列表
for (let i = 0; i <= file.length; i++) {
this.afterRead(file[i]);
}
},
// 上传视频方法
afterRead: function (file) {
// 声明表单
let data = new FormData();
data.append("file", file.file);
data.append("id", localStorage.getItem("id"));
data.append("cid", localStorage.getItem("cid"));
data.append("type", 1);
const myaxios = this.axios.create({ withCredentials: false });
myaxios({
method: "post",
url: "http://localhost:5000/upload/",
data: data,
}).then((result) => {
if (result.data.code == 200) {
//将地址添加到视频地址列表中
this.srcs.push(result.data.filename);
this.$toast.success(result.data.msg);
} else {
this.$toast.fail(result.data.msg);
}
});
},
},
mounted() {
this.cid = this.$route.query.fid; //课程id
localStorage.setItem("cid", this.cid);
this.get_data();
this.get_video();
},
created() {
// 监听
bus.$on("msg", (target) => {
this.fid = target;
this.get_cate(target);
});
},
};
</script>
<style scoped>
ul {
padding-left: 10rem;
list-style: none;
}
</style>
标签:vue,树结构,params,result,fid,组件,localStorage,data,id 来源: https://blog.csdn.net/weixin_56482316/article/details/120873310