Skip to content

Instantly share code, notes, and snippets.

@mattattui
Last active August 29, 2017 13:28
Show Gist options
  • Save mattattui/f7fdbe675827ae71fa461c372088de91 to your computer and use it in GitHub Desktop.
Save mattattui/f7fdbe675827ae71fa461c372088de91 to your computer and use it in GitHub Desktop.
I suck at Vue 2?

How to get this running:

vue init webpack-simple mytest
cd mytest
npm install # or yarn, whatever

Then add these two files to the src/ folder, (overwriting the original App.vue)

How to replicate the problem

  • Run npm run dev to start the dev environment and open a browser.
  • Swap blocks around using the up/down arrows, note how everything is fine.
  • Add a new block, and set its content (e.g. "4").
  • Add a second new block. Notice that its content appears the same as the previous block, but its data is correctly blank.
  • Move the top block down one, notice it becomes empty. The data looks fine here.
  • Move it back up. Once again the data looks fine, but the DOM displays the content from the previous block (e.g. "4")
  • Change the top block's content to 5, then move it down. The top two blocks display "5" (but the data is ok). Move the 2nd block back up and everything looks fine.
<template>
<div id="app">
<button @click.prevent="newBlock({type:'rich',data:''})">Add an editor</button>
<div v-for="(block, idx) in blocks" :key="`blocks-${idx}`" class="block">
<a class="handle handle--disabled" v-if="idx === 0">▲</a>
<a class="handle" v-if="idx !== 0" @click.prevent="swapBlock(idx - 1)">▲</a>
<a class="handle" v-if="idx !== (blocks.length - 1)" @click.prevent="swapBlock(idx)">▼</a>
<a class="handle handle--disabled" v-if="idx === (blocks.length - 1)">▼</a>
<block-rich v-model="blocks[idx].data"></block-rich>
</div>
<pre>{{ blockJson }}</pre>
</div>
</template>
<script>
import BlockRich from './TextBlock.vue';
export default {
data () {
return {
blocks: [
{ type: 'rich', data: '1' },
{ type: 'rich', data: '2' },
{ type: 'rich', data: '3' },
],
};
},
computed: {
blockJson() {
return JSON.stringify(this.blocks);
}
},
methods: {
swapBlock(index) {
if (this.blocks[index] === undefined || this.blocks[index + 1] === undefined) {
return;
}
this.blocks.splice(index, 2, this.blocks[index + 1], this.blocks[index]);
},
newBlock(data) {
this.blocks.splice(0, 0, Object.assign({}, data));
},
},
components: {
BlockRich,
},
};
</script>
<style>
body {
font-family: Helvetica, sans-serif;
}
.handle {
font-size: 1.5rem;
text-align: center;
}
.handle--disabled {
opacity: 0.5;
}
.block {
margin-bottom: 2em;
}
</style>
<template>
<div>
<textarea @input="$emit('input', $event.target.value)">{{ value }}</textarea>
</div>
</template>
<script>
export default {
props: {
value: {
required: true,
type: String,
default() {
return '';
},
},
},
}
</script>
@mattattui
Copy link
Author

For anyone stumbling across this, DO NOT USE IT, it's a bug report test case.
The bug was related to using the array index as the key -- that led to DOM being improperly reused, which caused some freaky errors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment