babel-preset-react-vue-directives

0.3.4 • Public • Published

babel-preset-react-vue-directives

Build Status codecov npm version

Enables the usage of Vue.js directives in React.

Refer to the Vue.js docs for more information on directives.

Table of Contents:

Installation

$ npm install babel-preset-react-vue-directives

Usage

Note: babel-preset-react-vue-directives must be placed after any preset that transforms ES6 classes, such as babel-preset-env or babel-preset-es2015.

Via .babelrc (Recommended)

.babelrc

{
  "presets": ["react", "react-vue-directives"]
}

Via CLI

$ babel --presets react,react-vue-directives script.js

Via Node API

require("babel-core").transform("code", {
  presets: ["react", "react-vue-directives"]
});

Changes from Vue.js directives:

Please note the following differences from Vue.js:

  • All directives use camelCase instead of kebab-case.
  • Directive modifiers use $ as a separator rather than : and ..
  • vOn only supports named functions.
  • vOn does not support the self and once event modifiers.
  • vModel supports binding to nested properties on state - see below for an example.

String literals vs expressions

  • vFor only supports string literals in the formats described below.
  • vIf and vShow support both curly brace expressions and string literals. String literals can only contain identifiers.
  • vModel and vOn support both string literals and curly brace expressions containing an identifier. For vModel, the identifier should be the name of a property on this.state; for vOn it should be the name of a class method (with this omitted). If using a nested property for vModel, only a string literal is supported.

Supported directives:

  • vFor
  • vIf
  • vElseIf
  • vElse
  • vShow
  • vModel
  • vOn

vFor

Since this preset transforms vFor into a .map call, a key property is required for the element. For arrays, if you do not provide a key, the array index will be used. For objects, the object's keys are used automatically.

As in Vue.js, the following forms are supported:

Arrays:

  • element in arr
  • element of arr
  • (element, index) in arr
  • (element, index) of arr

Example:

<ul>
    <li vFor="item of items">{item}</li>
</ul>

With key explicitly provided:

<ul>
    <li vFor="item of items" key={item.id}>{item}</li>
</ul>

Objects:

  • value in obj
  • value of obj
  • (value, key) in obj
  • (value, key) of obj
  • (value, key, index) in obj
  • (value, key, index) of obj

Please note that of and in are functionally identical and do not follow the behavior of their JavaScript equivalents.

As in Vue.js, when using custom React elements, you will need to explicitly define values for the props generated by vFor, with the exception of key, which will automatically be provided to each element.

Example:

<MyComponent
    vFor="(value, key, index) in obj"
    value={value}
    index={value} />

vIf

Conditionally render components based on a condition.

As noted above, vIf accepts both curly brace expressions and string literals. String literals can only contain identifiers.

Example:

<div>
    <div vIf="condition">
        Displays if condition is true
    </div>
    <div vElseIf={value > 5}>
        Displays if value > 5
    </div>
    <div vElse>
        Displays if neither of the previous conditions is true
    </div>
<div>

vShow

Example:

Sets the display property of the element to none if the condition is false.

As with vIf, vShow accepts both curly brace expressions and string literals. String literals can only contain identifiers.

If the element already has a display property, it will be used when the condition is true.

<div vShow="condition">Shows when condition is true</div>
<div vShow="condition" style={{display: 'block'}}>
    Has display: none when the condition is false, display: block when it is true
</div>

vModel

Creates a two-way binding between a property on this.state and the value of a form element. vModel can be used on <input>, <textarea>, and <select> elements.

Requires a class component.

Example:

<input vModel="inputValue" />

The <input /> element will become a controlled element, with its value linked to this.state.inputValue. When the input changes, this.setState({ inputValue: event.target.value }) will be called.

vModel also supports binding to nested properties on this.state:

import React, { Component } from 'react';
 
export default class NestedStateComponent extends component {
    state = {
        a: {
            b: {
                c: {
                    inputValue: ''
                }
            }
        }
    };
 
    render() {
        return (
            <input vModel="a.b.c.inputValue" />
        );
    }
}

The output code will use Object.assign as needed when calling this.setState to update the bound property. Please note that when using a nested property, only a string literal is supported; a curly brace expression will not work.

vModel supports the lazy, trim, and number modifiers. As with vOn, $ should be used as a separator rather than .:

<input vModel$lazy$trim$number="value" />

vOn

Adds event handlers.

Requires a class component.

Since : and . cannot be used in JSX attribute names, $ must be substituted for both.

For key modifiers, the separator should be omitted:

Vue.js:

<input v-on:keyup.13.prevent="submit" />

babel-preset-react-vue-directives:

<input vOn$keyup13$prevent="submit" />

The value of the vOn attribute must be the name of a method found on this or one of its properties (can be nested). Omit this when specifiying the function.

The following example from the Vue.js docs will not work:

<button v-on$click="counter += 1">
    Add 1
</button>

The function will be called with the triggered event.

When using a method found on this.props, both of the following formats will work:

<button vOn$click="props.handleClick" />
<button vOn$click={props.handleClick} />

Both will use this.props.handleClick with the triggered event.

import React, { Component } from 'react';
export default class Counter extends Component {
    state = {
        counter: 0
    };
    
    increment = event => this.setState({ counter: this.state.counter + 1});
    
    render() {
        return (
            <div>
                <button vOn$click="increment">Increment</button>
                <button vOn$click={event => this.setState({ counter: this.state.counter + 1 })}>Increment</button>
            </div>
        );
    }
}

Development

Test

npm test
npm run test:watch

Lint

npm run lint

Build

npm run build

Readme

Keywords

Package Sidebar

Install

npm i babel-preset-react-vue-directives

Weekly Downloads

8

Version

0.3.4

License

none

Last publish

Collaborators

  • aardito2