实例1:ember的一个博客实例教程

时间:2020-11-28 14:41:05

如果认真看了前面的ember101课程,相信已经有了驾驭ember 实现一个真正的应用程序的冲动,这次我们运用我们已经掌握的知识,构建一个完整的、刚好实现的博客程序。参照的书籍是ember实战。

应用程序主要有两个代码文件组成index.html 和 app.js 。实际的应用程序里,把app.js 分解成了几个.js 文件:models.js(模型)、views.js(视图)、controllers.js(控制器)、router(路由) 。其实对于本例不复杂的应用程序,这些文件内容都放在app.js 也没什么不可以,这样看着清晰些吧。

1、先来整体看下index.html文件


  <!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">

    <title>Ember.js In Action Blog</title>
 <link rel="stylesheet" href="css/master.css" type="text/css" charset="utf-8">
    <meta name="author" content="Joachim Haagen Skeie">
    <script src="js/scripts/jquery-1.10.2.min.js" type="text/javascript" charset="utf-8"></script>
 <script src="js/scripts/showdown.js" type="text/javascript" charset="utf-8"></script>
    <script src="js/scripts/handlebars-1.0.0.js" type="text/javascript" charset="utf-8"></script>
 <script src="js/scripts/ember-1.0.0.js" type="text/javascript" charset="utf-8"></script>
    <script src="js/scripts/ember-data-beta-1.js" type="text/javascript" charset="utf-8"></script>
 <script src="js/app/app.js" type="text/javascript" charset="utf-8"></script>
    <script src="js/app/models.js" type="text/javascript" charset="utf-8"></script>
 <script src="js/app/views.js" type="text/javascript" charset="utf-8"></script>
    <script src="js/app/controllers.js" type="text/javascript" charset="utf-8"></script>
 <script src="js/app/router.js" type="text/javascript" charset="utf-8"></script>

    
     //这里是*模版的定义,handlebars模版的linkTo块语句链接Home到博客的索引页面,链接About到关于页面;
       浏览器里我们看到的页面,这只是两个选项,主体内容由lutlet引入下面两个二级模版。
     <script type="text/x-handlebars" id="application">
        <h1>Ember.js in Action Blog</h1>
 <div class="headerLinks">
 {{#linkTo "blog.index"}}Home{{/linkTo}}<span class="middot">&middot;</span>
 {{#linkTo "about"}}About{{/linkTo}}
        </div>

 {{outlet}}
 </script>

   //这里是 blog/index 模版的定义,这是个blog的二级模版

    <script type="text/x-handlebars" id="blog/index">
        {{#each controller}}
            <h1>{{postTitle}}</h1>
 <div class="postDate">{{formattedDate}}</div>   
            {{postLongIntro}}<br />
            <br />{{#linkTo "blog.post" this}}Full Article ->{{/linkTo}}
 <hr class="blogSeperator"/>
        {{/each}}
 </script>
  
   //这里是 blog/post 模版的定义,这是blog另一个二级模版,用来在上面模版blog/index单击`Full Article -> `后链接对应的博客文章, 
     这个模板里在点击`>back`后链接到blog/index 博客索引界面。
     <script type="text/x-handlebars" id="blog/post">
        <div class="postDate">{{formattedDate}}</div>
 <br />{{#linkTo "blog.index"}}&lt; back{{/linkTo}}
 {{markdown}}
 <br />{{#linkTo "blog.index"}}&lt; back{{/linkTo}}
 </script>

   //这里是 about 模版的定义
    <script type="text/x-handlebars" id="about">
        <h1>About</h1>
 This blog is part of the Ember in Action book.
 Sample code for chapter 3.
 </script>

</head>
<body>
</body>
</html>

2、再来看看路由router

路由名称---- 对应网址URL

index路由---- 跳转到/posts

blog路由---- 对应 /blog
blog/index子路由---- 对应 /posts
blog/post子路由---- 对应 /psot/:post_id

about路由---- 对应 /about

按照前面ember101的讲解,ember会分别为定义application、index、blog、about 路由建立默认的类(路由、控制器、视图)和模版;拿blog做例子就是建立BlogRoute类、BlogContrller类、BlogView类和模版 blog。

//定义一个blog的路由,这里的`hash`参数是默认值,可以`histore` 区别在于URL的编码格式多了一个#散列符,前者是:#/blog/post/:post_id 后者是/blog/post/:post_id

Blog.Router = Ember.Router.extend({
    location: 'hash'
});

Blog.Router.map(function() {
    this.route("index", {path: "/"});
    this.resource("blog", {path: "/blog"}, function() {
        this.route("index", {path: '/posts'});
        this.route("post", {path: '/post/:blog_post_id'});
    });
    this.route("about", {path: "/about"});
});

//index 路由实际就是博客的索引界面,所以没有实质性内容,直接跳转到博客索引界面blog.index
Blog.IndexRoute = Ember.Route.extend({
    redirect: function() {
        this.transitionTo('blog.index');
    }
});

//定义blog.index子路由数据模型获取所有博客文章
Blog.BlogIndexRoute = Ember.Route.extend({
    model: function() {
        return this.store.find('blogPost');
    }
});
//定义blog.index子路由数据模型获取指定ID的博客文章
Blog.BlogPostRoute = Ember.Route.extend({
    model: function(blogPost) {
        return this.store.find('blogPost', blogPost.blog_post_id);
    }
});

3、看下model 模型里的内容


  //定义blog.post模型的数据结构
  Blog.BlogPost = DS.Model.extend({
    postTitle: DS.attr('string'),
    postDate: DS.attr('date'),
    postShortIntro: DS.attr('string'),
    postLongIntro: DS.attr('string'),
    postFilename: DS.attr('string'),

    
   //看到.property就知道这里是一个计算属性,用来把日期格式化,显示成我们比较习惯的格式。
    markdown: null,
    formattedDate: function() {
        if (this.get('postDate')) {
            return this.get('postDate').getUTCDay()
                + "/" + (this.get('postDate').getUTCMonth() + 1)
                + "/" + this.get('postDate').getUTCFullYear();
        }

        return '';
    }.property('postDate'),

  //这里定义了文章的获取路径/blog/post/id
    postFullUrl: function() {
        return "/blog/post/" + this.get('id');
    }.property('id')
});

4、看下控制器的内容


Blog.ApplicationController = Ember.Controller.extend({});

Blog.BlogIndexController = Ember.ArrayController.extend({});

Blog.BlogPostController = Ember.ObjectController.extend({
    content: null,

    contentObserver: function() {
        console.log('Blog.BlogPostController contentObserver: ' + this.get('content.id'));
        if (this.get('content')) {
            var page = this.get('content');

            $.get("/posts/" + this.get('content.id') + ".md", function(data) {
                var converter = new Showdown.converter();
                page.set('markdown', new Handlebars.SafeString(converter.makeHtml(data)));
            }, "text")
                .error(function() {
                    page.set('markdown',  "Unable to find specified page");
                    //TODO: Navigate to 404 state
                });

        }
    }.observes('content')
});

5、看看app.js里还需要有哪些内容

var Blog = Ember.Application.create({
    log: function(message) {
        if (window.console) console.log(message);
    }
});

Blog.Store = DS.Store.extend({
    adapter: DS.RESTAdapter
});

6、简单浏览下view视图的内容

Blog.ApplicationView = Ember.View.extend({
    elementId: 'mainArea'
});

Blog.BlogIndexView = Ember.View.extend({
    elementId: 'blogsArea'
});

Blog.BlogPostView = Ember.View.extend({
    elementId: 'blogPostArea'
});

Blog.AboutView = Ember.View.extend({
    elementId: 'aboutArea'
});