├── .babelrc
├── .editorconfig
├── .gitignore
├── README.md
├── index.html
├── package.json
├── src
├── App.vue
├── assets
│ └── logo.png
├── components
│ ├── BlogPost.vue
│ └── CommentsList.vue
├── hocs
│ └── withSubscription.js
├── main.js
└── store
│ └── source.js
└── webpack.config.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["env", { "modules": false }],
4 | "stage-3"
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | dist/
4 | npm-debug.log
5 | yarn-error.log
6 |
7 | # Editor directories and files
8 | .idea
9 | *.suo
10 | *.ntvs*
11 | *.njsproj
12 | *.sln
13 | *.vscode
14 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vue-hoc
2 |
3 | > Simple project demonstrating how to use Higher-Order Componets in Vue
4 |
5 | ## Build Setup
6 |
7 | ``` bash
8 | # install dependencies
9 | npm install
10 |
11 | # serve with hot reload at localhost:8080
12 | npm run dev
13 |
14 | # build for production with minification
15 | npm run build
16 | ```
17 |
18 | For detailed explanation on how things work, consult the [docs for vue-loader](http://vuejs.github.io/vue-loader).
19 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue-hoc
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-hoc",
3 | "description": "Simple project demonstrating how to use Higher-Order Componets in Vue",
4 | "version": "1.0.0",
5 | "author": "Bogna \"bognix\" Knychala ",
6 | "license": "MIT",
7 | "private": true,
8 | "scripts": {
9 | "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
10 | "build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
11 | },
12 | "dependencies": {
13 | "vue": "^2.5.11"
14 | },
15 | "browserslist": [
16 | "> 1%",
17 | "last 2 versions",
18 | "not ie <= 8"
19 | ],
20 | "devDependencies": {
21 | "babel-core": "^6.26.0",
22 | "babel-loader": "^7.1.2",
23 | "babel-preset-env": "^1.6.0",
24 | "babel-preset-stage-3": "^6.24.1",
25 | "cross-env": "^5.0.5",
26 | "css-loader": "^0.28.7",
27 | "file-loader": "^1.1.4",
28 | "vue-loader": "^13.0.5",
29 | "vue-template-compiler": "^2.4.4",
30 | "webpack": "^3.6.0",
31 | "webpack-dev-server": "^2.9.1"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |

4 |
{{ msg }}
5 |
6 |
7 |
8 |
9 |
10 |
38 |
39 |
67 |
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bognix/vue-hoc/a231871fb61c355e320682027f3d3e8ebc022f7b/src/assets/logo.png
--------------------------------------------------------------------------------
/src/components/BlogPost.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{data}}
6 |
7 |
8 |
9 |
14 |
--------------------------------------------------------------------------------
/src/components/CommentsList.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
13 |
--------------------------------------------------------------------------------
/src/hocs/withSubscription.js:
--------------------------------------------------------------------------------
1 | import DataSource from '../store/source'
2 | import Vue from 'vue'
3 |
4 |
5 | const withSubscription = (component, selectData) => {
6 | const inheritedProps = component.props || [];
7 |
8 | return Vue.component('withSubscription', {
9 | render(createElement) {
10 | return createElement(component, {
11 | props: {
12 | ...inheritedProps,
13 | data: this.fetchedData
14 | },
15 | on: {...this.$listeners}
16 | })
17 | },
18 | props: [...inheritedProps],
19 | data() {
20 | return {
21 | fetchedData: null
22 | }
23 | },
24 | methods: {
25 | handleChange() {
26 | this.fetchedData = selectData(DataSource, this.$props)
27 | }
28 | },
29 | mounted() {
30 | DataSource.addChangeListener(this.handleChange)
31 | },
32 | beforeDestroy() {
33 | DataSource.removeChangeListener(this.handleChange)
34 | }
35 | })
36 | }
37 |
38 | export default withSubscription
39 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App.vue'
3 |
4 | new Vue({
5 | el: '#app',
6 | render: h => h(App)
7 | })
8 |
--------------------------------------------------------------------------------
/src/store/source.js:
--------------------------------------------------------------------------------
1 | const listeners = {};
2 | const comments = ['comment one', 'comment two', 'comment three', 'comment four', 'comment five'];
3 | const blogPosts = {
4 | 1: `Lorem ipsum dolor sit amet, utinam scripta splendide ei cum.
5 | Mediocrem dissentiet est ut, nec tale ullum no, has putent scaevola mediocrem an.
6 | Ex quot latine denique vim, ne quot quaeque sea.
7 | In pri habeo diceret, an ius tale voluptatum, ad liber facilis minimum vis.
8 | Eos iriure concludaturque id, sed inani nulla interesset in, labores adipiscing dissentiet vel ut.`,
9 | 2: 'Peek-A-Boo!'
10 | }
11 |
12 | setInterval(() => {
13 | comments.push(`fresh comment ${comments.length + 1}`)
14 | Object.keys(blogPosts).forEach(id => {
15 | blogPosts[id] = `${blogPosts[id]} ${comments.length}`
16 | })
17 | }, 5000)
18 |
19 | export default {
20 | getComments() {
21 | return comments;
22 | },
23 |
24 | getBlogPost(id) {
25 | return blogPosts[id];
26 | },
27 |
28 | addChangeListener(listener) {
29 | const intervalId = setInterval(() => {
30 | listener()
31 | }, 1000)
32 |
33 | listeners[listener] = intervalId
34 | },
35 |
36 | removeChangeListener(listener) {
37 | clearInterval(listeners[listener])
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var webpack = require('webpack')
3 |
4 | module.exports = {
5 | entry: './src/main.js',
6 | output: {
7 | path: path.resolve(__dirname, './dist'),
8 | publicPath: '/dist/',
9 | filename: 'build.js'
10 | },
11 | module: {
12 | rules: [
13 | {
14 | test: /\.css$/,
15 | use: [
16 | 'vue-style-loader',
17 | 'css-loader'
18 | ],
19 | }, {
20 | test: /\.vue$/,
21 | loader: 'vue-loader',
22 | options: {
23 | loaders: {
24 | }
25 | // other vue-loader options go here
26 | }
27 | },
28 | {
29 | test: /\.js$/,
30 | loader: 'babel-loader',
31 | exclude: /node_modules/
32 | },
33 | {
34 | test: /\.(png|jpg|gif|svg)$/,
35 | loader: 'file-loader',
36 | options: {
37 | name: '[name].[ext]?[hash]'
38 | }
39 | }
40 | ]
41 | },
42 | resolve: {
43 | alias: {
44 | 'vue$': 'vue/dist/vue.esm.js'
45 | },
46 | extensions: ['*', '.js', '.vue', '.json']
47 | },
48 | devServer: {
49 | historyApiFallback: true,
50 | noInfo: true,
51 | overlay: true
52 | },
53 | performance: {
54 | hints: false
55 | },
56 | devtool: '#eval-source-map'
57 | }
58 |
59 | if (process.env.NODE_ENV === 'production') {
60 | module.exports.devtool = '#source-map'
61 | // http://vue-loader.vuejs.org/en/workflow/production.html
62 | module.exports.plugins = (module.exports.plugins || []).concat([
63 | new webpack.DefinePlugin({
64 | 'process.env': {
65 | NODE_ENV: '"production"'
66 | }
67 | }),
68 | new webpack.optimize.UglifyJsPlugin({
69 | sourceMap: true,
70 | compress: {
71 | warnings: false
72 | }
73 | }),
74 | new webpack.LoaderOptionsPlugin({
75 | minimize: true
76 | })
77 | ])
78 | }
79 |
--------------------------------------------------------------------------------