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

  1. koa
  2. koa-router
  3. koa-static-cache
  4. nunjucks

Train of thought

  1. I chose to use a template enginenunjucksFacilitate page output
  2. withkoaFrameworks make writing node much easier
  3. Because I have static resources (images) that NEED to be output, that write judgment is too cumbersome to usekoa-static-cache
  4. 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 usekoa-router

Static Resource Mapping

  • Use the firstkoa-static-cacheMapping static Resources
  • Ps: Static resources as our initial judgment,koa-static-cacheIt 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 tonunjucksTo 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 passuseRegister, tellkoa
  • On this basis, I also want to complete the package, the beginning of the search template dir also passed in, throughuseTell him when the method is registered
  • Eventually we’ll be able to use it againnunjucksWhen exporting HTML templates, only passctx.renderIt 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 pageparamsThe details page I use isquery

Home page

  • On the route we can get through:paramsUse dynamic routing, so that in:What follows is judged to be indeterminate,URLIs in the form of/params, such as:http://127.0.0.1:8080/params.paramsThe content will passURLTo 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,/ 1It’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/ 1Enter 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// 1How about they all map to the same thing? That’s fine, but we could think of it the other way/become/ 1Wouldn’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 parametersparams, 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 usequeryThe refs?
  • Because I like it.To practice duckLet’s talk about itqueryThe participation!
  • Just like a function, passing an argument, even if we don’t need the preceding argument, it still has to take the place,paramsThe same is true if we dynamically route groups for longer periods of time, for example/user/page/contentAt this time, but also need to placeholder
  • whilequeryIt 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 userangefunction
  • aLabel 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