Rendering FrintJS Apps with Vue.js
--
FrintJS itself is agnostic of any rendering library. The core is primarily focused on managing its dependencies with providers, so that other tools and integrations can form around it.
While the main frint
package takes care of creating Apps with providers, we have other packages like frint-react
handling React.js integration. Same way, we also have frint-vue
that enables you to render your Vue.js components using similar API to that of React’s integration.
Rendering with Vue.js alone
Before getting into FrintJS, let’s first create and render a Component with Vue.js alone.
We will be using JSX for the examples below. Let’s say we have a basic component that prints out “Hello World”:
import Vue from 'vue';const MyComponent = {
render(h) {
return <p>Hello World</p>;
},
};const vm = new Vue({
...MyComponent,
el: 'root',
});
The code above assumes, you have an element in your DOM with ID root
:
<div id="root"></div>
Rendering with frint-vue
Before rendering, we need to create a FrintJS App first:
import { createApp } from 'frint';const App = createApp({
name: 'MyApp',
});
Now we will let our App know about our Vue.js component, by setting it as a provider with the name component
:
import { createApp } from 'frint';const MyComponent = {
render(h) {
return <p>Hello World</p>;
},
};const App = createApp({
name: 'MyApp',
providers: [
{
name: 'component',
useValue: MyComponent,
},
{
name: 'foo',
useValue: 'foo value here',
},
],
});
Since our App is clearly defined by now, we can proceed with rendering it to DOM with Vue.js:
import { render } from 'frint-vue';const App = createApp({ ... });const app = new App();
render(app, {
el: 'root',
});
We basically imported the render
function from our frint-vue
package, and called it by providing the App instance, and additional options specifying where to render it in the DOM.
Accessing providers in Vue.js components
The frint-vue
package follows similar API as found in frint-react
. You can still access the FrintJS App instance from your components using our observe
higher-order component, from which you can then get your desired providers.
Synchronous props:
If the props are not changing over time:
import { observe } from 'frint-vue';const MyComponent = {
props: ['appName', 'foo'],
render(h) {
return (
<div>
App Name: {this.appName}
Foo: {this.foo}
</div>
);
},
};export default observe(function (app) {
return {
appName: app.getName(),
foo: app.get('foo'),
};
})(MyComponent);
Streaming props:
Where props is a stream expressed with an RxJS Observable:
import { observe } from 'frint-vue';
import { interval } from 'rxjs/observable/interval';
import { map } from 'rxjs/operators/map';const MyComponent = {
props: ['interval'],
render(h) {
return (
<div>
Interval: {this.interval}
</div>;
);
},
};export default observe(function (app) {
return interval(1000).pipe(
map(x => ({ interval: x }))
);
})(MyComponent);
The code above demonstrates props as a steam using RxJS lettable operators. Ultimately, we are streaming a prop-compatible object from the returned Observable here.
You can also use our streamProps
helper function to combine values from various sources into a single props observable:
import { observe, streamProps } from 'frint-vue';
import { interval } from 'rxjs/observable/interval';const MyComponent = { ... };export default observe(function (app) {
return streamProps()
// sync props
.set('appName', app.getName())
.set('foo', app.get('foo') // where source is an Observable
.set(
interval(1000),
x => ({ interval: x })
) // generate a combined Observable of props
.get$();
})(MyComponent);
Your MyComponent
will now receive both appName
, foo
, and interval
as props. The appName
and foo
props will stay the same, but interval
will keep incrementing every second, which will trigger a re-render of your Vue.js component.