├── .browserslistrc ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── LICENSE ├── README.md ├── babel.config.js ├── images └── 效果图.png ├── package-lock.json ├── package.json ├── public ├── favicon.ico └── index.html ├── src ├── App.vue ├── assets │ ├── images │ │ └── avatar.jpg │ └── logo.png ├── components │ ├── home │ │ └── TabBar.vue │ └── index │ │ ├── RightBar.vue │ │ ├── TopBar.vue │ │ ├── VideoInfo.vue │ │ ├── VideoList.vue │ │ └── Videos.vue ├── main.js ├── router │ └── index.js └── views │ ├── Home.vue │ ├── follow │ └── Index.vue │ └── index │ └── Index.vue └── vue.config.js /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{js,jsx,ts,tsx,vue}] 2 | indent_style = space 3 | indent_size = 2 4 | trim_trailing_whitespace = true 5 | insert_final_newline = true 6 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | build/*.js 2 | src/assets 3 | public 4 | dist 5 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true, 5 | browser: true, 6 | es6: true 7 | }, 8 | extends: [ 9 | 'plugin:vue/essential', 10 | '@vue/standard' 11 | ], 12 | parserOptions: { 13 | parser: 'babel-eslint', 14 | sourceType: 'module' 15 | }, 16 | // add your custom rules here 17 | //it is base on https://github.com/vuejs/eslint-config-vue 18 | rules: { 19 | 'vue/max-attributes-per-line': [2, { 20 | 'singleline': 10, 21 | 'multiline': { 22 | 'max': 1, 23 | 'allowFirstLine': false 24 | } 25 | }], 26 | 'vue/singleline-html-element-content-newline': 'off', 27 | 'vue/multiline-html-element-content-newline': 'off', 28 | 'vue/name-property-casing': ['error', 'PascalCase'], 29 | 'vue/no-v-html': 'off', 30 | 'accessor-pairs': 2, 31 | 'arrow-spacing': [2, { 32 | 'before': true, 33 | 'after': true 34 | }], 35 | 'block-spacing': [2, 'always'], 36 | 'brace-style': [2, '1tbs', { 37 | 'allowSingleLine': true 38 | }], 39 | 'camelcase': [0, { 40 | 'properties': 'always' 41 | }], 42 | 'comma-dangle': [2, 'never'], 43 | 'comma-spacing': [2, { 44 | 'before': false, 45 | 'after': true 46 | }], 47 | 'comma-style': [2, 'last'], 48 | 'constructor-super': 2, 49 | 'curly': [2, 'multi-line'], 50 | 'dot-location': [2, 'property'], 51 | 'eol-last': 2, 52 | 'eqeqeq': ['error', 'always', { 'null': 'ignore' }], 53 | 'generator-star-spacing': [2, { 54 | 'before': true, 55 | 'after': true 56 | }], 57 | 'handle-callback-err': [2, '^(err|error)$'], 58 | 'indent': [2, 2, { 59 | 'SwitchCase': 1 60 | }], 61 | 'jsx-quotes': [2, 'prefer-single'], 62 | 'key-spacing': [2, { 63 | 'beforeColon': false, 64 | 'afterColon': true 65 | }], 66 | 'keyword-spacing': [2, { 67 | 'before': true, 68 | 'after': true 69 | }], 70 | 'new-cap': [2, { 71 | 'newIsCap': true, 72 | 'capIsNew': false 73 | }], 74 | 'new-parens': 2, 75 | 'no-array-constructor': 2, 76 | 'no-caller': 2, 77 | 'no-console': 'off', 78 | 'no-class-assign': 2, 79 | 'no-cond-assign': 2, 80 | 'no-const-assign': 2, 81 | 'no-control-regex': 0, 82 | 'no-delete-var': 2, 83 | 'no-dupe-args': 2, 84 | 'no-dupe-class-members': 2, 85 | 'no-dupe-keys': 2, 86 | 'no-duplicate-case': 2, 87 | 'no-empty-character-class': 2, 88 | 'no-empty-pattern': 2, 89 | 'no-eval': 2, 90 | 'no-ex-assign': 2, 91 | 'no-extend-native': 2, 92 | 'no-extra-bind': 2, 93 | 'no-extra-boolean-cast': 2, 94 | 'no-extra-parens': [2, 'functions'], 95 | 'no-fallthrough': 2, 96 | 'no-floating-decimal': 2, 97 | 'no-func-assign': 2, 98 | 'no-implied-eval': 2, 99 | 'no-inner-declarations': [2, 'functions'], 100 | 'no-invalid-regexp': 2, 101 | 'no-irregular-whitespace': 2, 102 | 'no-iterator': 2, 103 | 'no-label-var': 2, 104 | 'no-labels': [2, { 105 | 'allowLoop': false, 106 | 'allowSwitch': false 107 | }], 108 | 'no-lone-blocks': 2, 109 | 'no-mixed-spaces-and-tabs': 2, 110 | 'no-multi-spaces': 2, 111 | 'no-multi-str': 2, 112 | 'no-multiple-empty-lines': [2, { 113 | 'max': 1 114 | }], 115 | 'no-native-reassign': 2, 116 | 'no-negated-in-lhs': 2, 117 | 'no-new-object': 2, 118 | 'no-new-require': 2, 119 | 'no-new-symbol': 2, 120 | 'no-new-wrappers': 2, 121 | 'no-obj-calls': 2, 122 | 'no-octal': 2, 123 | 'no-octal-escape': 2, 124 | 'no-path-concat': 2, 125 | 'no-proto': 2, 126 | 'no-redeclare': 2, 127 | 'no-regex-spaces': 2, 128 | 'no-return-assign': [2, 'except-parens'], 129 | 'no-self-assign': 2, 130 | 'no-self-compare': 2, 131 | 'no-sequences': 2, 132 | 'no-shadow-restricted-names': 2, 133 | 'no-spaced-func': 2, 134 | 'no-sparse-arrays': 2, 135 | 'no-this-before-super': 2, 136 | 'no-throw-literal': 2, 137 | 'no-trailing-spaces': 2, 138 | 'no-undef': 2, 139 | 'no-undef-init': 2, 140 | 'no-unexpected-multiline': 2, 141 | 'no-unmodified-loop-condition': 2, 142 | 'no-unneeded-ternary': [2, { 143 | 'defaultAssignment': false 144 | }], 145 | 'no-unreachable': 2, 146 | 'no-unsafe-finally': 2, 147 | 'no-unused-vars': [2, { 148 | 'vars': 'all', 149 | 'args': 'none' 150 | }], 151 | 'no-useless-call': 2, 152 | 'no-useless-computed-key': 2, 153 | 'no-useless-constructor': 2, 154 | 'no-useless-escape': 0, 155 | 'no-whitespace-before-property': 2, 156 | 'no-with': 2, 157 | 'one-var': [2, { 158 | 'initialized': 'never' 159 | }], 160 | 'operator-linebreak': [2, 'after', { 161 | 'overrides': { 162 | '?': 'before', 163 | ':': 'before' 164 | } 165 | }], 166 | 'padded-blocks': [2, 'never'], 167 | 'quotes': [2, 'single', { 168 | 'avoidEscape': true, 169 | 'allowTemplateLiterals': true 170 | }], 171 | 'semi': [2, 'never'], 172 | 'semi-spacing': [2, { 173 | 'before': false, 174 | 'after': true 175 | }], 176 | 'space-before-blocks': [2, 'always'], 177 | 'space-before-function-paren': [2, 'never'], 178 | 'space-in-parens': [2, 'never'], 179 | 'space-infix-ops': 2, 180 | 'space-unary-ops': [2, { 181 | 'words': true, 182 | 'nonwords': false 183 | }], 184 | 'spaced-comment': [2, 'always', { 185 | 'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ','] 186 | }], 187 | 'template-curly-spacing': [2, 'never'], 188 | 'use-isnan': 2, 189 | 'valid-typeof': 2, 190 | 'wrap-iife': [2, 'any'], 191 | 'yield-star-spacing': [2, 'both'], 192 | 'yoda': [2, 'never'], 193 | 'prefer-const': 2, 194 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, 195 | 'object-curly-spacing': [2, 'always', { 196 | objectsInObjects: false 197 | }], 198 | 'array-bracket-spacing': [2, 'never'] 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw? 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 二两 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 | # Vue 模仿抖音首页的视频播放效果 2 | 3 | ## 概述 4 | - 使用 @vue/cli 4.2.3 搭建的脚手架 5 | - 视频播放使用插件 [vue-video-player](https://github.com/surmon-china/vue-video-player) 6 | - [vue-awesome-swiper](https://github.com/surmon-china/vue-awesome-swiper) 做视频上下滑动 7 | 8 | ## 效果 9 | 10 | 上下滑动自动播放和暂停 11 | 12 | ![](./images/效果图.png) 13 | 14 | ## Project setup 15 | ``` 16 | npm install 17 | ``` 18 | 19 | ### Compiles and hot-reloads for development 20 | ``` 21 | npm run serve 22 | ``` 23 | 24 | ### Compiles and minifies for production 25 | ``` 26 | npm run build 27 | ``` 28 | 29 | ### Lints and fixes files 30 | ``` 31 | npm run lint 32 | ``` 33 | 34 | ### Customize configuration 35 | See [Configuration Reference](https://cli.vuejs.org/config/). 36 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /images/效果图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DouyinCommunity/vue_douyin/db02357488235956726dae157a7201fa4f7efb4d/images/效果图.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue_douyin", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "core-js": "^3.6.4", 12 | "swiper": "^5.3.6", 13 | "vue": "^2.6.11", 14 | "vue-awesome-swiper": "^4.0.2", 15 | "vue-router": "^3.1.5", 16 | "vue-video-player": "^5.0.2" 17 | }, 18 | "devDependencies": { 19 | "@vue/cli-plugin-babel": "~4.2.0", 20 | "@vue/cli-plugin-eslint": "~4.2.0", 21 | "@vue/cli-plugin-router": "^4.2.3", 22 | "@vue/cli-service": "~4.2.0", 23 | "@vue/eslint-config-standard": "^5.1.0", 24 | "babel-eslint": "^10.0.3", 25 | "eslint": "^6.7.2", 26 | "eslint-plugin-import": "^2.20.1", 27 | "eslint-plugin-node": "^11.0.0", 28 | "eslint-plugin-promise": "^4.2.1", 29 | "eslint-plugin-standard": "^4.0.0", 30 | "eslint-plugin-vue": "^6.1.2", 31 | "vue-template-compiler": "^2.6.11" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DouyinCommunity/vue_douyin/db02357488235956726dae157a7201fa4f7efb4d/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 17 | -------------------------------------------------------------------------------- /src/assets/images/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DouyinCommunity/vue_douyin/db02357488235956726dae157a7201fa4f7efb4d/src/assets/images/avatar.jpg -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DouyinCommunity/vue_douyin/db02357488235956726dae157a7201fa4f7efb4d/src/assets/logo.png -------------------------------------------------------------------------------- /src/components/home/TabBar.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 39 | 40 | 89 | -------------------------------------------------------------------------------- /src/components/index/RightBar.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 34 | 35 | 126 | -------------------------------------------------------------------------------- /src/components/index/TopBar.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 33 | 34 | 75 | -------------------------------------------------------------------------------- /src/components/index/VideoInfo.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 19 | 20 | 64 | -------------------------------------------------------------------------------- /src/components/index/VideoList.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 96 | 97 | 103 | -------------------------------------------------------------------------------- /src/components/index/Videos.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 70 | 71 | 93 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import router from './router' 4 | import VueAwesomeSwiper from 'vue-awesome-swiper' 5 | import VideoPlayer from 'vue-video-player' 6 | 7 | // import style 8 | import 'swiper/css/swiper.css' 9 | import 'video.js/dist/video-js.css' 10 | import 'vue-video-player/src/custom-theme.css' 11 | 12 | Vue.config.productionTip = false 13 | 14 | Vue.use(VueAwesomeSwiper) 15 | Vue.use(VideoPlayer) 16 | 17 | new Vue({ 18 | router, 19 | render: h => h(App) 20 | }).$mount('#app') 21 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueRouter from 'vue-router' 3 | import Home from '@/views/Home.vue' 4 | import Index from '@/views/index/Index' 5 | import Follow from '@/views/follow/Index' 6 | import VideoList from '@/components/index/VideoList' 7 | 8 | Vue.use(VueRouter) 9 | 10 | const routes = [ 11 | { 12 | path: '/', 13 | redirect: '/index' 14 | }, 15 | { 16 | path: '/', 17 | name: 'Home', 18 | component: Home, 19 | children: [ 20 | { 21 | path: 'index', 22 | name: 'Index', 23 | component: Index, 24 | children: [ 25 | { 26 | path: '/', 27 | name: 'VideoList', 28 | component: VideoList 29 | } 30 | ] 31 | }, 32 | { 33 | path: 'follow', 34 | name: 'Follow', 35 | component: Follow 36 | } 37 | ] 38 | } 39 | ] 40 | 41 | const router = new VueRouter({ 42 | routes 43 | }) 44 | 45 | export default router 46 | -------------------------------------------------------------------------------- /src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 17 | 18 | 20 | -------------------------------------------------------------------------------- /src/views/follow/Index.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 16 | -------------------------------------------------------------------------------- /src/views/index/Index.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 19 | 20 | 23 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | 4 | function resolve(dir) { 5 | return path.join(__dirname, dir) 6 | } 7 | 8 | module.exports = { 9 | chainWebpack: config => { 10 | config.resolve.alias 11 | .set('@', resolve('src')) 12 | } 13 | } 14 | --------------------------------------------------------------------------------