Add validate option

This commit is contained in:
Sébastien Chopin 2016-12-12 16:30:07 +01:00
parent b3df306c30
commit f8c7b5c012
6 changed files with 48 additions and 33 deletions

View File

@ -1,27 +1,4 @@
module.exports = { module.exports = {
router: {
routes: {
// author: {
// alias: '/nuxt'
// },
// users: {
// _id: {
// regexp: ':id(\\d+)'
// // generate: [1, 2, 3, 4] // Need to be finished on generate
// }
// },
// posts: {
// alias: '/articles'
// }
}
},
// generate: {
// routeParams: {
// '/guide/:slug': _(require('./static/docs/guide/menu.json')).values().flatten().map('to').compact().map((slug) => { return { slug: slug.replace(/^\//, '') } }).value(),
// '/api/:slug': _(require('./static/docs/api/menu.json')).values().flatten().map('to').compact().map((slug) => { return { slug: slug.replace(/^\//, '') } }).value(),
// '/examples/:slug': _(require('./static/docs/examples/menu.json')).values().flatten().map('to').compact().map((slug) => { return { slug: slug.replace(/^\//, '') } }).value()
// }
// },
build: { build: {
vendor: ['axios'] vendor: ['axios']
} }

View File

@ -8,6 +8,14 @@
</div> </div>
</template> </template>
<script>
export default {
validate ({ params }) {
return /^[A-z]+$/.test(params.slug)
}
}
</script>
<style scoped> <style scoped>
p p
{ {

View File

@ -3,7 +3,7 @@
<h1>Dynamic route example</h1> <h1>Dynamic route example</h1>
<h2>Projects list</h2> <h2>Projects list</h2>
<p> <p>
<router-link :to="{ name: 'projects-slug', params: { slug: 'nuxt.js'} }"> <router-link :to="{ name: 'projects-slug', params: { slug: 'nuxtjs'} }">
Nuxt.js Nuxt.js
</router-link> </router-link>
</p> </p>

View File

@ -70,6 +70,17 @@ function render (to, ___, next) {
this.setTransition(Components[0].options.transition) this.setTransition(Components[0].options.transition)
this.error() this.error()
let nextCalled = false let nextCalled = false
let isValid = Components.some((Component) => {
if (typeof Component.options.validate !== 'function') return true
return Component.options.validate({
params: to.params || {},
query: to.query || {}
})
})
if (!isValid) {
this.error({ statusCode: 404, message: 'This page could not be found.', url: to.path })
return next()
}
Promise.all(Components.map((Component) => { Promise.all(Components.map((Component) => {
let promises = [] let promises = []
const _next = function (path) { const _next = function (path) {
@ -78,6 +89,7 @@ function render (to, ___, next) {
next(path) next(path)
} }
const context = getContext({ to<%= (store ? ', store' : '') %>, isClient: true, next: _next.bind(this), error: this.error.bind(this) }) const context = getContext({ to<%= (store ? ', store' : '') %>, isClient: true, next: _next.bind(this), error: this.error.bind(this) })
// Validate method
if (Component._data && typeof Component._data === 'function') { if (Component._data && typeof Component._data === 'function') {
var promise = promisify(Component._data, context) var promise = promisify(Component._data, context)
promise.then((data) => { promise.then((data) => {

View File

@ -6,22 +6,22 @@ import Router from 'vue-router'
Vue.use(Router) Vue.use(Router)
<% <%
let components = [] function recursiveRoutes(routes, tab, components) {
function recursiveRoutes(routes, tab) { var res = ''
let res = ''
routes.forEach((route, i) => { routes.forEach((route, i) => {
components.push({ _name: route._name, component: route.component }) components.push({ _name: route._name, component: route.component })
res += tab + '{\n' res += tab + '{\n'
res += tab + '\tpath: ' + JSON.stringify(route.path) + ',\n' res += tab + '\tpath: ' + JSON.stringify(route.path) + ',\n'
res += tab + '\tcomponent: ' + route._name res += tab + '\tcomponent: ' + route._name
res += (route.name) ? ',\n\t' + tab + 'name: ' + JSON.stringify(route.name) : '' res += (route.name) ? ',\n\t' + tab + 'name: ' + JSON.stringify(route.name) : ''
res += (route.children) ? ',\n\t' + tab + 'children: [\n' + recursiveRoutes(routes[i].children, tab + '\t\t') + '\n\t' + tab + ']' : '' res += (route.children) ? ',\n\t' + tab + 'children: [\n' + recursiveRoutes(routes[i].children, tab + '\t\t', components) + '\n\t' + tab + ']' : ''
res += '\n' + tab + '}' + (i + 1 === routes.length ? '' : ',\n') res += '\n' + tab + '}' + (i + 1 === routes.length ? '' : ',\n')
}) })
return res return res
} }
let routes = recursiveRoutes(router.routes, '\t\t') var _components = []
uniqBy(components, '_name').forEach((route) => { %> var _routes = recursiveRoutes(router.routes, '\t\t', _components)
uniqBy(_components, '_name').forEach((route) => { %>
const <%= route._name %> = process.BROWSER_BUILD ? () => System.import('<%= route.component %>') : require('<%= route.component %>') const <%= route._name %> = process.BROWSER_BUILD ? () => System.import('<%= route.component %>') : require('<%= route.component %>')
<% }) %> <% }) %>
@ -49,6 +49,6 @@ export default new Router({
linkActiveClass: '<%= router.linkActiveClass %>', linkActiveClass: '<%= router.linkActiveClass %>',
scrollBehavior, scrollBehavior,
routes: [ routes: [
<%= routes %> <%= _routes %>
] ]
}) })

View File

@ -60,8 +60,8 @@ export default context => {
<% } %> <% } %>
return promise return promise
.then(() => { .then(() => {
// Call data & fetch hooks on components matched by the route. // Sanitize Components
return Promise.all(Components.map((Component) => { Components = Components.map((Component) => {
let promises = [] let promises = []
if (!Component.options) { if (!Component.options) {
Component = Vue.extend(Component) Component = Vue.extend(Component)
@ -70,6 +70,24 @@ export default context => {
Component._Ctor = Component Component._Ctor = Component
Component.extendOptions = Component.options Component.extendOptions = Component.options
} }
return Component
})
// Call .validate()
let isValid = Components.some((Component) => {
if (typeof Component.options.validate !== 'function') return true
return Component.options.validate({
params: context.route.params || {},
query: context.route.query || {}
})
})
if (!isValid) {
// Call the 404 error by making the Components array empty
Components = []
return _app
}
// Call data & fetch hooks on components matched by the route.
return Promise.all(Components.map((Component) => {
let promises = []
const ctx = getContext(context) const ctx = getContext(context)
if (Component.options.data && typeof Component.options.data === 'function') { if (Component.options.data && typeof Component.options.data === 'function') {
Component._data = Component.options.data Component._data = Component.options.data