├── .gitignore ├── README.md ├── index.js ├── package.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # VS Code dir 61 | .vscode 62 | 63 | # MacOS 64 | .DS_Store 65 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-responsive-components 2 | 3 | Create responsive components with ResizeObserver. 4 | 5 | ## Idea 6 | 7 | Check out [**my post on ITNEXT**](https://itnext.io/making-adaptive-vue-components-with-resizeobserver-123b5ebb20ae) 8 | 9 | ## Installation 10 | 11 | ``` 12 | npm install vue-responsive-components 13 | ``` 14 | 15 | ## (Optional) Add plugin globally 16 | 17 | ```javascript 18 | import Vue from "vue" 19 | import { VueResponsiveComponents } from "vue-responsive-components" 20 | 21 | Vue.use(VueResponsiveComponents) 22 | ``` 23 | 24 | It will add `Responsive` component and `v-responsive` directive 25 | 26 | ## Usage 27 | 28 | #### `Responsive` component with scoped slot 29 | 30 | ```vue 31 | 41 | 42 | 50 | 51 | 70 | ``` 71 | 72 | #### `v-responsive` directive 73 | 74 | > Thanks to [**this guy**](https://www.reddit.com/r/vuejs/comments/8eap88/making_responsive_vue_components_with/dxtx0bu/) for idea 75 | 76 | ```vue 77 | 84 | 85 | 95 | ``` 96 | 97 | #### Mixin 98 | 99 | ```vue 100 | 106 | 107 | 118 | ``` 119 | 120 | ## License 121 | 122 | MIT 123 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import throttle from "lodash.throttle" 2 | import ResizeObserver from "resize-observer-polyfill" 3 | 4 | export const ResponsiveMixin = { 5 | data() { 6 | return { 7 | el: { 8 | width: 0, 9 | height: 0, 10 | is: {} 11 | } 12 | } 13 | }, 14 | mounted() { 15 | if ( 16 | typeof process === "undefined" || 17 | (!process.server && (this.breakpoints || this.$options.breakpoints)) 18 | ) { 19 | this.$nextTick(() => { 20 | const handleResize = throttle(entries => { 21 | const cr = entries[0].contentRect 22 | ;(this.el.width = cr.width), (this.el.height = cr.height) 23 | const conds = Object.assign( 24 | {}, 25 | this.breakpoints || {}, 26 | this.$options.breakpoints || {} 27 | ) 28 | for (const breakpoint in conds) { 29 | this.$set(this.el.is, breakpoint, conds[breakpoint](this.el)) 30 | } 31 | }, 200) 32 | 33 | const observer = new ResizeObserver(handleResize) 34 | if (this.$el instanceof Element) { 35 | observer.observe(this.$el) 36 | } 37 | }) 38 | } 39 | } 40 | } 41 | 42 | export const Responsive = { 43 | data() { 44 | return { init: false } 45 | }, 46 | props: { 47 | noHide: { type: Boolean, default: false }, 48 | breakpoints: { type: Object, default: undefined } 49 | }, 50 | mixins: [ResponsiveMixin], 51 | render(h) { 52 | const slot = 53 | (this.$scopedSlots.default && this.$scopedSlots.default(this.el)) || 54 | this.$slots.default 55 | 56 | return !this.noHide && !this.init 57 | ? h( 58 | "div", 59 | { 60 | style: { visibility: "hidden" } 61 | }, 62 | [slot] 63 | ) 64 | : slot 65 | }, 66 | mounted() { 67 | this.init = true 68 | } 69 | } 70 | 71 | export const ResponsiveDirective = { 72 | inserted(el, conds) { 73 | if (typeof process === "undefined" || !process.server) { 74 | const handleResize = throttle(entries => { 75 | const cr = entries[0].contentRect 76 | for (const breakpoint in conds.value) { 77 | if (conds.value[breakpoint](cr)) { 78 | el.classList.add(breakpoint) 79 | } else { 80 | el.classList.remove(breakpoint) 81 | } 82 | } 83 | }, 200) 84 | 85 | const observer = new ResizeObserver(handleResize) 86 | observer.observe(el) 87 | } 88 | } 89 | } 90 | 91 | export const VueResponsiveComponents = Vue => { 92 | Vue.component("Responsive", Responsive) 93 | Vue.directive("responsive", ResponsiveDirective) 94 | } 95 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-responsive-components", 3 | "version": "0.2.3", 4 | "description": "Easily create responsive Vue.js components with ResizeObserver", 5 | "main": "index.js", 6 | "module": "index.js", 7 | "repository": "https://github.com/kelin2025/vue-responsive-components", 8 | "author": "Anton Kosykh ", 9 | "license": "MIT", 10 | "dependencies": { 11 | "lodash.throttle": "^4.1.1", 12 | "resize-observer-polyfill": "^1.5.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | lodash.throttle@^4.1.1: 6 | version "4.1.1" 7 | resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" 8 | 9 | resize-observer-polyfill@^1.5.0: 10 | version "1.5.0" 11 | resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.0.tgz#660ff1d9712a2382baa2cad450a4716209f9ca69" 12 | --------------------------------------------------------------------------------