-
Get Started
-
Events
-
Router / Navigation
-
Components
- App / Core
- Accordion / Collapsible
- Action Sheet / Actions
- Autocomplete
- Badge
- Block / Content Block
- Button
- Calendar / Datepicker
- Cards
- Checkbox
- Chips / Tags
- Contacts List
- Data Table
- Dialog
- Floating Action Button
- Form Data / Storage
- Grid / Layout Grid
- Icons
- Infinite Scroll
- Inputs / Form Inputs
- Lazy Load
- Link
- List View
- List Index
- Login Screen
- Messagebar
- Messages
- Navbar
- Notification
- Page
- Panel / Side Panels
- Photo Browser
- Picker
- Popover
- Popup
- Preloader
- Progressbar
- Pull to Refresh
- Radio
- Range Slider
- Searchbar
- Sheet Modal
- Smart Select
- Sortable List
- Statusbar
- Stepper
- Subnavbar
- Swiper
- Swipeout
- Tabs
- Timeline
- Toast
- Toggle
- Toolbar / Tabbar
- Video Intelligence (vi)
- View / Router
- Virtual List
-
Framework7 Icons
-
Styling
-
Dom7
-
Template7
-
Fast Clicks
-
Utilities
-
Plugins API
-
Custom Build
Router Component
Router Component is a special type of content that can be loaded by Router when we specify route content using component
or componentUrl
properties.
It should help to better structure our apps, keep things in appropriate place, and make many things quicker and in a more clear and comfortable way.
Component Structure
If you know what is Vue component, then it will be much easier to understand as it looks pretty similar. Router Component is basically an object with the following properties (all properties are optional):
Property | Type | Description |
---|---|---|
template | string | Template7 template string. Will be compiled as Template7 template |
render | function | Render function to render component. Must return full html string or HTMLElement |
data | function | Component data, function must return component context data |
style | string | Component CSS styles. Styles will be added to the document after component will be mounted (added to DOM), and removed after component will be destroyed (removed from the DOM) |
styleScopeId | string | Unique style scope id in case you are using scoped styles. Will add data-scope="styleScopeId" to the component element |
methods | object | Object with additional component methods which extend component context |
on | object | Object with page events handlers |
Lifecycle Hooks | ||
beforeCreate | function | Called synchronously immediately after the component has been initialized, before data and event/watcher setup. |
created | function | Called synchronously after the component is created, context data and methods are available and component element $el is also created and available |
beforeMount | function | Called right before component will be added to DOM |
mounted | function | Called right after component was be added to DOM |
beforeDestroy | function | Called right before component will be destoyed |
destroyed | function | Called when component destroyed |
All lifecycle hooks and methods automatically have their this
context bound to the component context, so that you can access component data and methods. This means you should not use an arrow function to define a lifecycle method (e.g. created: () => this.doSomething()
). The reason is arrow functions bind the parent context, so this
will not be the component instance as you expect and this.doSomething
will be undefined.
So the example route with page component may look like:
routes = [
// ...
{
path: '/some-page/',
// Component Object
component: {
template: `
<div class="page">
<div class="navbar">
<div class="navbar-inner">
<div class="title">{{title}}</div>
</div>
</div>
<div class="page-content">
<a @click="openAlert" class="red-link">Open Alert</a>
<div class="list simple-list">
<ul>
{{#each names}}
<li>{{this}}</li>
{{/each}}
</ul>
</div>
</div>
</div>
`,
style: `
.red-link {
color: red;
}
`,
data: function () {
return {
title: 'Component Page',
names: ['John', 'Vladimir', 'Timo'],
}
},
methods: {
openAlert: function () {
var self = this;
self.$app.dialog.alert('Hello world!');
},
},
on: {
pageInit: function (e, page) {
// do something on page init
},
pageAfterOut: function (e, page) {
// page has left the view
},
}
},
},
// ...
]
Note that in component additional @
attribute is supported in component template. It is a shorthand method to assign event listener to the specified element. Specified event handler will be searched in component methods
Component Context
As we said above, all component methods and Template7 compiler are executed in the context of the component.
Component context is the object you have returned in component's data
and methods from specified methods
object, but also extended with the following useful properties:
Property | Type | Desctiption |
---|---|---|
$el | object | Dom7 instance with component HTML element
|
$ $$ $dom7 |
function | Dom7 library:
|
$app | object | Framework7 app instance
|
$root | object | Root data and methods you have specified in data and methods properties on app init
|
$route | object | Current route. Contains object with route query , hash , params , path and url |
$router | Router instance | Related router instance
|
$theme | object | Object with md and ios boolean properties which indicating current theme. For example:
|
Component Page Events
Component page events handlers can be passed in on
component property. They are usual DOM Page Events. Because they are DOM events, they accept event
as first agrument, and Page Data as second argument. There only difference with usual DOM events is that their context (this
) bound to component context and event handler name must be specified in camelCase format:
...
data: function () {
return {
username: 'johndoe',
};
},
on: {
pageMounted: function (e, page) {
console.log('page mounted');
},
pageInit: function (e, page) {
console.log(this.username); // -> 'johndoe'
},
pageBeforeIn: function (e, page) {
console.log('page before in');
},
pageAfterIn: function (e, page) {
console.log('page after in');
},
pageBeforeOut: function (e, page) {
console.log('page before out');
},
pageAfterOut: function (e, page) {
console.log('page after out');
},
pageBeforeRemove: function (e, page) {
console.log('page before remove');
},
}
Single File Component
It is not very comfortable to specify all component routes under same routes array, especially if we have a lot of such routes. This is why we can use componentUrl
instead and out component into single file:
routes = [
...
{
path: '/some-page/',
componentUrl: './some-page.html',
},
..
];
And in some-page.html
:
<!-- component template -->
<template>
<div class="page">
<div class="navbar">
<div class="navbar-inner">
<div class="title">{{title}}</div>
</div>
</div>
<div class="page-content">
<a @click="openAlert">Open Alert</a>
<div class="list simple-list">
<ul>
{{#each names}}
<li>{{this}}</li>
{{/each}}
</ul>
</div>
</div>
</div>
</template>
<!-- component styles -->
<style>
.red-link {
color: red;
}
</style>
<!-- rest of component data and methods -->
<script>
// script must return component object
return {
data: function () {
return {
title: 'Component Page',
names: ['John', 'Vladimir', 'Timo'],
}
},
methods: {
openAlert: function () {
var self = this.$app.dialog.alert('Hello world!');
},
},
on: {
pageInit: function () {
// do something on page init
},
pageAfterOut: function () {
// page has left the view
},
}
}
</script>
Well, now it is much cleaner. The <template>
and <style>
tags will be automatically converted to the same properties of exported component.
You may think that it is not valid to have a direct return
statement in script, but it is ok because parser puts the content of the script tag into function body, so it is ok here
Scoped Styles
In case you want to scope component styles in single file component to this component only, you may add scoped
attribute to component <style>
tag:
<template>
<!-- component template -->
</template>
<!-- style has additional "scoped" attribute -->
<style scoped>
p {
color: red;
}
a {
text-decoration: none;
}
</style>
<script>
return {
...
}
</script>
When scoped style added component element will have additional data-scope="[unique_id]"
where [unique_id] is the unique timestamp. And all styles will be refactored to have this unique scope id, for example:
[data-scope="1515740589328"] p {
color: red;
}
[data-scope="1515740589328"] a {
text-decoration: none;
}
In case you need to use more complex selector with including component parent reference, then you may use {{this}}
keword to reference the component:
<template>
<!-- component template -->
</template>
<!-- style has additional "scoped" attribute -->
<style scoped>
<!-- all paragraphs in this component will be red under iOS theme -->
html.ios {{this}} p {
color: red;
}
<!-- all paragraphs in this component will be green under MD theme -->
html.md {{this}} p {
color: green;
}
</style>
<script>
return {
...
}
</script>