Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vue / Knobs - optimize on force render #4773

Merged
merged 13 commits into from
Nov 20, 2018
2 changes: 1 addition & 1 deletion app/react/src/client/preview/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export default function renderMain({
}

// We need to unmount the existing set of components in the DOM node.
// Otherwise, React may not recrease instances for every story run.
// Otherwise, React may not recreate instances for every story run.
// This could leads to issues like below:
// https://github.com/storybooks/react-storybook/issues/81
// But forceRender means that it's the same story, so we want too keep the state in that case.
Expand Down
54 changes: 44 additions & 10 deletions app/vue/src/client/preview/render.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,49 @@
import { stripIndents } from 'common-tags';
import Vue from 'vue';

let app = null;
let root = null;

function renderRoot(options) {
if (app) app.$destroy();
function updateComponent(component) {
const [lastStory] = root.$children;

app = new Vue(options);
if (!lastStory) {
return false;
}

if (typeof component.data !== 'function') {
return false;
}

const data = component.data();

if (!data) {
return false;
}

Object.entries(data).forEach(([key, value]) => {
lastStory[key] = value;
});

lastStory.$forceUpdate();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe this will be necessary since Vue as observers for all values of component internal states ; but that won't kill performances either for most of the case, so it's ok to leave it if you feel it's safer.


return true;
}

function renderRoot({ forceRender, component }) {
if (root) {
if (forceRender === true && updateComponent(component)) {
return;
}

root.$destroy();
}

root = new Vue({
el: '#root',
render(h) {
return h('div', { attrs: { id: 'root' } }, [h(component)]);
},
});
}

export default function render({
Expand All @@ -16,6 +53,7 @@ export default function render({
showMain,
showError,
showException,
forceRender,
}) {
Vue.config.errorHandler = showException;

Expand All @@ -33,10 +71,6 @@ export default function render({
}

showMain();
renderRoot({
el: '#root',
render(h) {
return h('div', { attrs: { id: 'root' } }, [h(component)]);
},
});

renderRoot({ forceRender, component });
}
23 changes: 23 additions & 0 deletions examples/vue-kitchen-sink/src/stories/SimpleKnobExample.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<template>
<div @click="i++">I am {{ name }} and I'm {{ age }} years old. Inner State Counter {{ i }}</div>
</template>

<script>
export default {
props: {
name: String,
age: Number,
},
data() {
return {
i: 40,
};
},
created() {
console.log('created');
},
destroyed() {
console.log('destroyed');
},
}
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ exports[`Storyshots Addon|Knobs All knobs 1`] = `

exports[`Storyshots Addon|Knobs Simple 1`] = `
<div>
I am John Doe and I'm 44 years old.
I am John Doe and I'm 44 years old. Inner State Counter 40
</div>
`;

Expand Down
9 changes: 7 additions & 2 deletions examples/vue-kitchen-sink/src/stories/addon-knobs.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,20 @@ import {
button,
} from '@storybook/addon-knobs';

import SimpleKnobExample from './SimpleKnobExample.vue';

storiesOf('Addon|Knobs', module)
.addDecorator(withKnobs)
.add('Simple', () => {
const name = text('Name', 'John Doe');
const age = number('Age', 44);
const content = `I am ${name} and I'm ${age} years old.`;

return {
template: `<div>${content}</div>`,
components: { SimpleKnobExample },
template: '<simple-knob-example :name="name" :age="age" />',
data() {
return { name, age };
},
};
})
.add('All knobs', () => {
Expand Down