Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
* develop: (27 commits)
  1.0.0-beta.4
  chores
  changed build script to work around cross-env
  improved examples, added router to split things up nicely
  fix example index.js for production run
  new test build
  bumping dependencies
  caused troubles with dependency svgo
  fix dockute dependency and nom script
  add $refs test to the examples
  add section about $refs caveat from #23 to docs
  chores
  clean up npm scripts, include test run in build script
  remove unnecessary folder
  add „Caveats“ page to docs
  add test for abstract component option
  Document SSR limitations when using „targetEl“
  make „to“ optional when targetEl is provided (fix #30)
  add reference to parent component (fix #34) (fix#35) (+1 squashed commit) Squashed commits: [770211d] enhance `targetEl` example with test component to verify that it shows up in devtools correctly.
  switch to nextTick instead of timeout in hopes of making refs work
  ...
  • Loading branch information
LinusBorg committed May 14, 2017
2 parents 532e010 + 34577fb commit 86f4439
Show file tree
Hide file tree
Showing 35 changed files with 489 additions and 211 deletions.
2 changes: 2 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ docs/
build/
example/
test/

logo.xcf
12 changes: 12 additions & 0 deletions build/rollup.conf.prod.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ import vue from 'rollup-plugin-vue'
import commonjs from 'rollup-plugin-commonjs'
import nodeResolve from 'rollup-plugin-node-resolve'

const pkg = require('../package.json')

const version = pkg.version
// const version = '1.0.0-beta.4'

const babelConfig = {
// runtimeHelpers: true,
exclude: 'node_modules/**',
Expand All @@ -14,6 +19,13 @@ const nodeResolveOptions = {
}

export default {
banner: `/*
portal-vue
Version: ${version}
Licence: MIT
(c) Thorsten Lünborg
*/
`,
entry: './src/index.js',
external: ['vue'],
globals: {
Expand Down
12 changes: 12 additions & 0 deletions build/webpack.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,20 @@ const config = {
loader: 'babel-loader',
exclude: path.resolve(__dirname, '../node_modules'),
},
{
test: /\.scss$/,
exclude: /node_modules/,
use: [
'style-loader',
{
loader: 'css-loader',
},
'sass-loader',
],
},
{
test: /\.css$/,
exclude: /node_modules/,
use: [
'style-loader',
{
Expand Down
32 changes: 23 additions & 9 deletions dist/portal-vue.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/portal-vue.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/portal-vue.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

49 changes: 49 additions & 0 deletions docs/docs/caveats.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#Known Caveats

Admittedly, portal-vue does a little bit of trickery to do what it does. With this come some caveats, which are documented below.

## Abstract components

`Portal` and `PortalTarget` are abstract components, which was necessary to make `$parent` work in the slot content as if the portal
did not exist, and keep pointing to the parent component of the portal.

That means they behave a bit differently in two ways:

1. They don't show up in devtools.
2. they don't show up in `$children`

## Server-Side Rendering

When you Vue [Vue's SSR capabilities](https://ssr.vuejs.org), there are some restrictions as well:

1. Order of components

The `PortalTarget` has to appear **after** the **Portal** component in the document flow.
The reason is that Vue renders the result of the first render to a string immediatly - so any changes that are triggered in a `PortalTarget`
after it has been initially rendered will not appear in the HTML document that is sent to the user's browser - but they will appear after hydration,
which will make Vue bail the hydration phase because it didn't find the HTML that it expected, and re-render the whole app.

2. targetEl cannot be a real HTMLElement

See the <a href="#" router-link="/docs/portal#targetel">Portal</a> documentation for details

## Refs

The internal mechanism which sends updates from `Portals` to `PortalTargets` is asynchrnoues at the moment, to avoid some race conditions.

Unfortunately, this means that `$refs` that you might have added to a `Portal's` slot content will not be available on the next Tick, but only the one after that.

So you have to use a workaround for now:
```javascript
// Option 1: Two nested $nextTick calls
this.$nextTick(() => {
this.$nextTick(() => {
console.log(this.$refs.text)
})
})

// Option 2: setTimeout
setTimeout(() => {
console.log(this.$refs.text)
}, 0)
```
22 changes: 18 additions & 4 deletions docs/docs/portal.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,27 @@ Defines the type of tag that should be rendered as a root element.

### `targetEl`

Defines the name of the `<portal>` component that the slot contents should be sent to. This mounts a new instance of the
|Type|Required|Default|
|----|--------|-------|
|`[String, HTMLElement]`|no|none|

<p class="info">
Type HTMElement is not allowed when using Vue SSR.
</p>

Defines the name of the `Portal` component that the slot contents should be sent to. This mounts a new instance of the
<pre>PortalTarget</pre> component.

<p class="warning">
This feature should only be used on elements <strong>outside</strong> of the scope of your Vue app,
This feature should be used on elements <strong>outside</strong> of the scope of your Vue app,
because it replaces the target element while mounting the <pre>PortalVue</pre> instance, which can lead to unwanted
side effects in your Vue App.

You *can* use it inside of the Vue-controlled part of your page, It works for the most part, but be warned that this is not thoroughly tested.
</p>

<p class="warning">

</p>

**Source**
Expand All @@ -114,10 +128,10 @@ Defines the name of the `<portal>` component that the slot contents should be se

```

### `To`
### `to`
|Type|Required|Default|
|----|--------|-------|
|`String`|yes|none|
|`String`|yes, unless `targetEl` prop is provided|a random String|

This defines the name of the `PortalTarget` component that the slot content should be rendered in.

Expand Down
2 changes: 1 addition & 1 deletion docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,5 +142,5 @@ If you use Vue for small bits and pieces on your website, but want to render som
### Tell us about your usecase!

We're sure you will find use cases beyond the ones we mentioned. If you do, please
let us know by opening an issue on <a href="http://github,com/linusborg/portal-vue">Github</a>
let us know by opening an issue on <a href="http://github.com/linusborg/portal-vue">Github</a>
and we will include it here.
64 changes: 32 additions & 32 deletions example/components/App.vue
Original file line number Diff line number Diff line change
@@ -1,45 +1,45 @@
<template>
<div>

<toggle-example />

<target-switch />

<source-switch />

<disabled />

<comp-as-root />

<empty-portal />

<mount-to-external />
<div class="main-container">
<div class="sidebar">
<ul>
<li v-for="target in routes">
<router-link :to="target.path"> {{target.path}}</router-link>
</li>
</ul>
</div>
<div class="viewport">
<router-view />
</div>
</div>

</template>

<script>
import ToggleExample from './toggle/toggle-example.vue'
import TargetSwitch from './target-switch/target-switch.vue'
import SourceSwitch from './source-switch/source-switch.vue'
import Disabled from './disabled'
import CompAsRoot from './comp-as-root/comp-as-root.vue'
import MountToExternal from './mount-to/mount-to-external.vue'
import EmptyPortal from './empty-portal/index.vue'
import { routes } from '../router'
export default {
components: {
ToggleExample,
TargetSwitch,
SourceSwitch,
Disabled,
CompAsRoot,
MountToExternal,
EmptyPortal,
name: 'App',
created () {
this.routes = routes
},
}
</script>

<style>
<style lang="scss">
@import '../styles/variables';
.main-container {
display: flex;
height: 100vh;
}
.sidebar {
padding: 10px;
flex: 0 0 300px;
border-right: 3px solid $vueColor;
}
.viewport {
flex: 1 1 auto;
padding: 25px;
}
</style>
12 changes: 8 additions & 4 deletions example/components/comp-as-root/comp-as-root.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,24 @@
</ul>
</div>
<div class="wrapper">
<div class="item source">

<container type="source">
<portal to="comp-as-root" :disabled="disabled">
<test :test-prop="testProp"></test>
</portal>
</div>
<div class="item destination">
</container>

<container type="destination">
<portal-target name="comp-as-root" />
</div>
</container>

</div>
</div>
</template>

<script>
export default {
name: 'compAsRoot',
data () {
return { disabled: true, testProp: 'Test!!' }
},
Expand Down
Loading

0 comments on commit 86f4439

Please sign in to comment.