diff --git a/examples/docs/en-US/tree.md b/examples/docs/en-US/tree.md index ed8002a779..5030cea260 100644 --- a/examples/docs/en-US/tree.md +++ b/examples/docs/en-US/tree.md @@ -17,6 +17,35 @@ .filter-tree { margin-top: 20px; } + + .custom-tree-container { + display: flex; + margin: -24px; + } + + .block { + flex: 1; + padding: 8px 24px 24px; + + &:first-child { + border-right: solid 1px #eff2f6; + } + + > p { + text-align: center; + margin: 0; + line-height: 4; + } + } + + .custom-tree-node { + flex: 1; + display: flex; + align-items: center; + justify-content: space-between; + font-size: 14px; + padding-right: 8px; + } } @@ -218,11 +247,11 @@ this.$refs.tree.setCheckedNodes([ { id: 5, - label: '二级 2-1' + label: 'Level two 2-1' }, { id: 9, - label: '三级 1-1-1' + label: 'Level three 1-1-1' } ]); }, @@ -249,13 +278,11 @@ renderContent(h, { node, data, store }) { return ( - - - {node.label} - + + {node.label} - this.append(data) }>Append - this.remove(node, data) }>Delete + this.append(data) }>Append + this.remove(node, data) }>Delete ); }, @@ -272,6 +299,7 @@ data2, data3, data4: JSON.parse(JSON.stringify(data2)), + data5: JSON.parse(JSON.stringify(data2)), regions, defaultProps, props, @@ -685,63 +713,92 @@ Tree nodes can be initially expanded or checked ### Custom node content The content of tree nodes can be customized, so you can add icons or buttons as you will -:::demo Use `render-content` to assign a render function that returns the content of tree nodes. See Vue's documentation for a detailed introduction of render functions. Note that this demo can't run in jsfiddle because it doesn't support JSX syntax. In a real project, `render-content` will work if relevant dependencies are correctly configured. +:::demo There are two ways to customize template for tree nodes: `render-content` and scoped slot. Use `render-content` to assign a render function that returns the content of tree nodes. See Vue's documentation for a detailed introduction of render functions. If you prefer scoped slot, you'll have access to `node` and `data` in the scope, standing for the TreeNode object and node data of the current node respectively. Note that the `render-content` demo can't run in jsfiddle because it doesn't support JSX syntax. In a real project, `render-content` will work if relevant dependencies are correctly configured. ```html - - +
+
+

Using render-content

+ + +
+
+

Using scoped slot

+ + + {{ node.label }} + + + Append + + + Delete + + + + +
+
+ + ``` ::: @@ -986,3 +1052,8 @@ Only one node among the same level can be expanded at one time. | current-change | triggers when current node changes | two parameters: node object corresponding to the current node, `node` property of TreeNode | | node-expand | triggers when current node open | three parameters: node object corresponding to the node opened, `node` property of TreeNode, TreeNode itself | | node-collapse | triggers when current node close | three parameters: node object corresponding to the node closed, `node` property of TreeNode, TreeNode itself | + +### Scoped slot +| name | Description | +|------|--------| +| — | Custom content for tree nodes. The scope parameter is { node, data } | diff --git a/examples/docs/es/tree.md b/examples/docs/es/tree.md index 31be8d8b51..0d24beee8e 100644 --- a/examples/docs/es/tree.md +++ b/examples/docs/es/tree.md @@ -17,6 +17,35 @@ .filter-tree { margin-top: 20px; } + + .custom-tree-container { + display: flex; + margin: -24px; + } + + .block { + flex: 1; + padding: 8px 24px 24px; + + &:first-child { + border-right: solid 1px #eff2f6; + } + + > p { + text-align: center; + margin: 0; + line-height: 4; + } + } + + .custom-tree-node { + flex: 1; + display: flex; + align-items: center; + justify-content: space-between; + font-size: 14px; + padding-right: 8px; + } } @@ -218,11 +247,11 @@ this.$refs.tree.setCheckedNodes([ { id: 5, - label: '二级 2-1' + label: 'Level two 2-1' }, { id: 9, - label: '三级 1-1-1' + label: 'Level three 1-1-1' } ]); }, @@ -249,13 +278,11 @@ renderContent(h, { node, data, store }) { return ( - - - {node.label} - + + {node.label} - this.append(data) }>Append - this.remove(node, data) }>Delete + this.append(data) }>Append + this.remove(node, data) }>Delete ); }, @@ -272,6 +299,7 @@ data2, data3, data4: JSON.parse(JSON.stringify(data2)), + data5: JSON.parse(JSON.stringify(data2)), regions, defaultProps, props, @@ -685,63 +713,92 @@ Los nodos pueden estar desplegados o seleccionados por defecto. ### Contenido personalizado en los nodos El contenido de los nodos puede ser personalizado, así que puede añadir iconos y botones a su gusto. -:::demo Utilice `render-content` para asignar una función de renderizado que devuelve el contenido del árbol de nodos. Mire la documentación de node para una introducción detallada a las funciondes de renderizado. Ten en cuenta que este ejemplo no puede ejecutarse en jsfiddle ya que no soporta la sintaxis JSX. En un proyecto real `render-content` funcionará si las dependencias relevantes están configuradas correctamente. +:::demo There are two ways to customize template for tree nodes: `render-content` and scoped slot. Utilice `render-content` para asignar una función de renderizado que devuelve el contenido del árbol de nodos. Mire la documentación de node para una introducción detallada a las funciondes de renderizado. If you prefer scoped slot, you'll have access to `node` and `data` in the scope, standing for the TreeNode object and node data of the current node respectively. Ten en cuenta que este ejemplo no puede ejecutarse en jsfiddle ya que no soporta la sintaxis JSX. En un proyecto real `render-content` funcionará si las dependencias relevantes están configuradas correctamente. ```html - - +
+
+

Using render-content

+ + +
+
+

Using scoped slot

+ + + {{ node.label }} + + + Append + + + Delete + + + + +
+
+ + ``` ::: @@ -984,3 +1050,8 @@ Solo puede ser expandido un nodo del mismo nivel a la vez. | current-change | cambia cuando el nodo actual cambia | dos parámetros: objeto nodo que se corresponde al nodo actual y propiedad `node` del TreeNode | | node-expand | se lanza cuando el nodo actual se abre | tres parámetros: el objeto del nodo abierto, propiedad `node` de TreeNode y el TreeNode en si | | node-collapse | se lanza cuando el nodo actual se cierra | tres parámetros: el objeto del nodo cerrado, propiedad `node` de TreeNode y el TreeNode en si | + +### Scoped slot +| name | Description | +|------|--------| +| — | Custom content for tree nodes. The scope parameter is { node, data } | \ No newline at end of file diff --git a/examples/docs/zh-CN/tree.md b/examples/docs/zh-CN/tree.md index d2aeb38206..57dedbe728 100644 --- a/examples/docs/zh-CN/tree.md +++ b/examples/docs/zh-CN/tree.md @@ -17,6 +17,35 @@ .filter-tree { margin-top: 20px; } + + .custom-tree-container { + display: flex; + margin: -24px; + } + + .block { + flex: 1; + padding: 8px 24px 24px; + + &:first-child { + border-right: solid 1px #eff2f6; + } + + > p { + text-align: center; + margin: 0; + line-height: 4; + } + } + + .custom-tree-node { + flex: 1; + display: flex; + align-items: center; + justify-content: space-between; + font-size: 14px; + padding-right: 8px; + } } @@ -249,13 +278,11 @@ renderContent(h, { node, data }) { return ( - - - {node.label} - + + {node.label} - this.append(data) }>Append - this.remove(node, data) }>Delete + this.append(data) }>Append + this.remove(node, data) }>Delete ); }, @@ -272,6 +299,7 @@ data2, data3, data4: JSON.parse(JSON.stringify(data2)), + data5: JSON.parse(JSON.stringify(data2)), regions, defaultProps, props, @@ -684,63 +712,92 @@ ### 自定义节点内容 节点的内容支持自定义,可以在节点区添加按钮或图标等内容 -:::demo 使用`render-content`指定渲染函数,该函数返回需要的节点区内容即可。渲染函数的用法请参考 Vue 文档。注意:由于 jsfiddle 不支持 JSX 语法,所以本例在 jsfiddle 中无法运行。但是在实际的项目中,只要正确地配置了相关依赖,就可以正常运行。 +:::demo 可以通过两种方法进行树节点内容的自定义:`render-content`和 scoped slot。使用`render-content`指定渲染函数,该函数返回需要的节点区内容即可。渲染函数的用法请参考 Vue 文档。使用 scoped slot 会传入两个参数`node`和`data`,分别表示当前节点的 Node 对象和当前节点的数据。注意:由于 jsfiddle 不支持 JSX 语法,所以`render-content`示例在 jsfiddle 中无法运行。但是在实际的项目中,只要正确地配置了相关依赖,就可以正常运行。 ```html - - +
+
+

使用 render-content

+ + +
+
+

使用 scoped slot

+ + + {{ node.label }} + + + Append + + + Delete + + + + +
+
+ + ``` ::: @@ -985,3 +1051,8 @@ | current-change | 当前选中节点变化时触发的事件 | 共两个参数,依次为:当前节点的数据,当前节点的 Node 对象 | | node-expand | 节点被展开时触发的事件 | 共三个参数,依次为:传递给 `data` 属性的数组中该节点所对应的对象、节点对应的 Node、节点组件本身。 | | node-collapse | 节点被关闭时触发的事件 | 共三个参数,依次为:传递给 `data` 属性的数组中该节点所对应的对象、节点对应的 Node、节点组件本身。 | + +### Scoped slot +| name | 说明 | +|------|--------| +| — | 自定义树节点的内容,参数为 { node, data } | diff --git a/packages/tree/src/tree-node.vue b/packages/tree/src/tree-node.vue index d9f74b1158..6020581302 100644 --- a/packages/tree/src/tree-node.vue +++ b/packages/tree/src/tree-node.vue @@ -97,13 +97,15 @@ }, render(h) { const parent = this.$parent; + const tree = parent.tree; const node = this.node; - const data = node.data; - const store = node.store; + const { data, store } = node; return ( parent.renderContent - ? parent.renderContent.call(parent._renderProxy, h, { _self: parent.tree.$vnode.context, node, data, store }) - : { this.node.label } + ? parent.renderContent.call(parent._renderProxy, h, { _self: tree.$vnode.context, node, data, store }) + : tree.$scopedSlots.default + ? tree.$scopedSlots.default({ node, data }) + : { this.node.label } ); } } diff --git a/test/unit/specs/tree.spec.js b/test/unit/specs/tree.spec.js index 6a73e29e04..fb9e57bfde 100644 --- a/test/unit/specs/tree.spec.js +++ b/test/unit/specs/tree.spec.js @@ -501,6 +501,63 @@ describe('Tree', () => { expect(button.textContent).to.equal('一级 1'); }); + it('scoped slot', () => { + vm = createVue({ + template: ` + +
+ {{ scope.node.label }} + +
+
+ `, + + data() { + return { + data: [{ + id: 1, + label: '一级 1', + children: [{ + id: 11, + label: '二级 1-1', + children: [{ + id: 111, + label: '三级 1-1' + }] + }] + }, { + id: 2, + label: '一级 2', + children: [{ + id: 21, + label: '二级 2-1' + }, { + id: 22, + label: '二级 2-2' + }] + }, { + id: 3, + label: '一级 3', + children: [{ + id: 31, + label: '二级 3-1' + }, { + id: 32, + label: '二级 3-2' + }] + }] + }; + } + }, true); + const firstNode = document.querySelector('.custom-tree-template'); + expect(firstNode).to.exist; + const span = firstNode.querySelector('span'); + const button = firstNode.querySelector('.el-button'); + expect(span).to.exist; + expect(span.innerText).to.equal('一级 1'); + expect(button).to.exist; + }); + it('load node', done => { vm = getTreeVm(':props="defaultProps" lazy :load="loadNode" show-checkbox', { methods: {