Code your own vue: methods and events
Tags: javascript, vue, webdev, tutorial
Published: 2021-10-29 21:11:29

---
title: "Code your own vue: methods and events"
published: true
description: "create your own vue, make your own vue"
tags: javascript, vuejs, webdev, tutorial
---

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

```html
<div id="app">
	<h1>{{ msg }}</h1>
	<button onclick="hi()">Click me</button>
</div>
```

```js
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";
```

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

```html
<div id="app">
	<h1>{{ msg }}</h1>
	<button v-on:click="hi">Click me</button>
</div>
```

```js
const vm = new Vue({
	el: "#app",
	data: {
		msg: "Hello",
	},
	methods: {
		hi() {
			this.msg = this.msg === "Hello" ? "World" : "Hello";
		},
	},
});
```

### Implementing methods

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

```js
function walkMethods(vue, methods) {
  for (const key in methods) {
    vue[key] = methods[key];
  }
}
```

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

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

    // Create

    // Mount
```

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.

```js
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;
}
```

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

```js
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));
}
```

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

```js
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);
  };
}
```

Example of the rendering:
```html
<!-- 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>
```

### 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](https://dev.to/ghaerdi/code-your-own-vue-50mg)