GithubHelp home page GithubHelp logo

sdt-uav's Introduction

uav is a JavaScript view library for those who are skeptical of complexity.

  • It's data-bound. You just change your data, and the view updates accordingly.
  • It's simple. The syntax is minimal; there are no dependencies or required toolchains.
  • It's small. Less than 3KB gzipped.

Table of contents:

Hello World

const component = uav.component(
    `<h1>{message}</h1>`,
    { message: 'Hello, world!' }, 
    '#app'
);

// Renders into the #app element:
<h1>Hello, world!</h1>

// After running the following ...
component.message = 'Goodbye, world.';

// ... the HTML automatically updates:
<h1>Goodbye, world.</h1>

Todo App

Click here for a live example

Creating a Component

uav.component(template, model, container, callback)

Arguments:

  • template (String or Element): An HTML template. Must have exactly one root node.
  • model (Object): A view model. Optional.
  • container (String or Element): The element in which to render the component. Optional.
  • callback (Function): A callback that will be passed the component's root node. Optional.

Returns the model, if provided. Otherwise returns the component's DOM node.

Changes to existing properties on the model will trigger an optimized re-render. Only the smallest DOM change possible will occur based on which properties on the model have changed.

Template Expressions

By default, uav expressions use {curly} notation. Any browser-supported JavaScript can be used in an any expression. The result of an expression can be any of the following:

  • String
  • Number
  • Function
  • Boolean
  • DOM element
  • uav component
  • undefined or null (renders an empty string)

You can change the template tag syntax with uav.setTag(). For example, to use {{mustache}} notation, call uav.setTag('{{', '}}') before creating any components.

Content Expressions:

uav.component(
    `<div>This is a content expression: {content}</div>`,
    { content: 'foo' }
);

Attribute Expressions:

Prepend u- to an attribute name to tell uav to parse it.

const component = uav.component(
    `<div u-class="{className} {visible}"></div>`, {
    visible: true,
    className: 'component'
});

// Renders the following:
<div class="component visible"></div>

If an attribute expression evaluates to a boolean, it will render nothing if false, or the property name if true. This makes toggling the "visible" class on the above <div> as easy as component.visble = !component.visible.

Template Loops

Use the u-for attribute to loop over an array as follows:

uav.component(`
    <ul u-for="item in items">
        <li>{item}</li>
    </ul>
`, {
    items: [ 1, 2, 'three' ]
});

This component will render the following:

<ul>
    <li>1</li>
    <li>2</li>
    <li>three</li>
</ul>

You can set a variable for the index of the current item by adding a comma and a variable name to the attribute value:

uav.component(`
    <ul u-for="item, index in items">
        <li class="item-{index}">{item}</li>
    </ul>
`, {
    items: [ 1, 2, 'three' ]
});

Renders:

<ul>
    <li class="item-0">1</li>
    <li class="item-1">2</li>
    <li class="item-2">three</li>
</ul>

Things you may wonder about:

  • Properties of the parent model are available within a loop.
  • Like a component, a loop's content must have one root node.
  • Array methods that modify the array like push and splice will trigger a render.

Events

uav.component(
    `<button u-onclick="{click}">Click me</button>`,
    { click: e => console.log(e) }
);

Like any expression, you can pass data to an event handler:

uav.component(`
    <ul u-for="item in items">
        <li u-onclick="{click(item)}">This is {item}</li>
    </ul>
`, {
    click: item => e => console.log(item),
    items: [ 'foo', 'bar', 'baz' ]
});

Child Components

A component can be rendered into other components.

const child = uav.component(`<h3>{message}</h3>`, {
    message: 'I am a child.'
});

uav.component(`
    <div>
        <h1>This is a component with a child.</h1>
        {child}
    </div>
`, { child });

This will render the following:

<div>
    <h1>This is a component with a child.</h1>
    <h3>I am a child.</h3>
</div>

Passing Data to Children

const child = data => uav.component(
    `<em>{data}</em>`,
    { data }
);

uav.component(`
    <div>
        This component passes data to its child.
        {child}
    </div>
`, {
    child: child('This is passed from parent to child.')
});

The parent component above passes data when the model is created. You could just as easily pass the data through the template:

uav.component(`
    <div>
        This component passes data to its child.
        {child('This is passed from parent to child.')}
    </div>
`, { child });

Either way, it will render the following:

<div>
    This component passes data to its child.
    <em>This is passed from parent to child.</em>
</div>

uav supports swapping child components on the fly. For example, you could call component.child = someOtherComponent and the view will update accordingly.

Creating a Model

If you want to create a view model before associating it with a template, use uav.model. This can come in handy when a model refers to itself at render time.

const model = uav.model({
    blue: true,
    redOrBlue: () => model.blue ? 'blue' : 'red'
});

const component = uav.component(
    '<div class="{redOrBlue()}"></div>', 
    model
);

Binding HTML

To render an HTML string as a DOM element, simply treat the string as the template of a child component by passing it through uav.component().

uav.component(
    `<div>{html}</div>`, {
    html: uav.component('<script>location="https://en.wikipedia.org/wiki/Cross-site_scripting"</script>')
});

Boolean Attributes

Use the u-attr attribute to bind a boolean attribute on an element.

uav.component(
    `<input type="text" u-attr="{disabled}">`,
    { disabled: true }
);

// Renders:
<input type="text" disabled>

Just because these are called boolean attributes doesn't mean they have to bound to a boolean value. Here's an example that uses a string:

uav.component(
    `<input type="text" u-attr="{'aria-' + ariaProp}">`,
    { ariaProp: 'hidden' }
);

// Renders:
<input type="text" aria-hidden>

DOM Access

Elements can be accessed directly by passing a selector to the uav or uav.all functions.

Access the first matched element:

uav('.item').classList.toggle('visible');

Run a callback on all matched elements:

uav('.item', item => item.classList.toggle('visible'));

Get an array of all matched elements:

uav.all('.item').forEach(item => item.classList.toggle('visible'));

Two Way Data Binding

Use the u-bind attribute to two-way bind an input, select, or textarea to a model property. Whenever the user changes the value of the input, the property will be updated. Whenever you programatically change the property, the input's value will be updated.

uav.component(
    `<input type="text" u-bind="value"/>`,
    { value: 'hi there' }
);

Checkboxes can be bound to arrays or booleans.

uav.component(`
    <form>
        <input type="checkbox" u-bind="items" value="1"> 1
        <input type="checkbox" u-bind="items" value="2"> 2
        <input type="checkbox" u-bind="items" value="3"> 3
    </form>`, {
    items: [1, 2]
});

See a live demo of two way binding

Script Tag Templates

It is recommended to write your templates using ES6 template strings because A) it provides the opportunity to interpolate data without binding it, using the native template ${variable} syntax, and B) it's easier to remove unnecessary whitespace in your templates during a build step. That said, you can also define templates within your HTML, and pass a DOM element instead of a template string to uav.component:

<div id="app"></div>
<script type="template" id="template">
    <h1>{content}</h1>
</script>
<script>
const template = uav('#template');

uav.component(template, {
    content: 'Hello, world!'
}, '#app');
</script>

Performance Tips

Only bind data when you have to

Avoid putting any data on the model that doesn't need to be bound to the DOM. If a particular value will never change, or changes to it don't need to update the DOM, just use a regular ES6 template variable to reference it (put a dollar sign in front of the expression).

const wontChange = 'hi!';

uav.component(`
    <div>
        <p>${wontChange}</p>
        <p>{willChange}</p>
    </div>
`, {
    willChange: 'loading...'
})

Unbind any DOM nodes you've manually detached

When uav updates the DOM as a result of a change to a model, it automatically removes any bindings to DOM nodes that have been removed or replaced. However, if for some reason you manually remove or replace a bound DOM node, you can clean up any bindings associated with it by calling uav.unbind(<Element>).

Collapsing Whitespace

Using multiline template strings creates unnecessary whitespace in your JavaScript files. To collapse this whitespace, add a step like this to your build process:

tr -s " " < dist/bundle.js > dist/tmp && mv dist/tmp dist/bundle.js

Browser Compatibility

Modern browsers and IE9+.

sdt-uav's People

Contributors

mike-unearth avatar dependabot[bot] avatar amysunearth avatar amyprocore avatar mgrahamjo avatar pat-lasswell avatar rob-unearth avatar braden-unearth avatar

Watchers

Alan Stebbens avatar Pablo Cordero avatar Benjamin Halsted avatar Zach Gross avatar Alex Golikov avatar Illia Dryha avatar Oleksandr Moskovka avatar Andrew Callahan avatar Jennifer Dixon avatar Jeremy Lund avatar Claudio Sergio Forain, Jr. avatar James Cloos avatar Jonathan Greene avatar Lauren Brandstein avatar irving.gomez avatar Jed Needle avatar Tom George avatar Jay Yang avatar David Martin avatar Jake Sanders avatar mmukarram avatar Bill Hancock avatar Michael Stephens avatar Klaus Nji avatar Bharath Hariharan avatar Luis de Haro avatar Uday Sharma avatar Marek Piasecki avatar Oleksandr Dervish avatar Louis Mejia avatar Kim Hin avatar David avatar Ryan Smith avatar Brett Cassedy avatar Yann Lebreton avatar Julian Claudino avatar Pierce Khougaz avatar Andrés avatar Jessica avatar Antonio Samay avatar  avatar Petro avatar Lydia Hara avatar Barnaby Falls avatar Brian Imbriani avatar Tanya Contreras avatar Henry Yogman  avatar Julian Gee avatar Ashton Ramezani Doulabi avatar Abraham Fathman avatar Ken Mundy avatar Josh Mun avatar Edith Au avatar Emily Lee avatar Oleh Kozlovskyi avatar Brian Smith avatar Molly Brown avatar Michelline Tran avatar Surabhya Aryal avatar Jerome Moore avatar Phil Custer avatar Ari Romero G avatar Anatolii Yaropovets avatar Micheal Hannan avatar Theo Rollin Anderson avatar Igor avatar Jayro Salgado avatar  avatar Yogev Finegouz avatar Petro Nikolaichuk avatar MasonB avatar Andrew Young avatar Graham Wren avatar Alejandro Gómez Alanís avatar Daniel Reinhart avatar Kellie Persson avatar Yurii Halapup avatar Rachel Arkebauer avatar  avatar Sarah Pinkelman avatar Chetan Kale avatar Hisham Maged avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.