Vue.js tips and tricks

Vue CLI

npm install -g @vue/cli @vue/cli-service-global
vue ui
vue create my-exaple-project
vue add eslint
# eslint => @vue/eslint => @vue/cli-plugin-eslint
vue add cli-plugin-eslint
# installs and invokes vue-cli-plugin-apollo
vue add apollo
Plugin Link
browser-extension https://npm.im/vue-cli-plugin-browser-extension
Vue Composition API https://npm.im/@vue/composition-api

Bootstrap table style not working?

Use <thead> and <tbody>.

v-model in Components (+ Composition API)

In browser

Vue.use(vueCompositionApi.default);
const {computed} = vueCompositionApi

HTML:

<div id="app">
  <foo v-model="fooVal"></foo>
    <foo :value="fooVal" @input="fooVal = $event"></foo>

  <bar v-model="barVal"></bar>
    <bar :lorem="barVal" @ipsum="barVal = $event"></bar>

  <lol :x="fooVal" :y="barVal" v-model="lolVal"></lol>
    <lol :x="fooVal" :y="barVal" :z="lolVal" @input="lolVal = $event"></lol>
</div>

Vue.js 2 (test)

Vue.component("foo", {
  template: `<button @click="increment">{{ value }}</button>`,
  props: {
    value: Number
  },
  methods: {
    increment() {
      this.$emit("input", this.value + 1);
    }
  }
});

Vue.component("bar", {
  template: `<button @click="increment">{{ lorem }}</button>`,
  props: {
    lorem: Number
  },
  model: {
    prop: "lorem",
    event: "ipsum"
  },
  methods: {
    increment() {
      this.$emit("ipsum", this.lorem * 2);
    }
  }
});

Vue.component("lol", {
  template: `<button @click="sum">{{ z }}</button>`,
  props: {
    x: Number,
    y: Number,
    z: Number
  },
  model: {
    prop: "z"
  },
  methods: {
    sum() {
      this.$emit("input", this.x + this.y);
    }
  }
});

new Vue({
  el: "#app",
  data: {
    fooVal: 1,
    barVal: 1,
    lolVal: 0
  }
});

Vue.js 3 / Composition API (test)

// vueCompositionApi => Vue.js 2.x plugin

Vue.use(vueCompositionApi.default);

Vue.component("foo", {
  template: `<button @click="increment">{{ value }}</button>`,
  props: {
    value: Number
  },
  setup: (props, context) => ({
    increment: () => context.emit("input", props.value + 1)
  })
});

Vue.component("bar", {
  template: `<button @click="increment">{{ lorem }}</button>`,
  props: {
    lorem: Number
  },
  model: {
    prop: "lorem",
    event: "ipsum"
  },
  setup: (props, context) => ({
    increment: () => context.emit("ipsum", props.lorem * 2)
  })
});

Vue.component("lol", {
  template: `<button @click="sum">{{ z }}</button>`,
  props: {
    x: Number,
    y: Number,
    z: Number
  },
  model: {
    prop: "z"
  },
  setup: (props, context) => ({
    sum: () => context.emit("input", props.x + props.y)
  })
});

new Vue({
  el: "#app",
  data: {
    fooVal: 1,
    barVal: 1,
    lolVal: 0
  }
});

Sources:

Init with data from dataset

export default {
    data() {
        return {
            id: this['$root']['$el']['dataset']['id'],
        };
    },
};

Version 2:

index.html:

    <div id="app" data-id="123"></div>

index.js:

    (function (el) {

        new Vue({
            el,
            render: h => h(Module),
            data: () => Object.assign({}, el.dataset) ,
        });

    })(document.getElementById('app'));

Module.vue:

    export default {
        name: 'Module',
        data() {
            return {
                id: this.$parent.id,
            };
        },
    };

Version 3:

    (function (el) {

        new Vue({
            el: el,
            render: h => h(Module),
            propsData: {
                ...el.dataset
            }
        });

    })(document.getElementById('app'));

Version 4:

(function (el) {
    new Vue({el, render: h => h(Module, {props: {...el.dataset}})});
})(document.getElementById('app'));
// Module.vue
export default {
  props: {
    id: {
      type: String,
      required: true,
      validator: v => /^\d+$/.test(v),
    },
  },
};

Version 5 (Vue 3.x) [example]:

<div id="foo">EXAMPLE #1</div>
<div id="bar" data-firstname="Evan" data-lastname="You">EXAMPLE #2</div>
function initApp(root) {
  Vue.createApp({
    props: {
      firstname: {
        type: String,
        default: 'John'
      },
      lastname: {
        type: String,
        default: 'Doe'
      }
    },
    template: '{{ firstname }} {{ lastname }}'
  }, root.dataset).mount(root);
}

initApp(document.getElementById('foo'));
initApp(document.getElementById('bar'));

Result:

<div id="foo">John Doe</div>
<div id="bar" data-firstname="Evan" data-lastname="You">Evan You</div>