From 42ea888543445bc796897bcb83317231e3269d43 Mon Sep 17 00:00:00 2001 From: pdsuwwz Date: Sat, 1 Jan 2022 16:14:33 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=8C=88=20feat:=20upgrade=20to=20Vue=203?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 118 +- babel.config.js | 5 +- build/utils.js | 7 + build/webpack.config.js | 81 +- build/webpack.example.js | 126 +- example/App.vue | 18 +- example/main.js | 17 +- example/router.js | 19 +- example/src/assets/logo.svg | 23 + example/src/components/Layout.vue | 30 +- example/src/styles/variables.scss | 14 + example/src/views/ExampleAffix.vue | 71 +- jsconfig.json | 12 + package.json | 98 +- pnpm-lock.yaml | 5548 +++++++++++++++++ src/components/ScrollAffix/index.vue | 155 +- src/main.js | 6 +- yarn.lock | 8282 -------------------------- 18 files changed, 5969 insertions(+), 8661 deletions(-) create mode 100644 build/utils.js create mode 100644 example/src/assets/logo.svg create mode 100644 example/src/styles/variables.scss create mode 100644 jsconfig.json create mode 100644 pnpm-lock.yaml delete mode 100644 yarn.lock diff --git a/README.md b/README.md index 6315863..1d07934 100644 --- a/README.md +++ b/README.md @@ -2,34 +2,49 @@ ![npm](https://img.shields.io/npm/v/@hoc-element/affix) ![NPM](https://img.shields.io/npm/l/@hoc-element/affix) -📌 将页面元素固定在可视范围内。 +📌 基于 Webpack 5 构建的 Vue 3.x 固钉组件,用于将页面元素固定在可视范围内。 **Live demo:** https://pdsuwwz.github.io/hoc-element-affix + +## Version + +* Vue 3.x 版本 | [Vue 2.x 版本](https://github.com/pdsuwwz/hoc-element-affix/tree/vue2.0) + + + ## Environment Support -* Vue 2.6.0+ +* Vue 3.2.x ## Install ```shell npm install @hoc-element/affix + +# or + +pnpm add @hoc-element/affix ``` ## Quick Start ```js -import Vue from 'vue' +import { createApp } from 'vue' import HocElementAffix from '@hoc-element/affix' +import App from './App.vue' -Vue.use(HocElementAffix) +createApp(App) + .use(HocElementAffix) + .mount('#app') ``` ## Feature -- [x] 自定义顶部偏移量 -- [x] 固定状态改变时触发的回调 -- [x] 插槽式的固定状态反馈 +- [x] 支持 Vue 3.x +- [x] 支持自定义顶部 `offsetTop` 偏移量 +- [x] 支持固定状态改变触发回调 +- [x] 支持 `Slot` 插槽式的固定状态反馈 ## Using @@ -56,92 +71,5 @@ Vue.use(HocElementAffix) ## Demo -下面是比较全的例子,几乎囊括了 API 的所有用法,源码戳这: [Code](https://github.com/pdsuwwz/hoc-element-affix/tree/master/example/src/views/ExampleAffix.vue ) - -```html - - - - - -``` +下面是比较全的例子,几乎囊括了 API 的所有用法,源码戳这: [Code](https://github.com/pdsuwwz/hoc-element-affix/tree/main/example/src/views/ExampleAffix.vue ) diff --git a/babel.config.js b/babel.config.js index a7a0eb8..c020093 100644 --- a/babel.config.js +++ b/babel.config.js @@ -5,7 +5,7 @@ const babelConfig = { { targets: { chrome: '58', - ie: '6' + ie: '11' } } ] @@ -22,7 +22,8 @@ const babelConfig = { ], '@babel/plugin-syntax-dynamic-import', '@babel/plugin-syntax-import-meta', - ['@babel/plugin-proposal-class-properties', { loose: true }], + ['@babel/plugin-proposal-class-properties', { loose: false }], + ['@babel/plugin-proposal-private-methods', { loose: false }], '@babel/plugin-proposal-json-strings', [ '@babel/plugin-proposal-decorators', diff --git a/build/utils.js b/build/utils.js new file mode 100644 index 0000000..612d40d --- /dev/null +++ b/build/utils.js @@ -0,0 +1,7 @@ +const path = require('path') + +module.exports = { + resolve (dir = '') { + return path.join(process.cwd(), dir) + } +} diff --git a/build/webpack.config.js b/build/webpack.config.js index 42282e3..acb458b 100644 --- a/build/webpack.config.js +++ b/build/webpack.config.js @@ -1,13 +1,8 @@ const path = require('path') const webpack = require('webpack') const { VueLoaderPlugin } = require('vue-loader') -const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin') -const notifier = require('node-notifier') - -function resolve (dir) { - return path.join(process.cwd(), dir) -} +const { resolve } = require('./utils') module.exports = { mode: 'production', entry: './src/main.js', @@ -17,21 +12,9 @@ module.exports = { filename: 'hoc-el-affix.js', libraryTarget: 'umd' }, + stats: 'minimal', module: { rules: [ - { - enforce: 'pre', - test: /\.(vue|js)(\?.*)?$/, - loader: 'eslint-loader', - include: resolve('src'), - options: { - fix: true, - failOnError: true, - useEslintrc: true, - configFile: resolve('.eslintrc.js'), - formatter: require('eslint-friendly-formatter') - } - }, { test: /\.css$/, use: [ @@ -61,7 +44,7 @@ module.exports = { loader: 'vue-loader' }, exclude: /node_modules/, - include: resolve('src') + include: resolve('./src') }, { test: /\.js$/, @@ -69,13 +52,42 @@ module.exports = { use: { loader: 'babel-loader', options: { - extends: resolve('babel.config.js') + extends: resolve('./babel.config.js') } } }, { - test: /\.(png|jpg|gif|svg)$/, + test: /\.(png|jpe?g|gif|svg|webp)(\?.*)?$/, + loader: 'url-loader', + exclude: /node_modules/, + options: { + limit: 10000, + esModule: false, + name: '[name].[hash:7].[ext]' + } + }, + { + test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, + loader: 'url-loader', + exclude: /node_modules/, + options: { + limit: 10000, + name: '[name].[hash:7].[ext]' + } + }, + { + test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, + loader: 'url-loader', + exclude: /node_modules/, + options: { + limit: 10000, + name: '[name].[hash:7].[ext]' + } + }, + { + test: /\.(png|jpe?g|gif|svg|webp|woff2?|eot|ttf|otf|mp4|webm|ogg|mp3|wav|flac|aac)(\?\S*)?$/, loader: 'file-loader', + include: /node_modules/, options: { name: '[name].[ext]?[hash]' } @@ -84,8 +96,8 @@ module.exports = { }, resolve: { alias: { - vue$: 'vue/dist/vue.esm.js', - '@': resolve('src') + vue$: 'vue/dist/vue.esm-bundler.js', + '@': resolve('./src') }, extensions: ['*', '.js', '.vue', '.json'] }, @@ -100,24 +112,17 @@ module.exports = { hints: false }, devtool: 'source-map', + externals: { + vue: { + root: 'Vue', + commonjs: 'vue', + commonjs2: 'vue' + } + }, plugins: [ new VueLoaderPlugin(), new webpack.LoaderOptionsPlugin({ minimize: true }), - new FriendlyErrorsWebpackPlugin({ - clearConsole: false, - onErrors: (severity, errors) => { - if (severity !== 'error') { - return - } - const error = errors[0] - notifier.notify({ - title: 'Webpack error', - message: `${severity}: ${error.name}`, - subtitle: error.file || '' - }) - } - }) ] } diff --git a/build/webpack.example.js b/build/webpack.example.js index b332487..22b49b3 100644 --- a/build/webpack.example.js +++ b/build/webpack.example.js @@ -1,48 +1,43 @@ -const path = require('path'); -const webpack = require('webpack'); -const HtmlWebpackPlugin = require('html-webpack-plugin'); -const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin') +const webpack = require('webpack') +const HtmlWebpackPlugin = require('html-webpack-plugin') +const { VueLoaderPlugin } = require('vue-loader') +const ESLintPlugin = require('eslint-webpack-plugin') -const VueLoaderPlugin = require('vue-loader/lib/plugin'); - -function resolve (dir) { - return path.join(process.cwd(), dir) -} +const { resolve } = require('./utils') +/** + * @type { webpack.Configuration } + */ const webpackConfig = { mode: process.env.NODE_ENV, + target: 'web', entry: './example/main.js', output: { path: resolve('./example/dist'), - filename: '[name].[hash:7].js', + filename: '[name].[fullhash:7].js' }, resolve: { alias: { - vue$: 'vue/dist/vue.esm.js', - 'source': resolve('./src'), - '@': resolve('./example/src') + root: resolve(), + vue$: 'vue/dist/vue.esm-bundler.js', + '@': resolve('./src'), + example: resolve('./example/src') + // Non-essential, turn it on when using npm link + // vue: resolve('./node_modules/vue') }, extensions: ['*', '.js', '.vue', '.json'] + // Non-essential, turn it on when using npm link + // symlinks: false }, devServer: { - publicPath: '/', - port: 8085, - quiet: true, - hot: true, - open: true, - openPage: 'affix-example' + port: 8086, + historyApiFallback: true, }, performance: { hints: false }, module: { rules: [ - { - enforce: 'pre', - test: /\.(vue|jsx?)$/, - exclude: /node_modules/, - loader: 'eslint-loader' - }, { test: /\.(jsx?|babel|es6)$/, include: process.cwd(), @@ -64,27 +59,68 @@ const webpackConfig = { } }, { - test: /\.(scss|css)$/, + test: /\.css$/, use: [ 'vue-style-loader', - 'css-loader', - 'sass-loader' + 'css-loader' ] }, { - test: /\.(svg|otf|ttf|woff2?|eot|gif|png|jpe?g)(\?\S*)?$/, + test: /\.s(c|a)ss$/, + use: [ + 'vue-style-loader', + 'css-loader', + { + loader: 'sass-loader', + options: { + // Prefer `dart-sass` + implementation: require('sass') + } + } + ] + }, + { + test: /\.(png|jpe?g|gif|svg|webp)(\?.*)?$/, loader: 'url-loader', - query: { + exclude: /node_modules/, + options: { limit: 10000, - name: '[name].[hash:7].[ext]' + esModule: false, + name: '[name].[fullhash:7].[ext]' + } + }, + { + test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, + loader: 'url-loader', + exclude: /node_modules/, + options: { + limit: 10000, + name: '[name].[fullhash:7].[ext]' + } + }, + { + test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, + loader: 'url-loader', + exclude: /node_modules/, + options: { + limit: 10000, + name: '[name].[fullhash:7].[ext]' + } + }, + { + test: /\.(png|jpe?g|gif|svg|webp|woff2?|eot|ttf|otf|mp4|webm|ogg|mp3|wav|flac|aac)(\?\S*)?$/, + loader: 'file-loader', + include: /node_modules/, + options: { + name: '[name].[ext]?[fullhash]' } } ] }, plugins: [ - new webpack.HotModuleReplacementPlugin(), + new ESLintPlugin(), new HtmlWebpackPlugin({ - template: './example/index.html', + template: './example/index.html' }), new VueLoaderPlugin(), new webpack.LoaderOptionsPlugin({ @@ -94,25 +130,15 @@ const webpackConfig = { } } }), - new FriendlyErrorsWebpackPlugin({ - clearConsole: false, - onErrors: (severity, errors) => { - if (severity !== 'error') { - return - } - const error = errors[0] - notifier.notify({ - title: 'Webpack error', - message: `${severity}: ${error.name}`, - subtitle: error.file || '' - }) - } - }) + new webpack.DefinePlugin({ + __VUE_OPTIONS_API__: false, + __VUE_PROD_DEVTOOLS__: false, + }), ], optimization: { minimizer: [] }, - devtool: '#eval-source-map' -}; + devtool: 'eval-source-map' +} -module.exports = webpackConfig; \ No newline at end of file +module.exports = webpackConfig diff --git a/example/App.vue b/example/App.vue index 7e0489a..c5d008a 100644 --- a/example/App.vue +++ b/example/App.vue @@ -1,13 +1,13 @@ - +export default defineComponent({ + name: 'App' +}) + + diff --git a/example/main.js b/example/main.js index 215efde..722a83b 100644 --- a/example/main.js +++ b/example/main.js @@ -1,12 +1,13 @@ -import Vue from 'vue' +import { createApp } from 'vue' import router from './router.js' - -import HocElementAffix from 'source/main.js' import App from './App.vue' -Vue.use(HocElementAffix) +import HocElementAffix from 'root/lib/hoc-el-affix' // Switch to bundle lib +// import HocElementAffix from '@/main.js' -new Vue({ - router, - render: h => h(App) -}).$mount('#app') +import 'example/styles/variables.scss' + +createApp(App) + .use(router) + .use(HocElementAffix) + .mount('#app') diff --git a/example/router.js b/example/router.js index 92e8aee..ff6af9f 100644 --- a/example/router.js +++ b/example/router.js @@ -1,24 +1,15 @@ -import Vue from 'vue' -import VueRouter from 'vue-router' +import { createRouter, createWebHistory } from 'vue-router' -const Layout = () => import('@/components/Layout') const importModule = (filePath) => { - return () => import(`@/${filePath}`) + return () => import(`example/${filePath}`) } const routes = [{ path: '/', - component: Layout, - children: [ - { - path: 'affix-example', - component: importModule('views/ExampleAffix') - } - ] + component: importModule('views/ExampleAffix') }] -Vue.use(VueRouter) -export default new VueRouter({ +export default createRouter({ routes, - mode: 'history' + history: createWebHistory() }) diff --git a/example/src/assets/logo.svg b/example/src/assets/logo.svg new file mode 100644 index 0000000..4dfdfaa --- /dev/null +++ b/example/src/assets/logo.svg @@ -0,0 +1,23 @@ + diff --git a/example/src/components/Layout.vue b/example/src/components/Layout.vue index 4d2aa3f..ed31e78 100644 --- a/example/src/components/Layout.vue +++ b/example/src/components/Layout.vue @@ -1,28 +1,12 @@ - - diff --git a/example/src/styles/variables.scss b/example/src/styles/variables.scss new file mode 100644 index 0000000..18b77f8 --- /dev/null +++ b/example/src/styles/variables.scss @@ -0,0 +1,14 @@ +* { + margin: 0; + padding: 0; +} +html, body { + background-color: #000; +} +#app { + font-family: Avenir, Helvetica, Arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + color: #FCFAF2; +} + diff --git a/example/src/views/ExampleAffix.vue b/example/src/views/ExampleAffix.vue index a6ca484..563c541 100644 --- a/example/src/views/ExampleAffix.vue +++ b/example/src/views/ExampleAffix.vue @@ -1,5 +1,18 @@