preface
- A lot of practice and review starts with a simple todoList
- This todoList I use Node as the back end, koA framework, has a home page and details page, but not much data, content is also very little, but it doesn’t matter ~
- Code and resources in my github: milk0v0, everyone interested can first look at the effect and then look at my ideas, also welcome to pay attention to ao ~
The entrance
- Github.com/milk0v0/koa…
node app.js
Copy the code
Using the Technology stack
- koa
- koa-router
- koa-static-cache
- nunjucks
Train of thought
- I chose to use a template engine
nunjucks
Facilitate page output- with
koa
Frameworks make writing node much easier- Because I have static resources (images) that NEED to be output, that write judgment is too cumbersome to use
koa-static-cache
- The most important is routing, we use routing for navigation (the actual operation is to output different content according to the URL), then routing navigation is very important, I choose to use
koa-router
Static Resource Mapping
- Use the first
koa-static-cache
Mapping static Resources - Ps: Static resources as our initial judgment,
koa-static-cache
It needs to be on top of all the middle keys
app.use(KoaStaticCache('./public', {
dynamic: true
}));
Copy the code
Template engine middle key
- We refer to
nunjucks
To reference the template => write the data => then output through ctx.body, it would be uncomfortable to write so much duplicate code if we had a relatively large number of templates - We wrote the middle key so that we can output the template through ctx.render(fileName, datas)
- Don’t get too complicated, just write a function that makes ctx.render a method and then pass
use
Register, tellkoa
- On this basis, I also want to complete the package, the beginning of the search template dir also passed in, through
use
Tell him when the method is registered - Eventually we’ll be able to use it again
nunjucks
When exporting HTML templates, only passctx.render
It is ok
module.exports = (dir, options) = > {
const tpl = new nunjucks.Environment(
new nunjucks.FileSystemLoader(dir, options)
);
return (ctx, next) = > {
ctx.render = (fileName, datas) = > {
let content = tpl.render(fileName, datas);
ctx.body = content;
}
next();
}
}
app.use(KoaStaticCache('./public', {
dynamic: true
}));
Copy the code
routing
- Routing is very important. The most important part of todoList is the routing part. If the routing is handled well, then the todoList will be finished soon
- Our page has two parts, one is the home page, one is the details page
- So my routing design is divided into
/
(Home page) and/detail
(Details page) two, but the contents of the home page need to be paginated, the details page will also have different content, how to do - I used dynamic routing. I used the home page
params
The details page I use isquery
Home page
- On the route we can get through
:params
Use dynamic routing, so that in:
What follows is judged to be indeterminate,URL
Is in the form of/params
, such as:http://127.0.0.1:8080/params
.params
The content will passURL
To the backend - The argument in parentheses is the re judgment. I’m going to enter the route by checking the number of pages on our home page
/ 1
、/ 2,
In this form
router.get('/:page(\\d+)'.ctx= >{});Copy the code
- Now, there’s a problem,
/ 1
It’s the first page,/ 2,
It’s the second page, but it was the first page when we startedhttp://127.0.0.1:8080/1
, users don’t traditionally write/ 1
Enter the home page/page (of course, the real project is also no reason for content paging as the home page), so also very ugly, how to do that - the
/
和/ 1
How about they all map to the same thing? That’s fine, but we could think of it the other way/
become/ 1
Wouldn’t it be all right? - I’m using redirection here
router.get('/'.ctx= > {
ctx.redirect('/ 1');
});
Copy the code
- At this time, our home route is designed ~
- Since the data is an array object, I want 5 contents on a page, so we can just wave our hands and determine the routing parameters
params
, filter it, and then fill it into the template
const pages = Math.ceil(datas.length / 5);
const { page } = ctx.params;
const showDatas = datas.filter((item, index) = > (index >= 5 * (page - 1) && index < page * 5));
ctx.render('index.html', { datas: showDatas, pages, page })
Copy the code
Details page
- Details page originally nothing to say, in fact, like the home page, through the dynamic routing parameters to determine the data array, the content can be output, but why I use
query
The refs? Because I like it.To practice duckLet’s talk about itquery
The participation!- Just like a function, passing an argument, even if we don’t need the preceding argument, it still has to take the place,
params
The same is true if we dynamically route groups for longer periods of time, for example/user/page/content
At this time, but also need to placeholder - while
query
It passes whatever it wants, just like a function passes an object, without occupying space, in the form of:? id=
- Then the details of the page, we are also a small hand wave ~ done
router.get('/detail'.ctx= > {
const data = datas.find(item= > +ctx.query.id === item.id);
ctx.render('detail.html', { data })
});
Copy the code
The template
- At last, I would like to talk about the template, which is not very interesting
- The loop numbers we need to use
range
function a
Label jump, paging we just according to our current page, the length of the data array, a small judgment is good ~- Details page, because my judgment is through id, so our request is also through
/detail? id=
Just deal with it
<a href="/detail? id={{data.id}}"></a> <! -- Details page -->
<! - page - >
<div class="pagination">
{% if page > 1 %}
<a href="{{+page-1}}" class="prev">⌜</a>
{% endif %}
{% for i in range(1, pages+1) %}
{% if i == page %}
<a class="current">{{i}}</a>
{% else %}
<a href="/{{i}}">{{i}}</a>
{% endif %}
{% endfor %}
{% if page < pages %}
<a href="{{+page+1}}" class="next">⌝</a>
{% endif %}
</div>
Copy the code
Feel free to discuss in the comments