Skip to content

Commit c21dc1a

Browse files
committed
feat: init tree
1 parent c834925 commit c21dc1a

File tree

8 files changed

+34756
-7575
lines changed

8 files changed

+34756
-7575
lines changed

package-lock.json

Lines changed: 26809 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

public/index.html

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@
66
<meta name="viewport" content="width=device-width,initial-scale=1.0">
77
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
88
<title><%= htmlWebpackPlugin.options.title %></title>
9+
<% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.css) { %>
10+
<link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet">
11+
<% } %>
12+
13+
<% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.js) { %>
14+
<script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
15+
<% } %>
916
</head>
1017
<body>
1118
<noscript>

src/App.vue

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,28 @@
11
<template>
22
<div id="app">
3-
<img alt="Vue logo" src="./assets/logo.png">
4-
<HelloWorld msg="Welcome to Your Vue.js App"/>
3+
<Tree />
4+
<!-- <img alt="Vue logo" src="./assets/logo.png"> -->
5+
<!-- <Dropdown @on-click="handleClick" trigger="click">
6+
<DropdownMenu transfer slot="dropdownList">
7+
<DropdownItem data="上海">上海</DropdownItem>
8+
<DropdownItem data="北京">北京</DropdownItem>
9+
<DropdownItem data="西安">西安</DropdownItem>
10+
</DropdownMenu>
11+
</Dropdown> -->
512
</div>
613
</template>
714

815
<script>
9-
import HelloWorld from './components/HelloWorld.vue'
10-
16+
import Tree from './components/Tree'
1117
export default {
1218
name: 'App',
1319
components: {
14-
HelloWorld
20+
Tree
21+
},
22+
methods: {
23+
handleClick (data) {
24+
console.log(data)
25+
},
1526
}
1627
}
1728
</script>

src/components/HelloWorld.vue

Lines changed: 0 additions & 58 deletions
This file was deleted.

