DEV Community

Cover image for Smell jQuery like Vue, this small plugin is mgical!
frustigor
frustigor

Posted on • Edited on

Smell jQuery like Vue, this small plugin is mgical!

Hi, I am back for a long time.

Today I will introduce a jQuery plugin written by me. Yes, I did not give up jQuery, because many old systems are using jQuery and not be able to refactor and even need to support IE8. It is a strong UI driven library, even though react, vue cover the sky today. I love react too, but I thought, react is a UI library too, what is the difference? Reactive!!! React is a reactive UI libaray, but jQuery is not. Can I make jQuery a reactive library? Here is my answer.

![](https://github.com/tangshuang/jqvm/raw/master/jqvm.png)
https://github.com/tangshuang/jqvm

A Quick Glance

I wrote the small plugin for jQuery, which costs hundreds lines, called jQvm (jQuery view model) following MVVM pattern. If you are familiar with jQuery, you will use it as a jQuery plugin as your familiar way. If you need to refactor your old jQuery system, maybe jQvm is an option.

Now, let's have a look into it:

<template id="app">
  <span>{{name}}</span>
  <span>{{age}}</span>
  <button jq-on="click:grow">Grow</button>
</template>

<script>
  $('#app')
      .vm({ name: 'tom', age: 10 })
      .fn('grow', state => state.age ++)
      .mount()
</script>
Enter fullscreen mode Exit fullscreen mode

Yes, a template section and a jQuery plugin usage, done!
To import the plugin, you can use CDN:

<script src="https://unpkg.com/jquery/dist/jquery.min.js"></script>
<script src="https://unpkg.com/jqvm/dist/jqvm.min.js"></script>
Enter fullscreen mode Exit fullscreen mode

You do not need to compile or build the code, it is so lightweight that you can use it in any website which even is out of date.

(Notice, jQvm is based on jQuery 3.6.x, and use Object.defineProperty to implement reactive system, you may need some polyfill to resolve warnings in old browsers.)

Features

Ok, I know you are doubt with the features in jqvm which vue provides but not in jqvm. Let's take a review:

Mutable Reactive

In vue, you can modify properties on this to trigger rerenderer, it is the same in jQvm.

$(...).vm(...)
  .fn('change', state => e => state.value = e.target.value)
Enter fullscreen mode Exit fullscreen mode

We directly change state to trigger rerenderer.

Conditional Render

In vue, you can use v-if to control the visibility of a node, you can use jq-if in jQvm.

<div jq-if="age > 10">I am older than 10.</div>
Enter fullscreen mode Exit fullscreen mode

Loop Render

In vue, you use v-for to render loop set, you can use jq-repeat in jQvm.

<div jq-repeat="value,index in data traceby value.id">
  <span>{{index + 1}}</span>
  <span>{{value.name}}</span>
  <span>{{value.time}}</span>
</div>
Enter fullscreen mode Exit fullscreen mode

Two Way Binding

In vue, you use v-model to bind a form component value with data, in jQvm you can use jq-bind.

<input jq-bind="age" />
Enter fullscreen mode Exit fullscreen mode

Component

In vue, you can use another vue component in current one. However, in jQvm, it is different. There is a concept View in jQvm, a view is a instance created by .vm, for example:

const myComp = $(...)
  .vm(() => ...) // notice here, you should better use a function to return initState
  .fn(...)
  .on(...)
Enter fullscreen mode Exit fullscreen mode

Notice that, I did not call .mount() at the end, this view is an alone View which is not be used in our system. Now we can use it as a component in our current view.

<div id="app">
  <my-comp></my-comp>
</div>

<script>
$('#app').vm(...)
  .component('my-comp', myComp)
  .mount()
</script>
Enter fullscreen mode Exit fullscreen mode

With props, you can pass and receive events:

<div id="app">
  <my-comp type="search" :count="count" @change="handleChange"></my-comp>
</div>

<script>
const myComp = $(`
  <template>
    <i class="icon icon-{{type}}"></i>
    <span>{{count}}</span>
    <button>plus</button>
  </template>
`)
  .vm(() => ({ count: 0, type: 'text' }))
  .on('click', 'button', function(state) {
    this.emit('change', state.count + 1)
  })
$('#app').vm({ count: 4 })
  .component('my-comp', myComp)
  .fn('handleChange', state => count => state.count = count)
  .mount()
</script>
Enter fullscreen mode Exit fullscreen mode

The previous code give type :count and @change props to my-comp.

More

Yeap! Isn't is like vue? You can explore more features here.

Why I wrote it (why not vue directly)? Because in some case, I do not need a heavyweight library/framework to enhance my application especially the old systems which written by jquery. And in my spare time, I write some small tools and can use jQvm so quickly to implement the UI.

If you think it is a good idea, please give a star on github here.

Bye~

Top comments (0)