├── .babelrc ├── .editorconfig ├── .eslintignore ├── .gitignore ├── README.md ├── build ├── build.js ├── dev-client.js ├── dev-server.js ├── utils.js ├── webpack.base.conf.js ├── webpack.dev.conf.js └── webpack.prod.conf.js ├── config ├── dev.env.js ├── index.js ├── prod.env.js └── test.env.js ├── dist ├── demo9.html └── static │ ├── css │ └── app.43d3074f2a2bf1d13a1fab9b310ee3e6.css │ └── js │ ├── app.46feb1d466eb8dbaa36b.js │ ├── manifest.7f22f7d765f4e74a8c8a.js │ └── vendor.49ca22089a17a505695d.js ├── index.html ├── package.json ├── src ├── App.vue ├── assets │ └── logo.png ├── components │ └── vue-tab.vue └── main.js └── static └── .gitkeep /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-2"], 3 | "plugins": ["transform-runtime"], 4 | "comments": false 5 | } 6 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | build/*.js 2 | config/*.js 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | npm-debug.log 4 | selenium-debug.log 5 | test/unit/coverage 6 | test/e2e/reports 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-tab for Vue2.x 2 | ###a tab that can be silded to change pages and allow different height、verticle scroll 3 | > A project supports for Vue2.x . for Vue1.0 see the "vue-tab.vue1.0" file [deprecated] 4 | 5 | ## demo 6 | 7 | [live-demo](https://rawgit.com/bajian/vue-tab/master/dist/demo9.html) 8 | 9 | ## Build Setup 10 | 11 | ``` bash 12 | # install dependencies 13 | npm install 14 | 15 | # serve with hot reload at localhost:8080 16 | npm run dev 17 | 18 | # build for production with minification 19 | npm run build 20 | 21 | ``` 22 | 23 | ```html 24 | 25 | 27 | 28 |
29 |
hahaha1
30 | 31 |
hahaha1
32 |
hahaha1
33 | 34 |
35 |
36 | bajian2 37 |
38 |
39 | 40 | ``` 41 | 42 | ## Api 43 | ### Properties 44 | | Name | Type | Default | Description | 45 | |----------------------|-----------|--------------|--------------------------------------------------------------------| 46 | | tabtitles | `Array` | `[]` | vue data to set tab title. | 47 | | current-page | `Number` | `1` | set the current active page start from 1. | 48 | | slidable | `Boolean` | `true` | set false to disable silding to change a page. | 49 | | ==================== | ========= | ============ | =================== | 50 | 51 | >the length of tabtitles should match to the page number 52 | 53 | ### Events 54 | | Name | Parameters | Description | 55 | |--------------------|------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------| 56 | | tab-change-start | `pageNumber` | Fire in the beginning of animation to other slide (next or previous). | 57 | | tab-change-end | `pageNumber` | Will be fired after animation to other slide (next or previous). | 58 | | tab-revert-start | `pageNumber` | Fire in the beginning of animation to revert slide (no change). | 59 | | tab-revert-end | `pageNumber` | Will be fired after animation to revert slide (no change). | 60 | | ================== | ================ | ============================ | 61 | 62 | #### To set the page the same height (according to the biggest one) ,add the css: 63 | ``` 64 | .tabswiper-wrap> div{ height: initial !important;} 65 | ``` 66 | -------------------------------------------------------------------------------- /build/build.js: -------------------------------------------------------------------------------- 1 | // https://github.com/shelljs/shelljs 2 | require('shelljs/global') 3 | env.NODE_ENV = 'production' 4 | 5 | var path = require('path') 6 | var config = require('../config') 7 | var ora = require('ora') 8 | var webpack = require('webpack') 9 | var webpackConfig = require('./webpack.prod.conf') 10 | 11 | console.log( 12 | ' Tip:\n' + 13 | ' Built files are meant to be served over an HTTP server.\n' + 14 | ' Opening index.html over file:// won\'t work.\n' 15 | ) 16 | 17 | var spinner = ora('building for production...') 18 | spinner.start() 19 | 20 | var assetsPath = path.join(config.build.assetsRoot, config.build.assetsSubDirectory) 21 | rm('-rf', assetsPath) 22 | mkdir('-p', assetsPath) 23 | cp('-R', 'static/', assetsPath) 24 | 25 | webpack(webpackConfig, function (err, stats) { 26 | spinner.stop() 27 | if (err) throw err 28 | process.stdout.write(stats.toString({ 29 | colors: true, 30 | modules: false, 31 | children: false, 32 | chunks: false, 33 | chunkModules: false 34 | }) + '\n') 35 | }) 36 | -------------------------------------------------------------------------------- /build/dev-client.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | require('eventsource-polyfill') 3 | var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') 4 | 5 | hotClient.subscribe(function (event) { 6 | if (event.action === 'reload') { 7 | window.location.reload() 8 | } 9 | }) 10 | -------------------------------------------------------------------------------- /build/dev-server.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var express = require('express') 3 | var webpack = require('webpack') 4 | var config = require('../config') 5 | var proxyMiddleware = require('http-proxy-middleware') 6 | var webpackConfig = process.env.NODE_ENV === 'testing' 7 | ? require('./webpack.prod.conf') 8 | : require('./webpack.dev.conf') 9 | 10 | // default port where dev server listens for incoming traffic 11 | var port = process.env.PORT || config.dev.port 12 | // Define HTTP proxies to your custom API backend 13 | // https://github.com/chimurai/http-proxy-middleware 14 | var proxyTable = config.dev.proxyTable 15 | 16 | var app = express() 17 | var compiler = webpack(webpackConfig) 18 | 19 | var devMiddleware = require('webpack-dev-middleware')(compiler, { 20 | publicPath: webpackConfig.output.publicPath, 21 | stats: { 22 | colors: true, 23 | chunks: false 24 | } 25 | }) 26 | 27 | var hotMiddleware = require('webpack-hot-middleware')(compiler) 28 | // force page reload when html-webpack-plugin template changes 29 | compiler.plugin('compilation', function (compilation) { 30 | compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) { 31 | hotMiddleware.publish({ action: 'reload' }) 32 | cb() 33 | }) 34 | }) 35 | 36 | // proxy api requests 37 | Object.keys(proxyTable).forEach(function (context) { 38 | var options = proxyTable[context] 39 | if (typeof options === 'string') { 40 | options = { target: options } 41 | } 42 | app.use(proxyMiddleware(context, options)) 43 | }) 44 | 45 | // handle fallback for HTML5 history API 46 | app.use(require('connect-history-api-fallback')()) 47 | 48 | // serve webpack bundle output 49 | app.use(devMiddleware) 50 | 51 | // enable hot-reload and state-preserving 52 | // compilation error display 53 | app.use(hotMiddleware) 54 | 55 | // serve pure static assets 56 | var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory) 57 | app.use(staticPath, express.static('./static')) 58 | 59 | module.exports = app.listen(port, function (err) { 60 | if (err) { 61 | console.log(err) 62 | return 63 | } 64 | console.log('Listening at http://localhost:' + port + '\n') 65 | }) 66 | -------------------------------------------------------------------------------- /build/utils.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config') 3 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 4 | 5 | exports.assetsPath = function (_path) { 6 | var assetsSubDirectory = process.env.NODE_ENV === 'production' 7 | ? config.build.assetsSubDirectory 8 | : config.dev.assetsSubDirectory 9 | return path.posix.join(assetsSubDirectory, _path) 10 | } 11 | 12 | exports.cssLoaders = function (options) { 13 | options = options || {} 14 | // generate loader string to be used with extract text plugin 15 | function generateLoaders (loaders) { 16 | var sourceLoader = loaders.map(function (loader) { 17 | var extraParamChar 18 | if (/\?/.test(loader)) { 19 | loader = loader.replace(/\?/, '-loader?') 20 | extraParamChar = '&' 21 | } else { 22 | loader = loader + '-loader' 23 | extraParamChar = '?' 24 | } 25 | return loader + (options.sourceMap ? extraParamChar + 'sourceMap' : '') 26 | }).join('!') 27 | 28 | if (options.extract) { 29 | return ExtractTextPlugin.extract('vue-style-loader', sourceLoader) 30 | } else { 31 | return ['vue-style-loader', sourceLoader].join('!') 32 | } 33 | } 34 | 35 | // http://vuejs.github.io/vue-loader/configurations/extract-css.html 36 | return { 37 | css: generateLoaders(['css']), 38 | postcss: generateLoaders(['css']), 39 | less: generateLoaders(['css', 'less']), 40 | sass: generateLoaders(['css', 'sass?indentedSyntax']), 41 | scss: generateLoaders(['css', 'sass']), 42 | stylus: generateLoaders(['css', 'stylus']), 43 | styl: generateLoaders(['css', 'stylus']) 44 | } 45 | } 46 | 47 | // Generate loaders for standalone style files (outside of .vue) 48 | exports.styleLoaders = function (options) { 49 | var output = [] 50 | var loaders = exports.cssLoaders(options) 51 | for (var extension in loaders) { 52 | var loader = loaders[extension] 53 | output.push({ 54 | test: new RegExp('\\.' + extension + '$'), 55 | loader: loader 56 | }) 57 | } 58 | return output 59 | } 60 | -------------------------------------------------------------------------------- /build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config') 3 | var utils = require('./utils') 4 | var projectRoot = path.resolve(__dirname, '../') 5 | 6 | module.exports = { 7 | entry: { 8 | app: './src/main.js' 9 | }, 10 | output: { 11 | path: config.build.assetsRoot, 12 | publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath, 13 | filename: '[name].js' 14 | }, 15 | resolve: { 16 | extensions: ['', '.js', '.vue'], 17 | fallback: [path.join(__dirname, '../node_modules')], 18 | alias: { 19 | 'src': path.resolve(__dirname, '../src'), 20 | 'assets': path.resolve(__dirname, '../src/assets'), 21 | 'components': path.resolve(__dirname, '../src/components') 22 | } 23 | }, 24 | resolveLoader: { 25 | fallback: [path.join(__dirname, '../node_modules')] 26 | }, 27 | module: { 28 | loaders: [ 29 | { 30 | test: /\.vue$/, 31 | loader: 'vue' 32 | }, 33 | { 34 | test: /\.js$/, 35 | loader: 'babel', 36 | include: projectRoot, 37 | exclude: /node_modules/ 38 | }, 39 | { 40 | test: /\.json$/, 41 | loader: 'json' 42 | }, 43 | { 44 | test: /\.html$/, 45 | loader: 'vue-html' 46 | }, 47 | { 48 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 49 | loader: 'url', 50 | query: { 51 | limit: 10000, 52 | name: utils.assetsPath('img/[name].[hash:7].[ext]') 53 | } 54 | }, 55 | { 56 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 57 | loader: 'url', 58 | query: { 59 | limit: 10000, 60 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]') 61 | } 62 | } 63 | ] 64 | }, 65 | vue: { 66 | loaders: utils.cssLoaders() 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /build/webpack.dev.conf.js: -------------------------------------------------------------------------------- 1 | var config = require('../config') 2 | var webpack = require('webpack') 3 | var merge = require('webpack-merge') 4 | var utils = require('./utils') 5 | var baseWebpackConfig = require('./webpack.base.conf') 6 | var HtmlWebpackPlugin = require('html-webpack-plugin') 7 | 8 | // add hot-reload related code to entry chunks 9 | Object.keys(baseWebpackConfig.entry).forEach(function (name) { 10 | baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) 11 | }) 12 | 13 | module.exports = merge(baseWebpackConfig, { 14 | module: { 15 | loaders: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) 16 | }, 17 | // eval-source-map is faster for development 18 | devtool: '#eval-source-map', 19 | plugins: [ 20 | new webpack.DefinePlugin({ 21 | 'process.env': config.dev.env 22 | }), 23 | // https://github.com/glenjamin/webpack-hot-middleware#installation--usage 24 | new webpack.optimize.OccurenceOrderPlugin(), 25 | new webpack.HotModuleReplacementPlugin(), 26 | new webpack.NoErrorsPlugin(), 27 | // https://github.com/ampedandwired/html-webpack-plugin 28 | new HtmlWebpackPlugin({ 29 | filename: 'index.html', 30 | template: 'index.html', 31 | inject: true 32 | }) 33 | ] 34 | }) 35 | -------------------------------------------------------------------------------- /build/webpack.prod.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config') 3 | var utils = require('./utils') 4 | var webpack = require('webpack') 5 | var merge = require('webpack-merge') 6 | var baseWebpackConfig = require('./webpack.base.conf') 7 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 8 | var HtmlWebpackPlugin = require('html-webpack-plugin') 9 | var env = process.env.NODE_ENV === 'testing' 10 | ? require('../config/test.env') 11 | : config.build.env 12 | 13 | var webpackConfig = merge(baseWebpackConfig, { 14 | module: { 15 | loaders: utils.styleLoaders({ sourceMap: config.build.productionSourceMap, extract: true }) 16 | }, 17 | devtool: config.build.productionSourceMap ? '#source-map' : false, 18 | output: { 19 | path: config.build.assetsRoot, 20 | filename: utils.assetsPath('js/[name].[chunkhash].js'), 21 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') 22 | }, 23 | vue: { 24 | loaders: utils.cssLoaders({ 25 | sourceMap: config.build.productionSourceMap, 26 | extract: true 27 | }) 28 | }, 29 | plugins: [ 30 | // http://vuejs.github.io/vue-loader/workflow/production.html 31 | new webpack.DefinePlugin({ 32 | 'process.env': env 33 | }), 34 | new webpack.optimize.UglifyJsPlugin({ 35 | compress: { 36 | warnings: false 37 | } 38 | }), 39 | new webpack.optimize.OccurenceOrderPlugin(), 40 | // extract css into its own file 41 | new ExtractTextPlugin(utils.assetsPath('css/[name].[contenthash].css')), 42 | // generate dist index.html with correct asset hash for caching. 43 | // you can customize output by editing /index.html 44 | // see https://github.com/ampedandwired/html-webpack-plugin 45 | new HtmlWebpackPlugin({ 46 | filename: process.env.NODE_ENV === 'testing' 47 | ? 'index.html' 48 | : config.build.index, 49 | template: 'index.html', 50 | inject: true, 51 | minify: { 52 | removeComments: true, 53 | collapseWhitespace: true, 54 | removeAttributeQuotes: true 55 | // more options: 56 | // https://github.com/kangax/html-minifier#options-quick-reference 57 | }, 58 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin 59 | chunksSortMode: 'dependency' 60 | }), 61 | // split vendor js into its own file 62 | new webpack.optimize.CommonsChunkPlugin({ 63 | name: 'vendor', 64 | minChunks: function (module, count) { 65 | // any required modules inside node_modules are extracted to vendor 66 | return ( 67 | module.resource && 68 | /\.js$/.test(module.resource) && 69 | module.resource.indexOf( 70 | path.join(__dirname, '../node_modules') 71 | ) === 0 72 | ) 73 | } 74 | }), 75 | // extract webpack runtime and module manifest to its own file in order to 76 | // prevent vendor hash from being updated whenever app bundle is updated 77 | new webpack.optimize.CommonsChunkPlugin({ 78 | name: 'manifest', 79 | chunks: ['vendor'] 80 | }) 81 | ] 82 | }) 83 | 84 | if (config.build.productionGzip) { 85 | var CompressionWebpackPlugin = require('compression-webpack-plugin') 86 | 87 | webpackConfig.plugins.push( 88 | new CompressionWebpackPlugin({ 89 | asset: '[path].gz[query]', 90 | algorithm: 'gzip', 91 | test: new RegExp( 92 | '\\.(' + 93 | config.build.productionGzipExtensions.join('|') + 94 | ')$' 95 | ), 96 | threshold: 10240, 97 | minRatio: 0.8 98 | }) 99 | ) 100 | } 101 | 102 | module.exports = webpackConfig 103 | -------------------------------------------------------------------------------- /config/dev.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var prodEnv = require('./prod.env') 3 | 4 | module.exports = merge(prodEnv, { 5 | NODE_ENV: '"development"' 6 | }) 7 | -------------------------------------------------------------------------------- /config/index.js: -------------------------------------------------------------------------------- 1 | // see http://vuejs-templates.github.io/webpack for documentation. 2 | var path = require('path') 3 | 4 | module.exports = { 5 | build: { 6 | env: require('./prod.env'), 7 | index: path.resolve(__dirname, '../dist/index.html'), 8 | assetsRoot: path.resolve(__dirname, '../dist'), 9 | assetsSubDirectory: 'static', 10 | assetsPublicPath: '/', 11 | productionSourceMap: true, 12 | // Gzip off by default as many popular static hosts such as 13 | // Surge or Netlify already gzip all static assets for you. 14 | // Before setting to `true`, make sure to: 15 | // npm install --save-dev compression-webpack-plugin 16 | productionGzip: false, 17 | productionGzipExtensions: ['js', 'css'] 18 | }, 19 | dev: { 20 | env: require('./dev.env'), 21 | port: 8080, 22 | assetsSubDirectory: 'static', 23 | assetsPublicPath: '/', 24 | proxyTable: {}, 25 | // CSS Sourcemaps off by default because relative paths are "buggy" 26 | // with this option, according to the CSS-Loader README 27 | // (https://github.com/webpack/css-loader#sourcemaps) 28 | // In our experience, they generally work as expected, 29 | // just be aware of this issue when enabling this option. 30 | cssSourceMap: false 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /config/prod.env.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | NODE_ENV: '"production"' 3 | } 4 | -------------------------------------------------------------------------------- /config/test.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var devEnv = require('./dev.env') 3 | 4 | module.exports = merge(devEnv, { 5 | NODE_ENV: '"testing"' 6 | }) 7 | -------------------------------------------------------------------------------- /dist/demo9.html: -------------------------------------------------------------------------------- 1 | vue-tab -------------------------------------------------------------------------------- /dist/static/css/app.43d3074f2a2bf1d13a1fab9b310ee3e6.css: -------------------------------------------------------------------------------- 1 | html{height:100%}*{margin:0;padding:0}body{display:flex;align-items:center;justify-content:center;height:100%}.tab-content-container{width:99%;height:200px;margin:0 auto}#app{color:#2c3e50;margin-top:50px;max-width:500px;width:100%;font-family:Source Sans Pro,Helvetica,sans-serif;text-align:center;margin:0 auto}.tab-container{width:100%}.invisible{visibility:hidden}.tabswiper{position:relative;overflow:hidden}.tabswiper-wrap{display:flex;display:inline-flex;width:100%;height:100%;transition:all .2s ease;flex-direction:row}.tabswiper-wrap.dragging{transition:none}.tabswiper-wrap>div{overflow-x:hidden;flex-shrink:0;width:100%;margin:0;padding:0}::-webkit-scrollbar{width:0}.tab-title-container{-webkit-tap-highlight-color:rgba(0,0,0,0);margin:0 auto;list-style:none;border-bottom:1px solid #ddd;display:-webkit-box;display:-o-box;display:-ms-flexbox;display:flex;flex-wrap:nowrap;align-items:center;justify-content:center;width:100%}.tab-title,.tab-title-container{position:relative;-moz-appearance:none;appearance:none;-webkit-user-select:none;outline:none;-webkit-appearance:none;text-decoration:none}.tab-title{height:35px;line-height:35px;text-align:center;cursor:pointer;outline-style:none;-webkit-box-flex:1;-ms-flex:1;flex:1}.tab-title.active,.tab-title:active{border-bottom:2px solid #36acf4;color:#36acf4} 2 | /*# sourceMappingURL=app.43d3074f2a2bf1d13a1fab9b310ee3e6.css.map*/ -------------------------------------------------------------------------------- /dist/static/js/app.46feb1d466eb8dbaa36b.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([1,0],[function(t,e,a){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}var n=a(3),s=i(n),r=a(6),c=i(r);new s.default({el:"app",render:function(t){return t(c.default)}})},function(t,e){},function(t,e){},,function(t,e,a){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=a(7),s=i(n);e.default={components:{tab:s.default},data:function(){return{tabtitles:["bajian","github","bajian","github"],tabtitles2:["bajian","github","bajian"]}}}},function(t,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a=0,i=1,n=2;e.default={props:{tabtitles:{type:Array,default:[]},curPage:{type:Number,default:1},slidable:{type:Boolean,default:!0}},watch:{curPage:function(){(void 0).currentPage=(void 0).curPage}},data:function(){return{lastPage:1,currentPage:this.curPage,translateX:0,startTranslateX:0,delta:0,deltaY:0,dragging:!1,startPos:null,startPosY:null,transitioning:!1,slideEls:[],invisible:!0,judge:a}},mounted:function(){this.$nextTick(function(){this._onTouchMove=this._onTouchMove.bind(this),this._onTouchEnd=this._onTouchEnd.bind(this),this.slideEls=this.$refs["tabswiper-wrap"].children,this.dragging=!0,this.setPage(this.currentPage);var t=this;setTimeout(function(){t.dragging=t.invisible=!1},100),window.onresize=function(){t.setPage(t.currentPage)}})},methods:{next:function(){var t=this.currentPage;t1?(t--,this.setPage(t)):this._revert()},setPage:function(t){this.lastPage=this.currentPage,this.currentPage=t,this.translateX=-[].reduce.call(this.slideEls,function(e,a,i){return i>t-2?e:e+a.clientWidth},0),this._onTransitionStart()},_onTouchStart:function(t){this.startPos=this._getTouchPos(t),this.startYPos=this._getTouchYPos(t),this.delta=0,this.startTranslateX=this.translateX,this.startTime=(new Date).getTime(),this.dragging=!0,document.addEventListener("touchmove",this._onTouchMove,!1),document.addEventListener("touchend",this._onTouchEnd,!1)},_onTouchMove:function(t){switch(this.delta=this._getTouchPos(t)-this.startPos,this.deltaY=Math.abs(this._getTouchYPos(t)-this.startYPos),console.log("test",this.judge),this.judge){case a:Math.abs(this.delta)/this.deltaY>1.5?(this.judge=i,t.preventDefault(),t.stopPropagation()):this.judge=n;break;case n:break;case i:t.preventDefault(),t.stopPropagation(),this.translateX=this.startTranslateX+this.delta}},_onTouchEnd:function(t){if(this.dragging=!1,this.judge==i){var e=(new Date).getTime()-this.startTime<1e3;this.delta<-100||e&&this.delta<-15&&this.deltaY/this.delta>-6?this.next():this.delta>100||e&&this.delta>15&&this.deltaY/this.delta<6?this.prev():this._revert()}this.judge=a,document.removeEventListener("touchmove",this._onTouchMove),document.removeEventListener("touchend",this._onTouchEnd)},_revert:function(){this.setPage(this.currentPage)},_getTouchPos:function(t){var e="pageX";return t.changedTouches?t.changedTouches[0][e]:t[e]},_getTouchYPos:function(t){var e="pageY";return t.changedTouches?t.changedTouches[0][e]:t[e]},_onTransitionStart:function(){this.transitioning=!0,this._isPageChanged()?this.$emit("tab-change-start",this.currentPage):this.$emit("tab-revert-start",this.currentPage)},_onTransitionEnd:function(t){t.stopPropagation(),"tabswiper-wrap"==t.target.className&&(this.transitioning=!1,this._isPageChanged()?this.$emit("tab-change-end",this.currentPage):this.$emit("tab-revert-end",this.currentPage))},_isPageChanged:function(){return this.lastPage!==this.currentPage}}}},function(t,e,a){var i,n;a(1),i=a(4);var s=a(8);n=i=i||{},"object"!=typeof i.default&&"function"!=typeof i.default||(n=i=i.default),"function"==typeof n&&(n=n.options),n.render=s.render,n.staticRenderFns=s.staticRenderFns,t.exports=i},function(t,e,a){var i,n;a(2),i=a(5);var s=a(9);n=i=i||{},"object"!=typeof i.default&&"function"!=typeof i.default||(n=i=i.default),"function"==typeof n&&(n=n.options),n.render=s.render,n.staticRenderFns=s.staticRenderFns,t.exports=i},function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{attrs:{id:"app"}},[a("tab",{attrs:{tabtitles:t.tabtitles,"current-page":3}},[a("div",{staticClass:"tab-content-container"},[a("button",{attrs:{onclick:"alert(2)"}},[t._v("click")]),t._v(" "),a("div",[t._v("hahaha1")]),t._v(" "),a("div",[t._v("hahaha1")]),t._v(" "),a("div",[t._v("hahaha1")]),t._v(" "),a("div",[t._v("hahaha1")]),t._v(" "),a("div",[t._v("hahaha1")]),t._v(" "),a("div",[t._v("hahaha1")]),t._v(" "),a("div",[t._v("hahaha1")]),t._v(" "),a("img",{attrs:{src:"http://i2.hdslb.com/bfs/archive/33a164cec9e4664675e928c5f0a2844788c077ad.jpg@320w_200h.webp"}}),t._v(" "),a("div",[t._v("hahaha1")]),t._v(" "),a("div",[t._v("hahaha1")]),t._v(" "),a("img",{attrs:{src:"http://i2.hdslb.com/bfs/archive/33a164cec9e4664675e928c5f0a2844788c077ad.jpg@320w_200h.webp"}})]),t._v(" "),a("div",{staticClass:"tab-content-container"},[t._v("\n bajian2\n ")]),t._v(" "),a("div",{staticClass:"tab-content-container"},[t._v("\n bajian3\n ")]),t._v(" "),a("div",{staticClass:"tab-content-container"},[t._v("\n bajian4\n ")])]),t._v(" "),a("br"),t._v(" "),a("br"),t._v(" "),a("div",[t._v("allow different height、verticle scroll")]),t._v(" "),a("b",[t._v("disable slide below:")]),t._v(" "),a("br"),t._v(" "),a("tab",{attrs:{tabtitles:t.tabtitles2,slidable:!1}},[a("div",{staticClass:"tab-content-container",staticStyle:{height:"200px","background-color":"green"}},[t._v("\n hahaha1\n "),a("img",{attrs:{src:"http://i2.hdslb.com/bfs/archive/33a164cec9e4664675e928c5f0a2844788c077ad.jpg@320w_200h.webp"}}),t._v(" "),a("div",[t._v("hahaha1")]),t._v(" "),a("div",[t._v("hahaha1")]),t._v(" "),a("img",{attrs:{src:"http://i2.hdslb.com/bfs/archive/33a164cec9e4664675e928c5f0a2844788c077ad.jpg@320w_200h.webp"}})]),t._v(" "),a("div",{staticClass:"tab-content-container",staticStyle:{height:"150px","background-color":"#999"}},[t._v("\n bajian2\n ")]),t._v(" "),a("div",{staticClass:"tab-content-container"},[t._v("\n bajian3\n ")])])],1)},staticRenderFns:[]}},function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"tab-container"},[a("ul",{staticClass:"tab-title-container"},t._l(t.tabtitles,function(e,i){return a("li",{key:i,staticClass:"tab-title",class:{active:i+1===t.currentPage},on:{click:function(e){t.setPage(i+1)}}},[t._v(t._s(e)+"\n ")])})),t._v(" "),t.slidable?a("div",{staticClass:"tabswiper",class:{invisible:t.invisible},on:{touchstart:t._onTouchStart}},[a("div",{ref:"tabswiper-wrap",staticClass:"tabswiper-wrap",class:{dragging:t.dragging},style:{transform:"translate3d("+t.translateX+"px,0, 0)"},on:{transitionend:t._onTransitionEnd}},[t._t("default")],2)]):a("div",{staticClass:"tabswiper",class:{invisible:t.invisible}},[a("div",{ref:"tabswiper-wrap",staticClass:"tabswiper-wrap",class:{dragging:t.dragging},style:{transform:"translate3d("+t.translateX+"px,0, 0)"},on:{transitionend:t._onTransitionEnd}},[t._t("default")],2)])])},staticRenderFns:[]}}]); 2 | //# sourceMappingURL=app.46feb1d466eb8dbaa36b.js.map -------------------------------------------------------------------------------- /dist/static/js/manifest.7f22f7d765f4e74a8c8a.js: -------------------------------------------------------------------------------- 1 | !function(e){function t(a){if(n[a])return n[a].exports;var r=n[a]={exports:{},id:a,loaded:!1};return e[a].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var a=window.webpackJsonp;window.webpackJsonp=function(o,c){for(var p,s,l=0,i=[];l-1)return t.splice(n,1)}}function a(t,e){return xn.call(t,e)}function s(t){return"string"==typeof t||"number"==typeof t}function c(t){var e=Object.create(null);return function(n){var r=e[n];return r||(e[n]=t(n))}}function u(t,e){function n(n){var r=arguments.length;return r?r>1?t.apply(e,arguments):t.call(e,n):t.call(e)}return n._length=t.length,n}function l(t,e){e=e||0;for(var n=t.length-e,r=new Array(n);n--;)r[n]=t[n+e];return r}function f(t,e){for(var n in e)t[n]=e[n];return t}function p(t){return null!==t&&"object"==typeof t}function d(t){return En.call(t)===Tn}function v(t){for(var e={},n=0;n1?l(n):n;for(var r=l(arguments,1),o=0,i=n.length;o=0&&hr[n].id>t.id;)n--;hr.splice(Math.max(n,_r)+1,0,t)}else hr.push(t);yr||(yr=!0,qn(kt))}}function St(t){wr.clear(),Et(t,wr)}function Et(t,e){var n,r,o=Array.isArray(t);if((o||p(t))&&Object.isExtensible(t)){if(t.__ob__){var i=t.__ob__.dep.id;if(e.has(i))return;e.add(i)}if(o)for(n=t.length;n--;)Et(t[n],e);else for(r=Object.keys(t),n=r.length;n--;)Et(t[r[n]],e)}}function Tt(t){t._watchers=[];var e=t.$options;e.props&&It(t,e.props),e.methods&&Pt(t,e.methods),e.data?jt(t):O(t._data={},!0),e.computed&&Dt(t,e.computed),e.watch&&Lt(t,e.watch)}function It(t,e){var n=t.$options.propsData||{},r=t.$options._propKeys=Object.keys(e),o=!t.$parent;tr.shouldConvert=o;for(var i=function(o){var i=r[o];S(t,i,B(i,e,n,t))},a=0;a-1:t.test(e)}function Zt(t,e){for(var n in t){var r=t[n];if(r){var o=Wt(r.componentOptions);o&&!e(o)&&(Qt(r),t[n]=null)}}}function Qt(t){t&&(t.componentInstance._inactive||At(t.componentInstance,"deactivated"),t.componentInstance.$destroy())}function Xt(t){var e={};e.get=function(){return Dn},Object.defineProperty(t,"config",e),t.util=or,t.set=E,t.delete=T,t.nextTick=qn,t.options=Object.create(null),Dn._assetTypes.forEach(function(e){t.options[e+"s"]=Object.create(null)}),t.options._base=t,f(t.options.components,Or),zt(t),qt(t),Kt(t),Jt(t)}function Yt(t){for(var e=t.data,n=t,r=t;r.componentInstance;)r=r.componentInstance._vnode,r.data&&(e=te(r.data,e));for(;n=n.parent;)n.data&&(e=te(e,n.data));return ee(e)}function te(t,e){return{staticClass:ne(t.staticClass,e.staticClass),class:t.class?[t.class,e.class]:e.class}}function ee(t){var e=t.class,n=t.staticClass;return n||e?ne(n,re(e)):""}function ne(t,e){return t?e?t+" "+e:t:e||""}function re(t){var e="";if(!t)return e;if("string"==typeof t)return t;if(Array.isArray(t)){for(var n,r=0,o=t.length;r-1?Vr[t]=e.constructor===window.HTMLUnknownElement||e.constructor===window.HTMLElement:Vr[t]=/HTMLUnknownElement/.test(e.toString())}function ae(t){if("string"==typeof t){if(t=document.querySelector(t),!t)return document.createElement("div")}return t}function se(t,e){var n=document.createElement(t);return"select"!==t?n:(e.data&&e.data.attrs&&"multiple"in e.data.attrs&&n.setAttribute("multiple","multiple"),n)}function ce(t,e){return document.createElementNS(Ur[t],e)}function ue(t){return document.createTextNode(t)}function le(t){return document.createComment(t)}function fe(t,e,n){t.insertBefore(e,n)}function pe(t,e){t.removeChild(e)}function de(t,e){t.appendChild(e)}function ve(t){return t.parentNode}function he(t){return t.nextSibling}function me(t){return t.tagName}function ye(t,e){t.textContent=e}function ge(t,e,n){t.setAttribute(e,n)}function _e(t,e){var n=t.data.ref;if(n){var r=t.context,o=t.componentInstance||t.elm,a=r.$refs;e?Array.isArray(a[n])?i(a[n],o):a[n]===o&&(a[n]=void 0):t.data.refInFor?Array.isArray(a[n])&&a[n].indexOf(o)<0?a[n].push(o):a[n]=[o]:a[n]=o}}function be(t){return null==t}function Ce(t){return null!=t}function we(t,e){return t.key===e.key&&t.tag===e.tag&&t.isComment===e.isComment&&!t.data==!e.data}function xe(t,e,n){var r,o,i={};for(r=e;r<=n;++r)o=t[r].key,Ce(o)&&(i[o]=r);return i}function Ae(t){function e(t){return new ir(O.tagName(t).toLowerCase(),{},[],void 0,t)}function n(t,e){function n(){0===--n.listeners&&r(t)}return n.listeners=e,n}function r(t){var e=O.parentNode(t);e&&O.removeChild(e,t)}function i(t,e,n,r,o){if(t.isRootInsert=!o,!a(t,e,n,r)){var i=t.data,s=t.children,c=t.tag;Ce(c)?(t.elm=t.ns?O.createElementNS(t.ns,c):O.createElement(c,t),v(t),f(t,s,e),Ce(i)&&d(t,e),l(n,t.elm,r)):t.isComment?(t.elm=O.createComment(t.text),l(n,t.elm,r)):(t.elm=O.createTextNode(t.text),l(n,t.elm,r))}}function a(t,e,n,r){var o=t.data;if(Ce(o)){var i=Ce(t.componentInstance)&&o.keepAlive;if(Ce(o=o.hook)&&Ce(o=o.init)&&o(t,!1,n,r),Ce(t.componentInstance))return c(t,e),i&&u(t,e,n,r),!0}}function c(t,e){t.data.pendingInsert&&e.push.apply(e,t.data.pendingInsert),t.elm=t.componentInstance.$el,p(t)?(d(t,e),v(t)):(_e(t),e.push(t))}function u(t,e,n,r){for(var o,i=t;i.componentInstance;)if(i=i.componentInstance._vnode,Ce(o=i.data)&&Ce(o=o.transition)){for(o=0;o<$.activate.length;++o)$.activate[o](qr,i);e.push(i);break}l(n,t.elm,r)}function l(t,e,n){t&&(n?O.insertBefore(t,e,n):O.appendChild(t,e))}function f(t,e,n){if(Array.isArray(e))for(var r=0;rp?(u=be(n[m+1])?null:n[m+1].elm,h(t,u,n,f,m,r)):f>m&&y(t,e,l,p)}function b(t,e,n,r){if(t!==e){if(e.isStatic&&t.isStatic&&e.key===t.key&&(e.isCloned||e.isOnce))return e.elm=t.elm,void(e.componentInstance=t.componentInstance);var o,i=e.data,a=Ce(i);a&&Ce(o=i.hook)&&Ce(o=o.prepatch)&&o(t,e);var s=e.elm=t.elm,c=t.children,u=e.children;if(a&&p(e)){for(o=0;o<$.update.length;++o)$.update[o](t,e);Ce(o=i.hook)&&Ce(o=o.update)&&o(t,e)}be(e.text)?Ce(c)&&Ce(u)?c!==u&&_(s,c,u,n,r):Ce(u)?(Ce(t.text)&&O.setTextContent(s,""),h(s,null,u,0,u.length-1,n)):Ce(c)?y(s,c,0,c.length-1):Ce(t.text)&&O.setTextContent(s,""):t.text!==e.text&&O.setTextContent(s,e.text),a&&Ce(o=i.hook)&&Ce(o=o.postpatch)&&o(t,e)}}function C(t,e,n){if(n&&t.parent)t.parent.data.pendingInsert=e;else for(var r=0;r-1?e.split(/\s+/).forEach(function(e){return t.classList.add(e)}):t.classList.add(e);else{var n=" "+t.getAttribute("class")+" ";n.indexOf(" "+e+" ")<0&&t.setAttribute("class",(n+e).trim())}}function qe(t,e){if(e&&e.trim())if(t.classList)e.indexOf(" ")>-1?e.split(/\s+/).forEach(function(e){return t.classList.remove(e)}):t.classList.remove(e);else{for(var n=" "+t.getAttribute("class")+" ",r=" "+e+" ";n.indexOf(r)>=0;)n=n.replace(r," ");t.setAttribute("class",n.trim())}}function Ke(t){ho(function(){ho(t)})}function Je(t,e){(t._transitionClasses||(t._transitionClasses=[])).push(e),ze(t,e)}function We(t,e){t._transitionClasses&&i(t._transitionClasses,e),qe(t,e)}function Ge(t,e,n){var r=Ze(t,e),o=r.type,i=r.timeout,a=r.propCount;if(!o)return n();var s=o===co?fo:vo,c=0,u=function(){t.removeEventListener(s,l),n()},l=function(e){e.target===t&&++c>=a&&u()};setTimeout(function(){c0&&(n=co,l=a,f=i.length):e===uo?u>0&&(n=uo,l=u,f=c.length):(l=Math.max(a,u),n=l>0?a>u?co:uo:null,f=n?n===co?i.length:c.length:0);var p=n===co&&mo.test(r[lo+"Property"]);return{type:n,timeout:l,propCount:f,hasTransform:p}}function Qe(t,e){for(;t.length1,j=n._enterCb=nn(function(){T&&(We(n,$),We(n,A)),j.cancelled?(T&&We(n,x),E&&E(n)):S&&S(n),n._enterCb=null});t.data.show||ot(t.data.hook||(t.data.hook={}),"insert",function(){var e=n.parentNode,r=e&&e._pending&&e._pending[t.key];r&&r.tag===t.tag&&r.elm._leaveCb&&r.elm._leaveCb(),O&&O(n,j)},"transition-insert"),k&&k(n),T&&(Je(n,x),Je(n,A),Ke(function(){Je(n,$),We(n,x),j.cancelled||I||Ge(n,i,j)})),t.data.show&&(e&&e(),O&&O(n,j)),T||I||j()}}}function tn(t,e){function n(){y.cancelled||(t.data.show||((r.parentNode._pending||(r.parentNode._pending={}))[t.key]=t),l&&l(r),h&&(Je(r,s),Je(r,u),Ke(function(){Je(r,c),We(r,s),y.cancelled||m||Ge(r,a,y)})),f&&f(r,y),h||m||y())}var r=t.elm;r._enterCb&&(r._enterCb.cancelled=!0,r._enterCb());var o=en(t.data.transition);if(!o)return e();if(!r._leaveCb&&1===r.nodeType){var i=o.css,a=o.type,s=o.leaveClass,c=o.leaveToClass,u=o.leaveActiveClass,l=o.beforeLeave,f=o.leave,p=o.afterLeave,d=o.leaveCancelled,v=o.delayLeave,h=i!==!1&&!Bn,m=f&&(f._length||f.length)>1,y=r._leaveCb=nn(function(){r.parentNode&&r.parentNode._pending&&(r.parentNode._pending[t.key]=null),h&&(We(r,c),We(r,u)),y.cancelled?(h&&We(r,s),d&&d(r)):(e(),p&&p(r)),r._leaveCb=null});v?v(n):n()}}function en(t){if(t){if("object"==typeof t){var e={};return t.css!==!1&&f(e,yo(t.name||"v")),f(e,t),e}return"string"==typeof t?yo(t):void 0}}function nn(t){var e=!1;return function(){e||(e=!0,t())}}function rn(t,e){e.data.show||Ye(e)}function on(t,e,n){var r=e.value,o=t.multiple;if(!o||Array.isArray(r)){for(var i,a,s=0,c=t.options.length;s-1,a.selected!==i&&(a.selected=i);else if(y(sn(a),r))return void(t.selectedIndex!==s&&(t.selectedIndex=s));o||(t.selectedIndex=-1)}}function an(t,e){for(var n=0,r=e.length;n0,Rn=Mn&&Mn.indexOf("edge/")>0,Hn=Mn&&Mn.indexOf("android")>0,Vn=Mn&&/iphone|ipad|ipod|ios/.test(Mn),Fn=function(){return void 0===bn&&(bn=!Ln&&"undefined"!=typeof e&&"server"===e.process.env.VUE_ENV),bn},zn=Ln&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__,qn=function(){function t(){r=!1;var t=n.slice(0);n.length=0;for(var e=0;e1&&(e[n[0].trim()]=n[1].trim())}}),e}),eo=/^--/,no=/\s*!important$/,ro=function(t,e,n){eo.test(e)?t.style.setProperty(e,n):no.test(n)?t.style.setProperty(e,n.replace(no,""),"important"):t.style[io(e)]=n},oo=["Webkit","Moz","ms"],io=c(function(t){if(Er=Er||document.createElement("div"),t=$n(t),"filter"!==t&&t in Er.style)return t;for(var e=t.charAt(0).toUpperCase()+t.slice(1),n=0;n=0&&y.splice(e,1)}function s(t){var e=document.createElement("style");return e.type="text/css",i(t,e),e}function c(t,e){var n,r,o;if(e.singleton){var i=m++;n=h||(h=s(e)),r=u.bind(null,n,i,!1),o=u.bind(null,n,i,!0)}else n=s(e),r=l.bind(null,n),o=function(){a(n)};return r(t),function(e){if(e){if(e.css===t.css&&e.media===t.media&&e.sourceMap===t.sourceMap)return;r(t=e)}else o()}}function u(t,e,n,r){var o=n?"":r.css;if(t.styleSheet)t.styleSheet.cssText=g(e,o);else{var i=document.createTextNode(o),a=t.childNodes;a[e]&&t.removeChild(a[e]),a.length?t.insertBefore(i,a[e]):t.appendChild(i)}}function l(t,e){var n=e.css,r=e.media,o=e.sourceMap;if(r&&t.setAttribute("media",r),o&&(n+="\n/*# sourceURL="+o.sources[0]+" */",n+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(o))))+" */"),t.styleSheet)t.styleSheet.cssText=n;else{for(;t.firstChild;)t.removeChild(t.firstChild);t.appendChild(document.createTextNode(n))}}var f={},p=function(t){var e;return function(){return"undefined"==typeof e&&(e=t.apply(this,arguments)),e}},d=p(function(){return/msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase())}),v=p(function(){return document.head||document.getElementsByTagName("head")[0]}),h=null,m=0,y=[];t.exports=function(t,e){e=e||{},"undefined"==typeof e.singleton&&(e.singleton=d()),"undefined"==typeof e.insertAt&&(e.insertAt="bottom");var n=o(t);return r(n,e),function(t){for(var i=[],a=0;a 2 | 3 | 4 | 5 | 6 | 7 | vue-tab 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-tab", 3 | "version": "1.0.0", 4 | "description": "A Vue.js project", 5 | "author": "bajian", 6 | "private": true, 7 | "scripts": { 8 | "dev": "node build/dev-server.js", 9 | "build": "node build/build.js", 10 | "test": "" 11 | }, 12 | "dependencies": { 13 | "vue": "^2.0.0", 14 | "babel-runtime": "^6.0.0" 15 | }, 16 | "devDependencies": { 17 | "babel-core": "^6.0.0", 18 | "babel-loader": "^6.0.0", 19 | "babel-plugin-transform-runtime": "^6.0.0", 20 | "babel-preset-es2015": "^6.0.0", 21 | "babel-preset-stage-2": "^6.0.0", 22 | "babel-register": "^6.0.0", 23 | "connect-history-api-fallback": "^1.1.0", 24 | "css-loader": "^0.23.0", 25 | "eventsource-polyfill": "^0.9.6", 26 | "express": "^4.13.3", 27 | "extract-text-webpack-plugin": "^1.0.1", 28 | "file-loader": "^0.8.4", 29 | "function-bind": "^1.0.2", 30 | "html-webpack-plugin": "^2.8.1", 31 | "http-proxy-middleware": "^0.12.0", 32 | "json-loader": "^0.5.4", 33 | "ora": "^0.2.0", 34 | "shelljs": "^0.6.0", 35 | "url-loader": "^0.5.7", 36 | "vue-hot-reload-api": "^1.2.0", 37 | "vue-html-loader": "^1.0.0", 38 | "vue-loader": "^9.0.0", 39 | "vue-style-loader": "^1.0.0", 40 | "webpack": "^1.12.2", 41 | "webpack-dev-middleware": "^1.4.0", 42 | "webpack-hot-middleware": "^2.6.0", 43 | "webpack-merge": "^0.8.3" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 57 | 58 | 73 | 74 | 118 | -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bajian/vue-tab/9f0d676798c8fd1a775d76779d97c19b48ffd4df/src/assets/logo.png -------------------------------------------------------------------------------- /src/components/vue-tab.vue: -------------------------------------------------------------------------------- 1 | 36 | 37 | 272 | 273 | 365 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App' 3 | 4 | /* eslint-disable no-new */ 5 | new Vue({ 6 | el: 'app', 7 | render: h => h(App) 8 | }) -------------------------------------------------------------------------------- /static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bajian/vue-tab/9f0d676798c8fd1a775d76779d97c19b48ffd4df/static/.gitkeep --------------------------------------------------------------------------------