src/components/Tree.js

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
// import { construct } from "core-js/fn/reflect"
2+
3+
const TREE_DATA = {selected: false, partialSelected: false}
4+
class TreeData{
5+
constructor(data){
6+
this.name = 'TreeData'
7+
this.data = {...TREE_DATA, ...data}
8+
this.children = []
9+
}
10+
setParent(node){
11+
this.parent = node
12+
}
13+
addChild(node){
14+
this.children.push(node)
15+
node.setParent(this)
16+
}
17+
isSelected(){
18+
return this?.data?.selected ?? false
19+
}
20+
isPartialSelected(){
21+
return this?.data?.partialSelected ?? false
22+
}
23+
isAllChildrenSelected(){
24+
// eslint-disable-next-line no-debugger
25+
// debugger
26+
return this.children.every((child) => child.isSelected())
27+
}
28+
hasChildrenPartialSelected(){
29+
return !this.isAllChildrenSelected() && this.children.some((child) => child.isSelected() || child.isPartialSelected())
30+
}
31+
}
32+
33+
const demeData = [
34+
{
35+
name: '一级 1',
36+
id: '1',
37+
children: [
38+
{
39+
name: '二级 1-1',
40+
id: '2',
41+
children: [
42+
{
43+
name: '三级 1-1-1',
44+
id: '3',
45+
children: [
46+
{
47+
name: '四级 1-1-1-1',
48+
id: '4',
49+
children: [],
50+
checked: true,
51+
disabled: true
52+
},
53+
{
54+
name: '四级 1-1-1-2',
55+
id: '5',
56+
children: [],
57+
checked: false
58+
}
59+
]
60+
}
61+
]
62+
},
63+
{
64+
name: '二级 1-2',
65+
id: '8',
66+
children: [
67+
{
68+
name: '三级 1-2-1',
69+
id: '9',
70+
children: [
71+
{
72+
name: '四级 1-2-1-1',
73+
id: '10',
74+
children: []
75+
}
76+
]
77+
}
78+
]
79+
}
80+
]
81+
},
82+
{
83+
name: '一级 2',
84+
id: '11',
85+
children: [
86+
{
87+
name: '二级 2-1',
88+
id: '12',
89+
children: [
90+
{
91+
name: '三级 2-1-1',
92+
id: '13',
93+
children: [
94+
{
95+
name: '四级 2-1-1-1',
96+
id: '14',
97+
children: []
98+
}
99+
]
100+
}
101+
]
102+
},
103+
{
104+
name: '二级 2-2',
105+
id: '15',
106+
children: [
107+
{
108+
name: '三级 2-2-1',
109+
id: '16',
110+
children: [
111+
{
112+
name: '四级 2-2-1-1',
113+
id: '17',
114+
children: []
115+
}
116+
]
117+
}
118+
]
119+
}
120+
]
121+
}
122+
]
123+
124+
const generateNode = (data) => {
125+
const {id, name, children} = data
126+
const node = new TreeData({id, name})
127+
console.log(node.name)
128+
children.forEach((child) => {
129+
// eslint-disable-next-line no-debugger
130+
node.addChild(generateNode(child))
131+
})
132+
return node
133+
}
134+
135+
export default {
136+
name: 'Tree',
137+
data () {
138+
return {
139+
root: generateNode(demeData[0])
140+
141+
}
142+
},
143+
methods: {
144+
nodeView (node, level) {
145+
const {name, selected} = node?.data ?? {}
146+
return (<div style={`margin-left: ${level * 10}px; display: inline-block`}>
147+
{ node.hasChildrenPartialSelected() && `-`}
148+
<input type='checkbox' checked={selected} onClick={() => this.selectToggle(node)}/>
149+
{name}
150+
</div>)
151+
},
152+
getNode(paths) {
153+
let node = this.root
154+
// eslint-disable-next-line no-debugger
155+
// debugger
156+
// 通过索引找到对应的元素
157+
paths.forEach((path) => {
158+
node = node.children[path]
159+
})
160+
return node
161+
},
162+
getView(paths, level){
163+
const node = this.getNode(paths)
164+
const currentNode = this.nodeView(node, level)
165+
console.log('paths:::', paths)
166+
return (<div>
167+
{currentNode}
168+
{node?.children?.map((_, index) => this.getView([...paths, index], level + 1))}
169+
</div>)
170+
},
171+
refreshUp({parent}){
172+
if (!parent) return
173+
const toState = parent.isAllChildrenSelected()
174+
// eslint-disable-next-line no-debugger
175+
// debugger
176+
Object.assign(parent.data, {selected: toState, partialSelected: parent.hasChildrenPartialSelected()})
177+
this.refreshUp(parent)
178+
},
179+
refreshDown(node){
180+
const toState = node.isSelected()
181+
node?.children.forEach((child) => {
182+
const fromState = child.isSelected()
183+
if(fromState === toState){
184+
return
185+
}
186+
Object.assign(child.data, {selected: toState, partialSelected: false})
187+
this.refreshDown(child)
188+
})
189+
},
190+
selectToggle(node){
191+
192+
console.log("1:", node)
193+
Object.assign(node.data, {selected: !node.isSelected(), partialSelected: false})
194+
console.log("2:", node)
195+
this.refreshUp(node)
196+
console.log("3:", node)
197+
this.refreshDown(node)
198+
console.log("4:", node)
199+
}
200+
},
201+
render () {
202+
return (
203+
<div style='text-align: left'>
204+
{this.getView([], 0)}
205+
</div>
206+
)
207+
}
208+
}

src/main.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import Vue from 'vue'
22
import App from './App.vue'
3+
// import shscUI from 'shsc-ui'
34

45
Vue.config.productionTip = false
6+
// Vue.use(shscUI)
57

68
new Vue({
79
render: h => h(App),

vue.config.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
2+
const isProduction = process.env.NODE_ENV === 'prod'
3+
4+
console.log('isProduction:::', isProduction)
5+
const cdn = {
6+
externals: {
7+
'shsc-ui': 'shscUI'
8+
},
9+
css: [
10+
'https://testcdnqiniu.shuhaisc.com/shsc-ui/3.5.6/index.css'
11+
],
12+
js: [
13+
'https://testcdnqiniu.shuhaisc.com/shsc-ui/3.5.6/index.umd.min.js'
14+
]
15+
}
16+
17+
module.exports = {
18+
configureWebpack: config => {
19+
config.externals = cdn.externals
20+
21+
},
22+
chainWebpack: config => {
23+
config.plugin('html').tap(args => {
24+
args[0].cdn = cdn
25+
return args
26+
})
27+
}
28+
}

0 commit comments

Comments
 (0)