DEV Community

Gil Rudolf Härdi
Gil Rudolf Härdi

Posted on

3 1

Code your own vue: methods and events

Hi everyone, It's been a while since the last chapter of 'Code your own vue', in the last post we saw how to do our own lifecycle hooks, today we going to see how to code methods and events.
If you followed atleast the first chapter you can use methods and events in this way

<div id="app">
    <h1>{{ msg }}</h1>
    <button onclick="hi()">Click me</button>
</div>
Enter fullscreen mode Exit fullscreen mode
const vm = new Vue({
    el: "#app",
    data: {
        msg: "Hello",
    },
});

// toggle vm.msg between 'Hello' and "World"
const hi = () => vm.msg = vm.msg === "Hello" ? "World" : "Hello";
Enter fullscreen mode Exit fullscreen mode

But today we going to programm this in the vue way:

<div id="app">
    <h1>{{ msg }}</h1>
    <button v-on:click="hi">Click me</button>
</div>
Enter fullscreen mode Exit fullscreen mode
const vm = new Vue({
    el: "#app",
    data: {
        msg: "Hello",
    },
    methods: {
        hi() {
            this.msg = this.msg === "Hello" ? "World" : "Hello";
        },
    },
});
Enter fullscreen mode Exit fullscreen mode

Implementing methods

First we can define a function that will read the methods and mix all those methods with our vue instance. Like this:

function walkMethods(vue, methods) {
  for (const key in methods) {
    vue[key] = methods[key];
  }
}
Enter fullscreen mode Exit fullscreen mode

Then call the function in the constructor before the created lifecycle hook.

class Vue {
  constructor({ methods }) {
    // Before Create
    walkMethods(this, methods);

    // Create

    // Mount
Enter fullscreen mode Exit fullscreen mode

And now you should be able to call this.[method] in the vm or vm.[method] outside of vue.

Implementing events

Implementing events is more dificult. Javascript Dom cannot get attributes with specials characters like @click or v-on:click. So we need to handle that, for that I decided read the innerHTML and add vue-event=[event] and vue-event-method=[method] as attribute when a @[event] or v-on:[event] is found in a element. Other thing to consider is editing the innerHTML, if we add a event and edit the innerHTML the element will lose all events, for this reason we need to edit the innerHTML before adding any event.

const regex = {
  // regex to get v-on:[event]="[method]" and @[event]="[method]"
  vueOn: /(@|v-on:)\w+="([0-z.?]+)\(?\)?"/,
};

// replace v-on:[event]=[method] to selectionable attributes
function replaceAttributes(el) {
  el.innerHTML = el.innerHTML.replace(
    new RegExp(regex.vueOn, "g"),
    (match) => {
      // get event and method as [event]=[method]
      // from @[event]=[method] or v-on:[event]=[method]
      const attr = /@/.test(match) ? match.slice(1) : match.split(":")[1];
      // get event and method without quotes
      const [ event, method ] = attr.replace(/"/g, "").split("=");
      return `vue-event=${event} vue-event-method=${method}`;
    }
  );

  return el;
}
Enter fullscreen mode Exit fullscreen mode

After that we need a function that read all element with the vue-event attribute, add the event listener and remove all those attributes.

function addEvents(vue) {
  vue.$el.querySelectorAll("[vue-event]").forEach((el) => {
    const event = el.getAttribute("vue-event");
    const method = el.getAttribute("vue-event-method");

    el.addEventListener(event, vue[method].bind(vue.$data));
    clearElement(el, ["vue-event", "vue-event-method"])
  });
}

function clearElement(el, attributes) {
  attributes.forEach(attr => el.removeAttribute(attr));
}
Enter fullscreen mode Exit fullscreen mode

And finally, we need to use those functions on our render function.

const regex = {
  mostach: /\{\{((?:.|\r?\n)+?)\}\}/,
};

function renderVue(vue) {
  const originalTemplate = replaceAttributes(vue.$el.cloneNode(true));

  return () => {
    const { $data } = vue;

    vue.$el.innerHTML = originalTemplate.innerHTML.replace(
      new RegExp(regex.mostach, "g"),
      (_, val) => $data[val.trim()]
    );

    addEvents(vue);
  };
}
Enter fullscreen mode Exit fullscreen mode

Example of the rendering:

<!-- Original -->
<button v-on:click="foo">I'm a button<button>

<!-- After replaceAttributes -->
<button vue-event="click" vue-event-method="foo">I'm a button<button>

<!-- After rendering -->
<button>I'm a button<button>
Enter fullscreen mode Exit fullscreen mode

Conclusion

And we are finally done, adding methods to vue is really easy but code the vue events can be a headache.

You can see more about code your own vue here

AWS GenAI LIVE image

Real challenges. Real solutions. Real talk.

From technical discussions to philosophical debates, AWS and AWS Partners examine the impact and evolution of gen AI.

Learn more

Top comments (1)

Collapse
 
ghaerdi profile image
Gil Rudolf Härdi

If you have readed the last two post about this series, just let you know that I did a little update to both post, mostly code.

nextjs tutorial video

Youtube Tutorial Series 📺

So you built a Next.js app, but you need a clear view of the entire operation flow to be able to identify performance bottlenecks before you launch. But how do you get started? Get the essentials on tracing for Next.js from @nikolovlazar in this video series 👀

Watch the Youtube series

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay