Intro
Raccoon is an experimental project inspired by Vue. It's a component based reactive framework with basic functionality such as, reactivity, template engine, computed functions, dom-events, etc.
Raccoon is an experimental project inspired by Vue. It's a component based reactive framework with basic functionality such as, reactivity, template engine, computed functions, dom-events, etc.
Install Raccoon [From where?], Import it use it.
<div id="demo-component-2">
<button @click="proxy.price += 10">Increase price</button>
<button @click="proxy.quantity += 1">Increase quantity</button>
<button @click="funcs.addOnePercentTax()">Add 1% tax</button>
<div>Price: {{price}}</div>
<div>Quantity: {{quantity}}</div>
<div>Tax: {{taxHuman}}</div>
<div>Sum (inc tax): {{sum}}</div>
</div>
import { Raccoon } from "raccoon-js-framework";
const componentEl = document.getElementById("demo-component-2");
const { proxy, compute, funcs } = new Raccoon(componentEl);
proxy.price = 1;
proxy.quantity = 15;
proxy.tax = 0.01;
compute.sum = () => (proxy.price * proxy.quantity) + (100 * proxy.tax);
compute.taxHuman = () => `${100 * proxy.tax}%`
funcs.addOnePercentTax = () => proxy.tax += 0.01
<div id="component">
<div id="valueA">{{a}}</div>
<div id="valueB">{{b}}</div>
<div id="sum">{{sum}}</div>
</div>
proxy.a = 1;
proxy.b = 2;
compute.sum = () => `$Sum: ${proxy.a + proxy.b}`;
Output
1
2
Sum: 3
{proxy.name} or {just name} The proxy does the heavy lifting when it comes to the reactivities. It's basically an object with properties that will update the dom every-time a property changes.
proxy.a = 1;
proxy.b = 2;
<p>a = {proxy.a}, b = {proxy.b}</p>
Output: a = 1, b = 2
TODO: Explain when proxy.a is needed and when it's ok to use just a.
compute.sum = () => proxy.a + proxy.b;
proxy.a = 12;
proxy.b = 12;
Output the computed sum
The sum of a and b is: <strong>{sum}</strong>
Sum in this case will be 24
This creates a button which counts up proxy.a by one on click using a function.
<div id="component">
<button id="button" @click='funcs.myFn(proxy.a)'>Count Up</button>
</div>
The funcs-function takes 2 arguments, the proxy which is magically applied by the framework and the value which in this case is passed as an argument from the @click event. In this example we are getting the value from proxy.a and then increase it by one and save it back.
proxy.a = 1;
// The first argument will always be the proxy which is applied by the framework.
funcs.myFn = (proxy, value) => {
proxy.a = Number(value) + 1;
}
This could be used with funcs too
<div id="component">
<button id="button" @click='proxy.a += 10'>Count Up</button>
</div>
proxy.a = 0
This could be used with funcs too
<div id="component">
<label for="price">Price</label>
<input type="number" @input="proxy.price = Number(event.target.value)" :value="proxy.price">
</div>
proxy.price = 1;
<div id="component">
<label for="price">Price</label>
<input type="number" @change="proxy.price = Number(event.target.value)" :value="proxy.price">
</div>
proxy.price = 1;
<div id="component">
<label for="price">Price</label>
<input type="number" @keyup="proxy.price = Number(event.target.value)" :value="proxy.price">
</div>
proxy.price = 1;
<div id="component">
<label for="price">Price</label>
<input type="number" @keydown="proxy.price = Number(event.target.value)" :value="proxy.price">
</div>
proxy.price = 1;
<div id="component">
<div r-for="name of names">
<article class="card">
<span class="text-red">{{ name }}<span>
</article>
</div>
</div>
An inner wrapper is required for the rendering precess.
<div id="component">
<div r-for="name of names">
<article class="card">
<span class="text-red">{{ name }}<span>
</article>
</div>
</div>
Invalid r-for loop as inner wrapper is missing.
<div id="component">
<div r-for="name of names">
{{ name }}
</div>
An r-for-key will be dynamically added to the markup which is required during the rendering process.
proxy.names = ["Lisa", "Frank", "Steve"];
Most methods of deleting does not trigger the proxy set event, in other words no reactivity. Using splice is the way to delete a value and still keep the reactivity. See examples.
<div id="component">
<button @click="proxy.names = proxy.names.slice(1, proxy.names.length)">Delete First</button>
<button @click="proxy.names = proxy.names.slice(0, -1)">Delete Last</button>
</div>
Adding value works works with the spread operator.
<div id="component">
<button @click="proxy.names = [...proxy.names, 'Rick']">Add Rick</button>
</div>
<div id="component">
<input id="input-el" type="number" r-model="proxy.price">
</div>
prefix with proxy is optional, above r-model could be used like this.
<div id="component">
<input id="input-el" type="number" r-model="price">
</div>
proxy.price = 1;
Having multiple components works as expected, proxies, computes, functions all works withing the component scope. Just ensure they are uniquely named as example shows. In this example proxy.a in component-1 is not the same as proxy.a in component-2.
<div id="component-1">
<button id="button" @click='proxy.a += 10'>Count Up</button>
</div>
<div id="component-2">
<button id="button" @click='proxy.a += 10'>Count Up</button>
</div>
const componentString1 = `<div id="component-1"><button id="button" @click='proxy.a += 10'>Count Up</button></div>`;
const componentString2 = `<div id="component-2"><button id="button" @click='proxy.a += 10'>Count Up</button></div>`;
const { appEl: appEl1, proxy: proxy1, compute: compute1 } = new Raccoon(document.getElementById(component-1));
const { appEl: appEl2, proxy: proxy2, compute: compute2 } = new Raccoon(document.getElementById(component-2));
proxy1.a = 1;
proxy2.a = 2;
compute1.withDollarSign = () => `$${proxy1.a}`;
compute2.withDollarSign = () => `$${proxy2.a}`;