Skip to content
This repository has been archived by the owner on Jan 18, 2022. It is now read-only.

feat: Vue 2.x compability #9

Closed
wants to merge 91 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
0415410
feat: Vue 2.x compability
karol-f Oct 8, 2016
a5e3523
docs: vue 2.x update
karol-f Oct 8, 2016
b09c053
feat: add to propsData only values from component props, add created …
karol-f Oct 8, 2016
11fa3c1
feat(create): create Vue instance only once, on 'created' callback
karol-f Oct 21, 2016
19fe202
revert(create): create Vue instance only once, on 'created' callback
karol-f Nov 21, 2016
fd7630a
feat(custom-elements): using V1 specs backbone
karol-f Jan 1, 2017
5d12c0a
feat(custom-elements): V1 class init, .babelrc remove unnecessary plugin
karol-f Jan 1, 2017
b4399e9
feat(custom-elements): connected, disconnected, attributeChanged call…
karol-f Jan 2, 2017
efc70e0
feat(custom-elements): reorganize files, cleanup, options
karol-f Jan 2, 2017
8d6c98a
feat(vue-element): initial code for vue-element
karol-f Jan 2, 2017
ec3e022
feat(vue-element): improvements, first semi-working code
karol-f Jan 3, 2017
f8506ef
feat(vue-element): improvements, working code
karol-f Jan 3, 2017
4efff26
feat(vue-element): props and arguments handling improvements
karol-f Jan 3, 2017
7255ad8
feat(vue-element): proper propsData handling
karol-f Jan 3, 2017
3438602
feat(vue-element): fix 'this' in es2015 constructor
karol-f Jan 4, 2017
acd797a
feat(vue-element): eslint
karol-f Jan 4, 2017
723b436
test: remove unnecessary test
karol-f Jan 4, 2017
6010cfe
feat(vue-element): Add proxy component for HMR and slot
karol-f Jan 4, 2017
6a971d5
fix(vue-element): fix bug with props type
karol-f Jan 4, 2017
baa2e37
chore(eslint): update rules
karol-f Jan 4, 2017
3d746a7
refactor: renaming
karol-f Jan 4, 2017
20c2d9e
chore(dependencies): bump dependencies
karol-f Jan 5, 2017
2924ec9
fix(slot): fix non text slots, multiple children nodes
karol-f Jan 5, 2017
3e913aa
feat(custom-elements): do not throw error if customElements is not av…
karol-f Jan 5, 2017
c6dff17
feat(vue-element): add Shadow Dom option
karol-f Jan 5, 2017
fb6f454
fix(vue-element): get tag name from options
karol-f Jan 5, 2017
25721ee
fix(vue-element): Shadow DOM working properly
karol-f Jan 5, 2017
761001e
docs: images
karol-f Jan 5, 2017
187ed45
chore: remove dist/ folder from .gitignore
karol-f Jan 5, 2017
97de91b
feat(demo): prepare for docs & demos
karol-f Jan 6, 2017
a6970e4
feat(slot): minor improvement
karol-f Jan 6, 2017
6594cd9
fix(slots): named slots, no wrapper needed
karol-f Jan 6, 2017
e10844d
docs(demo): prepare for demos
karol-f Jan 6, 2017
a2825b7
docs(demo): improve layout
karol-f Jan 6, 2017
fb57ceb
docs(demo): improve layout
karol-f Jan 6, 2017
ac1c4fb
docs(demos): source highlighting, element-ui, improve demo page styling
karol-f Jan 6, 2017
25f8655
demo: basic demo
karol-f Jan 7, 2017
4875ea2
docs(demo): automatize demos inserting (route and Custom Element regi…
karol-f Jan 7, 2017
eed82dc
docs(demo): "Binding Demo", improvements
karol-f Jan 7, 2017
382ef5f
docs(demo): "Slots Demo", improvements
karol-f Jan 7, 2017
757229c
feat(vue-element): add lazy loading feature
karol-f Jan 7, 2017
8e2c4c0
docs(demo): "Lazy loading demo", improvements
karol-f Jan 7, 2017
2b3c950
docs(demo): "Lazy loading demo" improvements
karol-f Jan 7, 2017
74b7f53
docs(demo): "Lazy loading demo" improvements
karol-f Jan 7, 2017
97c3fa9
feat(vue-element): auto Vue.use when not required
karol-f Jan 8, 2017
ce5f787
feat(vue-element): compatibility 0.12+
karol-f Jan 8, 2017
41eeb5d
docs(demo): wording
karol-f Jan 8, 2017
e851248
docs(readme): initial changes
karol-f Jan 8, 2017
42e90ac
docs: add image - logo with text
karol-f Jan 8, 2017
8d21b5d
docs(demo): styling
karol-f Jan 8, 2017
5ef6ca5
docs(readme): changes
karol-f Jan 8, 2017
15afafd
chore(release): build production
karol-f Jan 8, 2017
cb10e7f
docs(readme): changes
karol-f Jan 8, 2017
69f54cf
docs(github-pages): prepare for github pages
karol-f Jan 8, 2017
880e3aa
docs(readme): improvements
karol-f Jan 8, 2017
f8a4b8c
chore(npm): update package.json
karol-f Jan 8, 2017
592af34
docs(readme): improvements
karol-f Jan 8, 2017
7be1a4e
chore(release): build production, change paths, improve config
karol-f Jan 8, 2017
b1da15a
docs(github-pages): update demo site
karol-f Jan 8, 2017
d2acf3a
chore(release): fix public path
karol-f Jan 8, 2017
d4f0806
docs(github-pages): update demo site
karol-f Jan 8, 2017
eafe4ca
docs(readme): improvements
karol-f Jan 8, 2017
75e31d5
docs(demo): styling
karol-f Jan 8, 2017
09f5ee8
docs(readme): improvements
karol-f Jan 8, 2017
826308c
chore(release): delete demo files from 'dist'
karol-f Jan 8, 2017
c2a742d
chore(release): only vue-element.* in 'dist/' folder
karol-f Jan 8, 2017
2aea927
fix(vue-element): proper destroying Vue instance on detached
karol-f Jan 8, 2017
e0773c2
docs(readme): improvements
karol-f Jan 8, 2017
3411bfc
docs(readme): improvements
karol-f Jan 8, 2017
4477d2a
feat(vue-element): improve and simplify lazy-loading, docs
karol-f Jan 8, 2017
15f8d59
chore(release): release new docs and vue-element
karol-f Jan 8, 2017
1427b9f
feat(vue-element): handle ve-cloak and ve-ready attributes
karol-f Jan 8, 2017
f21e3ff
docs(readme): improvements
karol-f Jan 8, 2017
b217219
chore(release): release new docs and vue-element
karol-f Jan 8, 2017
5578322
docs(readme): improvements
karol-f Jan 8, 2017
3f2bc91
docs(demo): typo in Binding demo
karol-f Jan 8, 2017
c41e23b
docs(demo): wording in LazyLoading Demo
karol-f Jan 8, 2017
3957ca9
chore(release): release new docs
karol-f Jan 8, 2017
003409d
docs(readme): info about release and ES6 polyfill usage
karol-f Jan 9, 2017
071e5fd
feat(custom-elements): export registered Custom Element constructor
karol-f Jan 9, 2017
02ccfb4
docs(readme): add "Why do you need Vue-element?" section
karol-f Jan 10, 2017
57e321f
feat(vue-element): allow for passing functions to props using JavaScript
karol-f Jan 10, 2017
8a6b6ea
feat(demo): added "DemoCallback", improved docs
karol-f Jan 10, 2017
07b54b3
chore(release): updated vue-element.js and docs
karol-f Jan 10, 2017
f786e3d
docs(readme): fix typo
karol-f Jan 11, 2017
307ebe5
docs(demo): improve 'Demo Callback', add Vue binding example
karol-f Jan 11, 2017
0e77f26
chore(release): update docs
karol-f Jan 11, 2017
ccdbc08
docs(infographic): minor changes
karol-f Jan 11, 2017
1dea675
docs(demo): improve 'Demo Callback'
karol-f Jan 11, 2017
4bfe67b
chore(release): update demos
karol-f Jan 11, 2017
fc153ff
docs: minor description editing
karol-f Jan 30, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 11 additions & 0 deletions .babelrc
@@ -0,0 +1,11 @@
{
"presets": [
"es2015",
"stage-2"
],
"plugins": [
"transform-custom-element-classes",
"transform-vue-jsx"
],
"comments": false
}
9 changes: 9 additions & 0 deletions .editorconfig
@@ -0,0 +1,9 @@
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
2 changes: 2 additions & 0 deletions .eslintignore
@@ -0,0 +1,2 @@
build/*.js
config/*.js
49 changes: 49 additions & 0 deletions .eslintrc.js
@@ -0,0 +1,49 @@
module.exports = {
root: true,
parser: 'babel-eslint',
parserOptions: {
sourceType: 'module'
},
'env': {
'browser': true
},
extends: 'airbnb-base',
// required to lint *.vue files
plugins: [
'html'
],
// check if imports actually resolve
'settings': {
'import/resolver': {
'webpack': {
'config': 'build/webpack.base.conf.js'
}
}
},
// add your custom rules here
'rules': {
// don't require .vue extension when importing
'import/extensions': ['error', 'always', {
'js': 'never',
'vue': 'never'
}],
"comma-dangle": ["error", "never"],
"no-unused-expressions": ["error", { "allowShortCircuit": true }],
"no-param-reassign": ["error", { "props": false }],
'max-len': ['error', 100, 2, {
ignoreUrls: true,
ignoreComments: true,
ignoreStrings: true,
ignoreTemplateLiterals: true,
}],
"no-underscore-dangle": ["error", { "allow": ["__vue_element__", "__detached__"] }],
"spaced-comment": ["error", "always", { "exceptions": ["/"] }],
// allow debugger during development
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
"class-methods-use-this": 0
},
'globals': {
'HTMLElement': true,
'customElements': true
}
};
37 changes: 36 additions & 1 deletion .gitignore
@@ -1 +1,36 @@
.DS_Store
# OS generated files #
######################
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
*.tmp
.idea

# Generated files #
######################
*node_modules
.sass-cache
.happypack
.bower-*
report/
bower_component
docs/bower_components
libs/
coverage
*.log
docs/esdoc/
docs/docco/
TESTS-*
.yarnrc
yarn.lock
test/unit/coverage
test/e2e/reports
selenium-debug.log

dist/*
!dist/vue-element*

201 changes: 183 additions & 18 deletions README.md
@@ -1,41 +1,206 @@
# Vue.element plugin
![Vue-element](src/demo/assets/images/vue-element-logo-text.png)

Register a real Custom Element using Vue.js.
## Table of content

## Requirements
- [Demo](#demo)
- [Installation](#installation)
- [Description](#description)
- [Example](#example)
- [Browsers support](#browsers-support)
- [Options](#options)
- [How does it work?](#how-does-it-work)
- [Testing](#testing)
- [Caveats](#caveats)

- Does not work with Vue 2.0 yet
- Only works with Vue ^0.11.0
- The browser must support the Custom Element API (currently Chrome only), or you need to include the [Web Components polyfill](https://github.com/webcomponents/webcomponentsjs).
## Demo
You can check Vue-element demos at **https://karol-f.github.io/vue-element/**

## Installation

Available through npm, Component, Duo or Bower.
#### NPM
```bash
npm install vue-element --save
```

```javascript
import vueElement from 'vue-element'

Vue.use(vueElement);
```

### Direct include
#### Direct include

If you are using Vue globally, just include `vue-element.js` and it will automatically install the `Vue.element` method.

### CommonJS
```html
<script src="path/to/vue-element.js"></script>
```
####Optional polyfill
For cross-browser compatibility (IE9+) use Custom Elements polyfill.

```html
<script src="https://cdnjs.cloudflare.com/ajax/libs/document-register-element/1.3.0/document-register-element.js"></script>
```

or

```
import 'document-register-element/build/document-register-element';
```

## Description

`Vue-element` is a tiny wrapper around Vue components. It provide seamless way to use it in HTML, plain JavaScript, Vue, React, Angular etc., using power of Custom Elements.
* Works with Vue 0.12.x, 1.x and 2.x
* Small - 2.5 kb min+gzip, optional polyfill - 5,1 kb min+gzip

### Why you might need `Vue-element`?
![Vue-element](src/demo/assets/images/vue-element-why.png)

It might be confusing for users to understand difference between Vue components, Custom Elements and it's use cases.

Why you might need `Vue-element`? Simply, for your Vue components user's convinience. All they would need to do is include your JavaScript file and then they can:

* include HTML tag (e.g. `<my-component><my-component />`) in any time of document lifecycle. You can use your elements in e.g. SPA application just by including HTML tag - no Vue initialization or JavaScript usage is needed. Custom Elements will auto initialize when mounted into document. You can include them in e.g. Vue, Angular or React projects and browser will take care of detecting it and initialization
* use simple API that allows for interacting with underlaying Vue instance by changing attributes, props or passing callback functions
* take advantage of features like lazy-loading, that allows for loading components on demand, only when user add them to document

### Features

* **Simplicity** - only `tag-name` and Vue component `object` is needed for `Vue.element()` usage
* **Compatibility** - using optional polyfill we can support wide range of browsers, including IE9+, Android and IOS
* **Full featured** - you can use nesting, HMR, slots, lazy-loading, native Custom Elements callbacks.
* reactive props and HTML attributes
* automatic props casting (numbers, booleans) so they won't be available as strings but proper data types
* passing callback functions to props via JavaScript
* 'default' and 'named' slots are available, check demo for example
* Hot Module Replacement for seamless developer experience (Vue 2.x+)
* lazy-loading - you can download component after it's attached to document. Useful for e.g. UI library authors. Check demo for example
* detecting if detached callback is not invoked due to opening vue-element in modal - element is then detached and attached to DOM again. It would be undesirable to destroy it immediately
* **Custom Elements v1** - compatible with latest specification. Vue-element will use native implementation if supported

Check demos site to see it in action.

## Example
For additional examples and detailed description check the demos page.

###### Custom Element HTML
``` html
<widget-vue prop1="1" prop2="string" prop3="true"></widget-vue>
```

###### JavaScript - register with Vue-element
``` js
Vue.element('widget-vue', {
props: [
'prop1',
'prop2',
'prop3'
],
data: {
message: 'Hello Vue!'
},
template: '<p>{{ message }}, {{ prop1 }}, {{prop2}}, {{prop3}}</p>'
});
```

###### JavaScript - element API usage
``` js
Vue.use(require('vue-element')) // installed
Vue.element('my-element', { /* ... */ })
document.querySelector('widget-vue')[0].prop2 // get prop value
document.querySelector('widget-vue')[0].prop2 = 'another string' // set prop value
```

## Usage
You can also change `<widget-vue>` HTML attributes and changes will be instantly reflected.


Usage is the same as `Vue.component()` - you pass in exactly the same options as if you are defining a Vue component. A few things to note:
## Browsers support

- Nested Vue custom elements are not supported - it is recommended to use Vue's own component system inside a custom element; The custom element interface is intended for inter-op with other libraries (e.g. Polymer).
| [<img src="https://raw.githubusercontent.com/godban/browsers-support-badges/master/src/images/firefox.png" alt="Firefox" width="16px" height="16px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/godban/browsers-support-badges/master/src/images/chrome.png" alt="Chrome" width="16px" height="16px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/godban/browsers-support-badges/master/src/images/safari.png" alt="Safari" width="16px" height="16px" />](http://godban.github.io/browsers-support-badges/)</br>Safari | [<img src="https://raw.githubusercontent.com/godban/browsers-support-badges/master/src/images/opera.png" alt="Opera" width="16px" height="16px" />](http://godban.github.io/browsers-support-badges/)</br>Opera | [<img src="https://raw.githubusercontent.com/godban/browsers-support-badges/master/src/images/chrome-android.png" alt="Chrome for Android" width="16px" height="16px" />](http://godban.github.io/browsers-support-badges/)</br>Android |
|:---------:|:---------:|:---------:|:---------:|:---------:|
| behind --flag| 54+ | Technology Preview| 42+| 55+

- You don't need to manually instantiate a root level Vue instance. Custom Elements get auto-promoted when `document.registerElement` is called. You can also freely define the element before or after the markup.
[Custom Elements v1 support](http://caniuse.com/#feat=custom-elementsv1)

- Real custom elements **must** contain a hyphen in its tag name. For example, `my-element` is valid, but `myelement` is not.
#### With optional polyfill

- You can expose attributes with Vue's `props` (0.12) or `paramAttributes` (0.11) option, but you can only pass in literal values (no dynamic bindings). See the example folder to see it in action.
| [<img src="https://raw.githubusercontent.com/godban/browsers-support-badges/master/src/images/edge.png" alt="IE / Edge" width="16px" height="16px" />](http://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/godban/browsers-support-badges/master/src/images/firefox.png" alt="Firefox" width="16px" height="16px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/godban/browsers-support-badges/master/src/images/chrome.png" alt="Chrome" width="16px" height="16px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/godban/browsers-support-badges/master/src/images/safari.png" alt="Safari" width="16px" height="16px" />](http://godban.github.io/browsers-support-badges/)</br>Safari | [<img src="https://raw.githubusercontent.com/godban/browsers-support-badges/master/src/images/opera.png" alt="Opera" width="16px" height="16px" />](http://godban.github.io/browsers-support-badges/)</br>Opera | [<img src="https://raw.githubusercontent.com/godban/browsers-support-badges/master/src/images/safari-ios.png" alt="iOS Safari" width="16px" height="16px" />](http://godban.github.io/browsers-support-badges/)</br>iOS | [<img src="https://raw.githubusercontent.com/godban/browsers-support-badges/master/src/images/chrome-android.png" alt="Chrome for Android" width="16px" height="16px" />](http://godban.github.io/browsers-support-badges/)</br>Android |
|:---------:|:---------:|:---------:|:---------:|:---------:|:---------:|:---------:|
| IE9+, Edge| &check;| &check; | &check; | &check; | &check; | &check;

## Options
Additional, optional, third parameter to `Vue.element()` is options object. You can pass following methods.

'This' in callbacks points to Custom Element's DOM Node.

```javascript
{
// 'constructorCallback' can be triggered multiple times when e.g. vue-router is used
constructorCallback() {
console.info('constructorCallback', this);
},

// element is mounted/inserted into document
connectedCallback() {
console.info('connectedCallback', this);
},

// element is removed from document
disconnectedCallback() {
console.warn('disconnectedCallback', this);
},

// one of element's attributes (Vue instance props) is changed
attributeChangedCallback(name, oldValue, value) {
console.info('attributeChangedCallback', name, oldValue, value);
},

// only needed when using lazy-loading - when 'props' are not accessible on Custom Element registration
props: [],

// you can set shadow root for element. Only works if native implementation is available.
shadow: false
}
```

Callbacks are executed before lifecycle hooks from Vue component passed to Vue-element. It's better idea just to use Vue component lifecycle hooks (e.g. `created`, `mounted`, `beforeDestroy`).

## How does it work?
![Vue-element](src/demo/assets/images/vue-element-schema.png)

Inside HTML tag of defined custom element, Vue-element will create:

* Proxy component for seamless Hot Module Replacement, using render function for performance (Vue 2.x+)
* Vue component passed to Vue-element

Custom Element HTML tag will expose API to interact with underlying Vue component - you can change HTML attributes or props, using JavaScript.

## Testing

For advanced access, when exposed API is not enough, defined custom element will expose Vue instance via `__vue_element__` prop.

```javascript
console.info(document.querySelector('widget-vue').__vue_element__)
```
## Caveats

* custom elements **must** contain a hyphen in its tag name. For example, `my-element` is valid, but `myelement` is not
* in dev mode Vue will display console warning about element not being registered. It's desirable behaviour as we want to use browser's Custom Elements registration

## Contribute

#### Developement
```
npm install
npm run dev
```

#### Release
```
npm run build
```
This command will compile `vue-element.js` and docs files (handled by `.gitignore`) to `dist` folder. You have to manually copy it to `docs` folder.

- By default the element does not use Shadow DOM. If you want to enable Shadow DOM encapsulation, pass in `shadow: true` in your component options.
Please take a note that `npm run build` will use `config.build.assetsPublicPath`, which is set to Github Pages path in `config/index.js`.

## License

Expand Down
36 changes: 36 additions & 0 deletions build/build.js
@@ -0,0 +1,36 @@
// https://github.com/shelljs/shelljs
require('./check-versions')()
require('shelljs/global')
env.NODE_ENV = 'production'

var path = require('path')
var config = require('../config')
var ora = require('ora')
var webpack = require('webpack')
var webpackConfig = require('./webpack.prod.conf')

console.log(
' Tip:\n' +
' Built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n'
)

var spinner = ora('building for production...')
spinner.start()

var assetsPath = path.join(config.build.assetsRoot, config.build.assetsSubDirectory)
rm('-rf', assetsPath)
mkdir('-p', assetsPath)
cp('-R', 'static/*', assetsPath)

webpack(webpackConfig, function (err, stats) {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false,
chunks: false,
chunkModules: false
}) + '\n')
})