├── .babelrc
├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── build
├── gh-pages.sh
├── webpack.config.js
├── webpack.example.base.conf.js
├── webpack.example.dev.conf.js
└── webpack.example.prod.conf.js
├── example
├── index.html
└── src
│ ├── App.vue
│ ├── best-rating.vue
│ ├── main.js
│ └── template.js
├── lib
└── collapse.js
├── package.json
├── screenshot
└── collapse.gif
├── src
├── components
│ ├── collapse-item.vue
│ └── collapse.vue
├── index.js
├── styles
│ └── less
│ │ ├── base.less
│ │ ├── collapse.less
│ │ └── index.less
├── transitions
│ └── collapse-transition.js
└── utils
│ └── dom.js
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["env", { "modules": false }]
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | **/*.js linguist-language=Vue
2 | **/*.less linguist-language=Vue
3 | **/*.css linguist-language=Vue
4 | **/*.html linguist-language=Vue
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | .idea
4 | example/dist
5 | gh-pages
6 | images
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # collapse
2 |
3 | > [Element](https://github.com/ElemeFE/element) Collapse clone, extract the core function and did a little change. If you have a better idea of this component improvement, please share it and I will update it immediately.
4 |
5 | ## Screenshots
6 |
7 | 
8 |
9 | ## Install
10 |
11 | ```bash
12 | npm install vue-multiple-collapse -S
13 | ```
14 |
15 | ## Quick Start
16 |
17 | ```bash
18 | import Vue from 'vue'
19 | import {VmCollapse, VmCollapseItem } from 'vue-multiple-collapse'
20 | Vue.component('vm-collapse', VmCollapse)
21 | Vue.component('vm-collapse-item', VmCollapseItem)
22 | ```
23 |
24 | OR
25 |
26 | ```bash
27 | import Vue from 'vue'
28 | import VmCollapse from 'vue-multiple-collapse'
29 | Vue.use(VmCollapse)
30 | ```
31 |
32 | For more information, please refer to [Collapse](https://vue-multiple.github.io/collapse) in our documentation.
33 |
34 | ## Build Setup
35 |
36 | ``` bash
37 | # install dependencies
38 | npm install
39 |
40 | # serve with hot reload at localhost:8080
41 | npm run demo:dev
42 |
43 | # build for demo with minification
44 | npm run demo:build
45 |
46 | # build for gh-pages with minification
47 | npm run demo:prepublish
48 |
49 | # build for production with minification
50 | npm run build
51 |
52 | # generate gh-pages
53 | npm run deploy
54 | ```
55 |
56 | ## LICENSE
57 |
58 | [MIT](http://opensource.org/licenses/MIT)
59 |
--------------------------------------------------------------------------------
/build/gh-pages.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | npm run demo:prepublish
3 | cd gh-pages
4 | git init
5 | git add -A
6 | git commit -m 'update gh-pages'
7 | git push -f git@github.com:vue-multiple/collapse.git master:gh-pages
--------------------------------------------------------------------------------
/build/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var webpack = require('webpack')
3 | var ExtractTextPlugin = require('extract-text-webpack-plugin')
4 |
5 | module.exports = {
6 | entry: './src/index.js',
7 | output: {
8 | path: path.resolve(__dirname, '..', './lib'),
9 | filename: 'collapse.js',
10 | library: 'collapse',
11 | libraryTarget: 'umd'
12 | },
13 | externals: {
14 | vue: {
15 | root: 'Vue',
16 | commonjs: 'vue',
17 | commonjs2: 'vue',
18 | amd: 'vue'
19 | }
20 | },
21 | module: {
22 | rules: [
23 | {
24 | test: /\.vue$/,
25 | loader: 'vue-loader',
26 | options: {
27 | loaders: {
28 | css: 'vue-style-loader!css-loader',
29 | less: 'vue-style-loader!css-loader!less-loader',
30 | // css: ExtractTextPlugin.extract({
31 | // use: 'css-loader',
32 | // fallback: 'vue-style-loader'
33 | // }),
34 | // less: ExtractTextPlugin.extract({
35 | // fallback: 'vue-style-loader',
36 | // use: ['css-loader', 'less-loader']
37 | // })
38 | }
39 | // other vue-loader options go here
40 | }
41 | },
42 | {
43 | test: /\.css$/,
44 | use: [
45 | { loader: 'style-loader' },
46 | { loader: 'css-loader' }
47 | ]
48 | // loader: ExtractTextPlugin.extract({
49 | // use: "css-loader",
50 | // fallback: "style-loader"
51 | // })
52 | },
53 | {
54 | test: /\.less$/,
55 | use: [
56 | { loader: 'style-loader' },
57 | { loader: 'css-loader' },
58 | { loader: 'less-loader' }
59 | ]
60 | // loader: ExtractTextPlugin.extract({
61 | // fallback: 'style-loader',
62 | // use: ['css-loader', 'less-loader']
63 | // })
64 | },
65 | {
66 | test: /\.js$/,
67 | loader: 'babel-loader',
68 | exclude: /node_modules/
69 | },
70 | {
71 | test: /\.(png|jpg|gif|svg)$/,
72 | loader: 'file-loader',
73 | options: {
74 | name: '[name].[ext]?[hash]'
75 | }
76 | },
77 | {
78 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
79 | loader: 'url-loader',
80 | query: {
81 | limit: 10000,
82 | name: path.posix.join('static', 'fonts/[name].[hash:7].[ext]')
83 | }
84 | }
85 | ]
86 | },
87 | resolve: {
88 | extensions: ['.js', '.vue', '.json']
89 | },
90 | plugins: [
91 | new webpack.optimize.UglifyJsPlugin({
92 | sourceMap: true,
93 | compress: {
94 | warnings: false
95 | }
96 | })
97 | // ,
98 | // new ExtractTextPlugin({
99 | // filename: '../lib/collapse.css',
100 | // allChunks: true
101 | // })
102 | ]
103 | }
104 |
--------------------------------------------------------------------------------
/build/webpack.example.base.conf.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var ExtractTextPlugin = require('extract-text-webpack-plugin')
3 | var isProduction = process.env.NODE_ENV === 'production'
4 |
5 | module.exports = {
6 | entry: {
7 | app: './example/src/main.js'
8 | },
9 | output: {
10 | path: '/example',
11 | filename: '[name].js',
12 | publicPath: '/'
13 | },
14 | module: {
15 | rules: [
16 | {
17 | test: /\.vue$/,
18 | loader: 'vue-loader',
19 | options: {
20 | // other vue-loader options go here
21 | loaders: {
22 | css: isProduction ? ExtractTextPlugin.extract({
23 | fallback: 'vue-style-loader',
24 | use: 'css-loader'
25 | }) : 'vue-style-loader!css-loader',
26 | less: isProduction ? ExtractTextPlugin.extract({
27 | fallback: 'vue-style-loader',
28 | use: ['css-loader', 'less-loader']
29 | }) : 'vue-style-loader!css-loader!less-loader'
30 | }
31 | }
32 | },
33 | {
34 | test: /\.js$/,
35 | loader: 'babel-loader',
36 | exclude: /node_modules/
37 | },
38 | {
39 | test: /\.(png|jpg|gif|svg)$/,
40 | loader: 'file-loader',
41 | options: {
42 | name: '[name].[ext]?[hash]',
43 | publicPath: '../example/src/images/',
44 | outputPath: '../gh-pages/images/'
45 | }
46 | },
47 | {
48 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
49 | loader: 'url-loader',
50 | query: {
51 | limit: 10000,
52 | name: path.posix.join('static', 'fonts/[name].[hash:7].[ext]')
53 | }
54 | }
55 | ]
56 | }
57 | }
--------------------------------------------------------------------------------
/build/webpack.example.dev.conf.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack')
2 | var merge = require('webpack-merge')
3 | var baseWebpackConfig = require('./webpack.example.base.conf')
4 | var HtmlWebpackPlugin = require('html-webpack-plugin')
5 | var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
6 |
7 | module.exports = merge(baseWebpackConfig, {
8 | module: {
9 | rules: [
10 | {
11 | test: /\.css$/,
12 | loader: 'vue-style-loader!css-loader'
13 | },
14 | {
15 | test: /\.less$/,
16 | loader: 'vue-style-loader!css-loader!less-loader'
17 | }
18 | ]
19 | },
20 | // cheap-module-eval-source-map is faster for development
21 | devtool: '#cheap-module-eval-source-map',
22 | plugins: [
23 | new webpack.DefinePlugin({
24 | 'process.env': {
25 | NODE_ENV: '"development"'
26 | }
27 | }),
28 | new webpack.NoEmitOnErrorsPlugin(),
29 | new HtmlWebpackPlugin({
30 | filename: 'index.html',
31 | template: 'example/index.html',
32 | inject: true
33 | }),
34 | new FriendlyErrorsPlugin()
35 | ]
36 | })
--------------------------------------------------------------------------------
/build/webpack.example.prod.conf.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var webpack = require('webpack')
3 | var merge = require('webpack-merge')
4 | var baseWebpackConfig = require('./webpack.example.base.conf')
5 | var HtmlWebpackPlugin = require('html-webpack-plugin')
6 | var ExtractTextPlugin = require('extract-text-webpack-plugin')
7 | var isProduction = process.env.NODE_ENV === 'production'
8 |
9 | module.exports = merge(baseWebpackConfig, {
10 | module: {
11 | rules: [
12 | {
13 | test: /\.css$/,
14 | loader: ExtractTextPlugin.extract({
15 | fallback: "vue-style-loader",
16 | use: "css-loader"
17 | })
18 | },
19 | {
20 | test: /\.less/,
21 | loader: ExtractTextPlugin.extract({
22 | fallback: "vue-style-loader",
23 | use: ["css-loader", "less-loader"]
24 | })
25 | }
26 | ]
27 | },
28 | devtool: '#source-map',
29 | output: {
30 | path: path.resolve(__dirname, '..', `${isProduction ? './example/dist' : 'gh-pages'}`),
31 | publicPath: isProduction ? '/' : '/collapse',
32 | filename: 'js/[name].[chunkhash].js'
33 | },
34 | plugins: [
35 | new webpack.DefinePlugin({
36 | 'process.env': {
37 | NODE_ENV: '"production"'
38 | }
39 | }),
40 | new webpack.optimize.UglifyJsPlugin({
41 | sourceMap: true,
42 | compress: {
43 | warnings: false
44 | }
45 | }),
46 | new ExtractTextPlugin({
47 | filename: 'css/[name].[contenthash].css',
48 | allChunks: true
49 | }),
50 | new HtmlWebpackPlugin({
51 | filename: 'index.html',
52 | template: 'example/index.html',
53 | inject: true,
54 | minify: {
55 | removeComments: true,
56 | collapseWhitespace: true,
57 | removeAttributeQuotes: true
58 | // more options:
59 | // https://github.com/kangax/html-minifier#options-quick-reference
60 | },
61 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin
62 | chunksSortMode: 'dependency'
63 | })
64 | ]
65 | })
66 |
--------------------------------------------------------------------------------
/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 | collapse
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/example/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
12 |
13 | 通过多个组件(Collapse折叠面板,Rate评分,Tabs标签页)结合
16 |
17 |
18 |
19 |
20 |
21 |
26 |
27 | 基础用法 (改进特性)
28 |
29 |
30 |
31 |
默认
32 |
33 |
34 | 与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;
35 | 在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。
36 |
37 |
38 | 控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;
39 | 页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。
40 |
41 |
42 | 简化流程:设计简洁直观的操作流程;
43 | 清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;
44 | 帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。
45 |
46 |
47 | 用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;
48 | 结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。
49 |
50 |
51 |
52 |
53 |
带边框
54 |
55 |
56 | 与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;
57 | 在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。
58 |
59 |
60 | 控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;
61 | 页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。
62 |
63 |
64 | 简化流程:设计简洁直观的操作流程;
65 | 清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;
66 | 帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。
67 |
68 |
69 | 用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;
70 | 结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。
71 |
72 |
73 |
74 |
75 |
76 | 通过添加 vm-collapse
组件添加 class="vm-collapse--bordered"
来为组件添加边框。
77 |
78 |
79 |
84 |
85 | 每次只能展开一个面板
86 |
87 |
88 |
89 |
90 |
91 | 与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;
92 | 在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。
93 |
94 |
95 | 控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;
96 | 页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。
97 |
98 |
99 | 简化流程:设计简洁直观的操作流程;
100 | 清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;
101 | 帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。
102 |
103 |
104 | 用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;
105 | 结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。
106 |
107 |
108 |
109 |
110 |
111 | 通过 accordion
属性来设置是否以手风琴模式显示。
112 |
113 |
114 |
119 |
120 | 变换 (新增特性,新增示例)
121 |
122 |
123 |
124 |
默认模式下
125 |
126 |
127 | 与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;
128 | 在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。
129 |
130 |
131 | 控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;
132 | 页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。
133 |
134 |
135 | 简化流程:设计简洁直观的操作流程;
136 | 清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;
137 | 帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。
138 |
139 |
140 | 用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;
141 | 结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。
142 |
143 |
144 |
145 |
146 |
手风琴模式下
147 |
148 |
149 | 与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;
150 | 在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。
151 |
152 |
153 | 控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;
154 | 页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。
155 |
156 |
157 | 简化流程:设计简洁直观的操作流程;
158 | 清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;
159 | 帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。
160 |
161 |
162 | 用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;
163 | 结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。
164 |
165 |
166 |
167 |
168 |
169 | 通过 transform
属性来设置是否以变换模式显示。
170 |
171 |
172 |
177 |
178 | 多个展开面板 (新增特性,新增示例)
179 |
180 |
181 |
182 |
默认模式下
183 |
184 |
185 | 与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;
186 | 在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。
187 |
188 |
189 | 控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;
190 | 页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。
191 |
192 |
193 | 简化流程:设计简洁直观的操作流程;
194 | 清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;
195 | 帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。
196 |
197 |
198 | 用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;
199 | 结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。
200 |
201 |
202 |
203 |
204 |
默认模式下(可关闭)
205 |
206 |
207 | 与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;
208 | 在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。
209 |
210 |
211 | 控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;
212 | 页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。
213 |
214 |
215 | 简化流程:设计简洁直观的操作流程;
216 | 清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;
217 | 帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。
218 |
219 |
220 | 用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;
221 | 结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。
222 |
223 |
224 |
225 |
226 |
手风琴模式下(无效)
227 |
228 |
229 | 与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;
230 | 在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。
231 |
232 |
233 | 控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;
234 | 页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。
235 |
236 |
237 | 简化流程:设计简洁直观的操作流程;
238 | 清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;
239 | 帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。
240 |
241 |
242 | 用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;
243 | 结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。
244 |
245 |
246 |
247 |
248 |
变换模式下
249 |
250 |
251 | 与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;
252 | 在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。
253 |
254 |
255 | 控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;
256 | 页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。
257 |
258 |
259 | 简化流程:设计简洁直观的操作流程;
260 | 清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;
261 | 帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。
262 |
263 |
264 | 用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;
265 | 结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。
266 |
267 |
268 |
269 |
270 |
271 | 通过 remain
属性来设置最多展开面板的数量,同时指定 closable
属性来设置是否可以关闭展开的面板。
272 |
273 |
274 |
279 |
280 | 自定义面板 (改进特性,新增示例)
281 |
282 |
283 | 除了可以通过 title
属性以外,还可以通过具名 slot="title"
来实现自定义面板的标题内容,以实现增加图标等效果。还可以通过 具名 slot="header" 来实现自定义面板的头部内容。
284 |
285 |
286 |
287 |
自定义标题
288 |
289 |
290 |
291 | 自定义标题
292 |
293 | 与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;
294 | 在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。
295 |
296 |
297 | 控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;
298 | 页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。
299 |
300 |
301 | 简化流程:设计简洁直观的操作流程;
302 | 清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;
303 | 帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。
304 |
305 |
306 | 用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;
307 | 结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。
308 |
309 |
310 |
311 |
312 |
自定义头部
313 |
314 |
315 |
316 | 自定义头部
317 |
318 | 与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;
319 | 在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。
320 |
321 |
322 | 控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;
323 | 页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。
324 |
325 |
326 | 简化流程:设计简洁直观的操作流程;
327 | 清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;
328 | 帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。
329 |
330 |
331 | 用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;
332 | 结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。
333 |
334 |
335 |
336 |
337 |
338 |
342 |
343 |
344 |
345 |
346 | 参数 |
347 | 说明 |
348 | 类型 |
349 | 可选值 |
350 | 默认值 |
351 |
352 |
353 |
354 |
355 | accordion |
356 | 是否手风琴模式 |
357 | boolean |
358 | — |
359 | false |
360 |
361 |
362 | transform (新增) |
363 | 是否变换模式 |
364 | boolean |
365 | — |
366 | false |
367 |
368 |
369 | remain (新增) |
370 | 最多展开面板的数量 |
371 | number |
372 | — |
373 | 0 |
374 |
375 |
376 | closable (新增) |
377 | 展开面板数量>=指定remain值是,被激活的面板是否可关闭 |
378 | boolean |
379 | — |
380 | false |
381 |
382 |
383 | value |
384 | 当前激活的面板(如果是手风琴模式,绑定值类型需要为string ,否则为array ) |
385 | string/array |
386 | — |
387 | — |
388 |
389 |
390 |
391 |
392 |
393 |
397 |
398 |
399 |
400 |
401 | 事件名称 |
402 | 说明 |
403 | 回调参数 |
404 |
405 |
406 |
407 |
408 | change |
409 | 当前激活面板改变时触发(如果是手风琴模式,参数 activeNames 类型为string ,否则为array ) |
410 | (activeNames: array|string) |
411 |
412 |
413 |
414 |
415 |
416 |
420 |
421 |
422 |
423 |
424 | 参数 |
425 | 说明 |
426 | 类型 |
427 | 可选值 |
428 | 默认值 |
429 |
430 |
431 |
432 |
433 | name |
434 | 唯一标志符 |
435 | string/number |
436 | — |
437 | — |
438 |
439 |
440 | title |
441 | 面板标题 |
442 | string |
443 | — |
444 | — |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
607 |
608 |
616 |
--------------------------------------------------------------------------------
/example/src/best-rating.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | {{item.rank}}
9 | {{item.name}}
10 | {{item.type}}
11 |
12 |
13 |
{{item.rank}}
14 |
![]()
15 |
16 | {{item.name}}
17 |
24 | {{item.type}}
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
54 |
--------------------------------------------------------------------------------
/example/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App.vue'
3 |
4 | import Collapse from '../../src/index.js'
5 | Vue.use(Collapse)
6 |
7 | import VmRate from 'vue-multiple-rate'
8 | import 'vue-multiple-rate/lib/rate.css'
9 | Vue.component(VmRate.name, VmRate)
10 |
11 | import VmTabs from 'vue-multiple-tabs'
12 | Vue.use(VmTabs)
13 |
14 | import VueDemonstration from 'vue-demonstration'
15 | Vue.component('demonstration', VueDemonstration)
16 |
17 | new Vue({
18 | el: '#app',
19 | render: h => h(App)
20 | })
21 |
--------------------------------------------------------------------------------
/example/src/template.js:
--------------------------------------------------------------------------------
1 | export const sourcecodeA = `
2 |
默认
3 |
4 |
5 | 与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;
6 | 在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。
7 |
8 |
9 | 控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;
10 | 页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。
11 |
12 |
13 | 简化流程:设计简洁直观的操作流程;
14 | 清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;
15 | 帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。
16 |
17 |
18 | 用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;
19 | 结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。
20 |
21 |
22 |
23 |
24 | 带边框
25 |
26 | ...
27 |
28 |
29 |
30 | `
40 |
41 | export const sourcecodeB = `
42 | ...
43 |
44 |
45 | `
54 |
55 | export const sourcecodeC = `
56 | 默认模式下
57 |
58 | ...
59 |
60 |
61 |
62 | 手风琴模式下
63 |
64 | ...
65 |
66 |
67 |
68 | `
78 |
79 | export const sourcecodeD = `
80 | 默认模式下
81 |
82 | ...
83 |
84 |
85 |
86 | 默认模式下(可关闭)
87 |
88 | ...
89 |
90 |
91 |
92 | 手风琴模式下(无效)
93 |
94 | ...
95 |
96 |
97 |
98 | 变换模式下
99 |
100 | ...
101 |
102 |
103 |
104 | `
116 |
117 | export const sourcecodeE = `
118 |
自定义标题
119 |
120 |
121 |
122 | 自定义标题
123 |
124 | 与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;
125 | 在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。
126 |
127 | ...
128 |
129 |
130 |
131 |
自定义头部
132 |
133 |
134 |
135 | 自定义头部
136 |
137 | 与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;
138 | 在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。
139 |
140 | ...
141 |
142 |
`
--------------------------------------------------------------------------------
/lib/collapse.js:
--------------------------------------------------------------------------------
1 | !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.collapse=t():e.collapse=t()}(this,function(){return function(e){function t(o){if(n[o])return n[o].exports;var r=n[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,t),r.l=!0,r.exports}var n={};return t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,o){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:o})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=6)}([function(e,t){e.exports=function(e,t,n,o,r){var i,a=e=e||{},s=typeof e.default;"object"!==s&&"function"!==s||(i=e,a=e.default);var l="function"==typeof a?a.options:a;t&&(l.render=t.render,l.staticRenderFns=t.staticRenderFns),o&&(l._scopeId=o);var c;if(r?(c=function(e){e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext,e||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),n&&n.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(r)},l._ssrRegister=c):n&&(c=n),c){var u=l.functional,d=u?l.render:l.beforeCreate;u?l.render=function(e,t){return c.call(t),d(e,t)}:l.beforeCreate=d?[].concat(d,c):[c]}return{esModule:i,exports:a,options:l}}},function(e,t,n){var o=n(9);"string"==typeof o&&(o=[[e.i,o,""]]);var r={};r.transform=void 0;n(11)(o,r);o.locals&&(e.exports=o.locals)},function(e,t,n){var o=n(0)(n(4),n(14),null,null,null);o.options.__file="F:\\DailyLearning\\collapse\\src\\components\\collapse-item.vue",o.esModule&&Object.keys(o.esModule).some(function(e){return"default"!==e&&"__"!==e.substr(0,2)})&&console.error("named exports are not supported in *.vue files."),o.options.functional&&console.error("[vue-loader] collapse-item.vue: functional components are not supported with templates, they should use render functions."),e.exports=o.exports},function(e,t,n){var o=n(0)(n(5),n(13),null,null,null);o.options.__file="F:\\DailyLearning\\collapse\\src\\components\\collapse.vue",o.esModule&&Object.keys(o.esModule).some(function(e){return"default"!==e&&"__"!==e.substr(0,2)})&&console.error("named exports are not supported in *.vue files."),o.options.functional&&console.error("[vue-loader] collapse.vue: functional components are not supported with templates, they should use render functions."),e.exports=o.exports},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var o=n(7);t.default={name:"VmCollapseItem",componentName:"VmCollapseItem",components:{"vm-collapse-transition":o.a},props:{title:String,name:{type:[String,Number],default:function(){return this._uid}}},computed:{isActive:function(){return this.$parent.activeNames.indexOf(this.name)>-1},transform:function(){var e=this.findParentComponentByName("VmCollapse");return e&&e.transform},remain:function(){var e=this.findParentComponentByName("VmCollapse");return e&&e.remain},closable:function(){var e=this.findParentComponentByName("VmCollapse");return e&&e.closable}},methods:{handleClick:function(e){var t=this.$parent.activeNames.length;this.remain&&t>=this.remain&&this.isActive&&!this.closable||this.dispatch("VmCollapse","item-click",this)},dispatch:function(e,t,n){var o=this.findParentComponentByName(e);o&&o.$emit.apply(o,[t].concat(n))},findParentComponentByName:function(e){for(var t=this.$parent||this.$root,n=t.$options.componentName;t&&(!n||n!==e);)(t=t.$parent)&&(n=t.$options.componentName);return t}}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default={name:"VmCollapse",componentName:"VmCollapse",props:{accordion:Boolean,transform:Boolean,closable:Boolean,remain:{type:Number,default:0},value:{type:[Array,String,Number],default:function(){return[]}}},data:function(){return{activeNames:[].concat(this.value)}},watch:{value:function(e){this.activeNames=[].concat(e)}},methods:{setActiveNames:function(e){e=[].concat(e);var t=this.accordion?e[0]:e;this.activeNames=e,this.$emit("input",t),this.$emit("change",t)},handleItemClick:function(e){if(this.accordion)this.setActiveNames(!this.activeNames[0]&&0!==this.activeNames[0]||this.activeNames[0]!==e.name?e.name:"");else{var t=this.activeNames.slice(0),n=t.indexOf(e.name);n>-1?t.splice(n,1):(t.push(e.name),this.remain&&t.length>this.remain&&t.shift()),this.setActiveNames(t)}}},created:function(){this.$on("item-click",this.handleItemClick)}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var o=n(3),r=n.n(o),i=n(2),a=n.n(i),s=n(1);n.n(s);n.d(t,"VmCollapse",function(){return r.a}),n.d(t,"VmCollapseItem",function(){return a.a});var l=function e(t){arguments.length>1&&void 0!==arguments[1]&&arguments[1];e.installed||(t.component(r.a.name,r.a),t.component(a.a.name,a.a))};"undefined"!=typeof window&&window.Vue&&l(window.Vue),t.default={install:l,VmCollapse:r.a,VmCollapseItem:a.a}},function(e,t,n){"use strict";function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var r=n(8),i=function(){function e(e,t){for(var n=0;n-1}function i(e,t){if(e){for(var n=e.className,o=(t||"").split(" "),i=0,a=o.length;i .vm-collapse-item__header .vm-collapse-icon--arrow-right {\n top: 6px;\n transform: rotate(90deg);\n}\n.vm-collapse-item:last-child {\n margin-bottom: -1px;\n}\n.vm-collapse-icon--arrow-right {\n position: relative;\n top: 2px;\n display: inline-block;\n width: 14px;\n height: 14px;\n transform: rotate(0deg);\n}\n.vm-collapse-icon--arrow-right:after {\n content: "";\n display: block;\n width: 0;\n height: 0;\n border: 7px solid transparent;\n border-left-color: #48576a;\n}\n.vm-collapse .collapse-transition {\n transition: 0.3s height ease-in-out, 0.3s padding-top ease-in-out, 0.3s padding-bottom ease-in-out;\n}\n',""])},function(e,t){function n(e,t){var n=e[1]||"",r=e[3];if(!r)return n;if(t&&"function"==typeof btoa){var i=o(r);return[n].concat(r.sources.map(function(e){return"/*# sourceURL="+r.sourceRoot+e+" */"})).concat([i]).join("\n")}return[n].join("\n")}function o(e){return"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(e))))+" */"}e.exports=function(e){var t=[];return t.toString=function(){return this.map(function(t){var o=n(t,e);return t[2]?"@media "+t[2]+"{"+o+"}":o}).join("")},t.i=function(e,n){"string"==typeof e&&(e=[[null,e,""]]);for(var o={},r=0;r=0&&b.splice(t,1)}function s(e){var t=document.createElement("style");return e.attrs.type="text/css",c(t,e.attrs),i(e,t),t}function l(e){var t=document.createElement("link");return e.attrs.type="text/css",e.attrs.rel="stylesheet",c(t,e.attrs),i(e,t),t}function c(e,t){Object.keys(t).forEach(function(n){e.setAttribute(n,t[n])})}function u(e,t){var n,o,r,i;if(t.transform&&e.css){if(!(i=t.transform(e.css)))return function(){};e.css=i}if(t.singleton){var c=y++;n=g||(g=s(t)),o=d.bind(null,n,c,!1),r=d.bind(null,n,c,!0)}else e.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(n=l(t),o=p.bind(null,n,t),r=function(){a(n),n.href&&URL.revokeObjectURL(n.href)}):(n=s(t),o=f.bind(null,n),r=function(){a(n)});return o(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;o(e=t)}else r()}}function d(e,t,n,o){var r=n?"":o.css;if(e.styleSheet)e.styleSheet.cssText=x(t,r);else{var i=document.createTextNode(r),a=e.childNodes;a[t]&&e.removeChild(a[t]),a.length?e.insertBefore(i,a[t]):e.appendChild(i)}}function f(e,t){var n=t.css,o=t.media;if(o&&e.setAttribute("media",o),e.styleSheet)e.styleSheet.cssText=n;else{for(;e.firstChild;)e.removeChild(e.firstChild);e.appendChild(document.createTextNode(n))}}function p(e,t,n){var o=n.css,r=n.sourceMap,i=void 0===t.convertToAbsoluteUrls&&r;(t.convertToAbsoluteUrls||i)&&(o=_(o)),r&&(o+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(r))))+" */");var a=new Blob([o],{type:"text/css"}),s=e.href;e.href=URL.createObjectURL(a),s&&URL.revokeObjectURL(s)}var m={},v=function(e){var t;return function(){return void 0===t&&(t=e.apply(this,arguments)),t}}(function(){return window&&document&&document.all&&!window.atob}),h=function(e){var t={};return function(n){return void 0===t[n]&&(t[n]=e.call(this,n)),t[n]}}(function(e){return document.querySelector(e)}),g=null,y=0,b=[],_=n(12);e.exports=function(e,t){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");t=t||{},t.attrs="object"==typeof t.attrs?t.attrs:{},t.singleton||(t.singleton=v()),t.insertInto||(t.insertInto="head"),t.insertAt||(t.insertAt="bottom");var n=r(e,t);return o(n,t),function(e){for(var i=[],a=0;a
2 |
17 |
18 |
92 |
--------------------------------------------------------------------------------
/src/components/collapse.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
80 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import VmCollapse from './components/collapse.vue'
2 | import VmCollapseItem from './components/collapse-item.vue'
3 | import './styles/less/index.less'
4 |
5 | const install = function (Vue, opts = {}) {
6 | if (install.installed) return
7 | Vue.component(VmCollapse.name, VmCollapse)
8 | Vue.component(VmCollapseItem.name, VmCollapseItem)
9 | }
10 |
11 | if (typeof window !== 'undefined' && window.Vue) {
12 | install(window.Vue)
13 | }
14 |
15 | export {
16 | VmCollapse,
17 | VmCollapseItem
18 | }
19 |
20 | export default {
21 | install,
22 | VmCollapse,
23 | VmCollapseItem
24 | }
--------------------------------------------------------------------------------
/src/styles/less/base.less:
--------------------------------------------------------------------------------
1 | @css-prefix: ~"vm-";
2 |
3 | @collaspe-border-color: #dfe6ec;
4 | @collapse-border-radius: 0;
5 |
6 | @collapse-header-height: 43px;
7 | @collapse-header-fill: #fff;
8 | @collapse-header-color: #48576a;
9 | @collapse-header-size: 13px;
10 | @collapse-border-color: #dfe6ec;
11 |
12 | @collapse-content-fill: #fbfdff;
13 | @collapse-content-size: 13px;
14 | @collapse-content-color: #1f2d3d;
--------------------------------------------------------------------------------
/src/styles/less/collapse.less:
--------------------------------------------------------------------------------
1 | @collapse-css-prefix-cls: ~"@{css-prefix}collapse";
2 |
3 | .@{collapse-css-prefix-cls} {
4 | border-radius: @collapse-border-radius;
5 | &--bordered {
6 | border: 1px solid @collaspe-border-color;
7 | }
8 | &-item {
9 | &__header {
10 | height: @collapse-header-height;
11 | padding-left: 15px;
12 | font-size: @collapse-header-size;
13 | line-height: @collapse-header-height;
14 | color: @collapse-header-color;
15 | background-color: @collapse-header-fill;
16 | border-bottom: 1px solid @collapse-border-color;
17 | cursor: pointer;
18 |
19 | &__arrow {
20 | transition: transform .3s, top .3s;
21 | }
22 | }
23 | &__wrap {
24 | will-change: height;
25 | background-color: @collapse-content-fill;
26 | border-bottom: 1px solid @collapse-border-color;
27 | overflow: hidden;
28 | box-sizing: border-box;
29 | }
30 | &__content {
31 | padding: 10px 15px;
32 | font-size: @collapse-content-size;
33 | color: @collapse-content-color;
34 | line-height: 1.769230769230769;
35 | }
36 | &.is-active {
37 | > .vm-collapse-item__header {
38 | .vm-collapse-icon--arrow-right {
39 | top: 6px;
40 | transform: rotate(90deg);
41 | }
42 | }
43 | }
44 | &:last-child {
45 | margin-bottom: -1px;
46 | }
47 | }
48 | &-icon--arrow-right {
49 | position: relative;
50 | top: 2px;
51 | display: inline-block;
52 | width: 14px;
53 | height: 14px;
54 | transform: rotate(0deg);
55 | &:after {
56 | content: "";
57 | display: block;
58 | width: 0;
59 | height: 0;
60 | border: 7px solid transparent;
61 | border-left-color: #48576a;
62 | }
63 | }
64 | .collapse-transition {
65 | transition: 0.3s height ease-in-out, 0.3s padding-top ease-in-out, 0.3s padding-bottom ease-in-out;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/styles/less/index.less:
--------------------------------------------------------------------------------
1 | @import "base";
2 | @import "collapse";
--------------------------------------------------------------------------------
/src/transitions/collapse-transition.js:
--------------------------------------------------------------------------------
1 | import { addClass, removeClass } from '../utils/dom'
2 |
3 | class Transition {
4 | beforeEnter (el) {
5 | addClass(el, 'collapse-transition')
6 | if (!el.dataset) el.dataset = {}
7 |
8 | el.dataset.oldPaddingTop = el.style.paddingTop
9 | el.dataset.oldPaddingBottom = el.style.paddingBottom
10 |
11 | el.style.height = 0
12 | el.style.paddingTop = 0
13 | el.style.paddingBottom = 0
14 | }
15 |
16 | enter (el) {
17 | el.dataset.oldOverflow = el.style.overflow
18 | if (el.scrollHeight !== 0) {
19 | el.style.height = el.scrollHeight + 'px'
20 | el.style.paddingTop = el.dataset.oldPaddingTop
21 | el.style.paddingBottom = el.dataset.oldPaddingBottom
22 | } else {
23 | el.style.height = ''
24 | el.style.paddingTop = el.dataset.oldPaddingTop
25 | el.style.paddingBottom = el.dataset.oldPaddingBottom
26 | }
27 | el.style.overflow = 'hidden'
28 | }
29 |
30 | afterEnter (el) {
31 | removeClass(el, 'collapse-transition')
32 | el.style.height = ''
33 | el.style.overflow = el.dataset.oldOverflow
34 | }
35 |
36 | beforeLeave (el) {
37 | if (!el.dataset) el.dataset = {}
38 | el.dataset.oldPaddingTop = el.style.paddingTop
39 | el.dataset.oldPaddingBottom = el.style.paddingBottom
40 | el.dataset.oldOverflow = el.style.overflow
41 |
42 | el.style.height = el.scrollHeight + 'px'
43 | el.style.overflow = 'hidden'
44 | }
45 |
46 | leave (el) {
47 | if (el.scrollHeight !== 0) {
48 | addClass(el, 'collapse-transition')
49 | el.style.height = 0
50 | el.style.paddingTop = 0
51 | el.style.paddingBottom = 0
52 | }
53 | }
54 |
55 | afterLeave (el) {
56 | removeClass(el, 'collapse-transition')
57 | el.style.height = ''
58 | el.style.overflow = el.dataset.oldOverflow
59 | el.style.paddingTop = el.dataset.oldPaddingTop
60 | el.style.paddingBottom = el.dataset.oldPaddingBottom
61 | }
62 | }
63 |
64 | export default {
65 | name: 'VmCollapseTransition',
66 | functional: true,
67 | render (h, context) {
68 | const transition = new Transition()
69 | const data = {
70 | on: {
71 | 'before-enter': transition.beforeEnter,
72 | 'enter': transition.enter,
73 | 'after-enter': transition.afterEnter,
74 | 'before-leave': transition.beforeLeave,
75 | 'leave': transition.leave,
76 | 'after-leave': transition.afterLeave
77 | }
78 | }
79 |
80 | return h('transition', data, context.children)
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/utils/dom.js:
--------------------------------------------------------------------------------
1 | export function trim (string) { // BOM
2 | return (string || '').replace(/^[\s\uFEFF]+|[\s\uFEFF]+/g, '')
3 | }
4 |
5 | export function hasClass (el, cls) {
6 | if (!el || !cls) return false
7 | if (cls.indexOf(' ') !== -1) throw new Error('className should not contain space.')
8 | if (el.classList) {
9 | return el.classList.contains(cls)
10 | } else {
11 | return (' ' + el.className + ' ').indexOf(' ' + cls + ' ') > -1
12 | }
13 | }
14 |
15 | export function addClass (el, cls) {
16 | if (!el) return
17 | let curClass = el.className
18 | let classes = (cls || '').split(' ')
19 |
20 | for (let i = 0, len = classes.length; i < len; i++) {
21 | let clsName = classes[i]
22 | if (!clsName) continue
23 |
24 | if (el.classList) {
25 | el.classList.add(clsName)
26 | } else {
27 | if (!hasClass(el, clsName)) {
28 | curClass += ' ' + clsName
29 | }
30 | }
31 | }
32 | if (!el.classList) {
33 | el.className = curClass
34 | }
35 | }
36 |
37 | export function removeClass (el, cls) {
38 | if (!el || !cls) return
39 | let curClass = ' ' + el.className + ' '
40 | let classes = cls.split(' ')
41 |
42 | for (let i = 0, len = classes.length; i < len; i++) {
43 | let clsName = classes[i]
44 | if (!clsName) continue
45 |
46 | if (el.classList) {
47 | el.classList.remove(clsName)
48 | } else {
49 | if (hasClass(el, clsName)) {
50 | curClass = curClass.replace(' ' + clsName + ' ', ' ')
51 | }
52 | }
53 | }
54 | if (!el.classList) {
55 | el.className = trim(curClass)
56 | }
57 | }
58 |
--------------------------------------------------------------------------------