Web实战之文章阅览与编辑


完成的功能

  • 阅览文章
  • 有作者信息栏
  • 根据当前用户判断是否可修改文章
  • 修改并保存文章

依赖的第三方工具

  • vue.js
  • SuMarkdown
  • jquery
  • bootstrap-taginput

前言

我们先来分析一下这个功能的实现,其实这个过程中是需要很多数据的——作者的数据,文章的数据,当前用户的数据。如果分两个页面来做,显然许多异步数据会被重复加载,所以我决定把这一部分做成一个极小的单页面应用。

同时,在这一次的博客里,用到了许多Vue的重要特性,比如component,directive,life-cycle,是Vue一个不错的示例。

页面代码

主页面代码

 


    

    
        <%= title %>
    
    
    
    
    
    
    
    
    
    
    


    <%include layout/left-bar.ejs%>
    
<%include layout/alert.ejs%>

阅览模板













{{blog.author}}

{{author.description}}

{{blog.title}}

发表时间 {{blog.date | toDate }} 字数:{{blog.body.length}} 阅读量:30

编辑模板



标题


标签


0%

前端代码

Directive

/**
 * Created by suemi on 14-12-13.
 */
module.exports={
  tag:function(Vue){
       Vue.directive('tags',{
          twoWay:true,
          bind: function () {
              var self=this;
              console.log(self);
              $(self.el).on('itemAdded',function(){
                  scope.blog.tags=$(this).val();
              });
              $(self.el).on('itemRemoved',function(){
                  scope.blog.tags=$(this).val();
              });
          },
          update:function(){},
          unbind:function(){
              $(this.el).off();
          }
      });
      return module.exports;
  },
  all:function(Vue){
      for(var i in module.exports){
          if(i==='all') return module.exports;
          else module.exports[i](Vue);
      }
      return module.exports;
  }
};

让所有函数返回module.exports可以支持漂亮的链调的写法,同时还写了all函数以实现像angular一样(如下)

angular.module('demo',['app.directives']);

一次加载全部directive

Components

/**
 * Created by suemi on 14-12-13.
 */
module.exports={
    readBlog:function(Vue){
        var scope=Vue.component('readBlog',{
            inherit:true,
            template:require('../templates/readBlog.html'),
            ready:function(){
                $('#blogBody').html(marked(this.blog.body));
                $('pre code').each(function(i,block){
                       hljs.highlightBlock(block);
                });
            },
            methods:{
                edit:function(){
                    console.log(this);
                    this.currentView='editBlog';
                }
            },
            filters:{
                toDate:function(date){
                    var tmp=new Date(date);
                    return tmp.getFullYear()+'-'+tmp.getMonth()+'-'+tmp.getDate()+' '+tmp.toTimeString().split(' ')[0];
                }
            }
        });
        return module.exports;
    },
    editBlog:function(Vue){
      var scope=Vue.component('editBlog',{
          inherit:true,
          template:require('../templates/editBlog.html'),
          ready:function(){
            console.log(this.$el);
            $.extend(this.myBlog,this.blog);
            //复制原文标签
            $("input[data-role=tagsinput], select[multiple][data-role=tagsinput]",$(this.$el)).tagsinput();
            var tmp=[];
            $.extend(tmp,this.blog.tags);
            for(var i=0;i

main.js

/**
 * Created by suemi on 14-12-13.
 */
hljs.initHighlightingOnLoad();
var Vue=require('vue');
//Vue.config.debug=true;
require('./directives.js').tag(Vue);
require('./components.js').readBlog(Vue).editBlog(Vue);



scope=new Vue({
    el:'body',
    data:{
        user:{
            name:'',
            avatar:''
        },
        author:{
            avatar:''
            description:'',
            page:''
        },
        blog:{
            title:'',
            tags:[],
            body:'',
            author:'',
            date:undefined,
            content:''//html of the blog
        },
        msg:'',
        display:false,
        currentView:'readBlog',
        editable:true,
        login:false
    },
    methods:{
        getAuthor:function(){
            var tmp=window.location.href.split('/');
            $.get('/getBlog/'+tmp.pop()).done(function(data){
                if(data.success){
                    $.extend(scope.user,data.user);
                    $.extend(scope.author,data.author);
                    $.extend(scope.blog,data.blog);
                    $('#blogBody').html(marked(scope.blog.body));
                    $('pre code').each(function(){hljs.highlightBlock(this);});
                    //scope.blog.content=marked(scope.blog.body);
                    if(scope.user.name!=='') scope.login=true;
                    if(scope.user.name!==scope.blog.author) scope.editable=false;
                }
                else window.location.href='/404';
            }).fail(function(){
                window.location.href='/404';
            });
        },
    }
});


scope.getAuthor();

后端代码

/**
 *
 * Created by suemi on 14-12-4.
 */
var Err=usf.module.tool.Err,
    EndHanler=usf.module.tool.EndHandler,
    msg=usf.module.msg,
    Then=usf.lib.then,
    User=usf.db.def.User,
    Blog=usf.db.def.Blog;

function writeBlog(req,res){
    req.session.uname='suemi';
    if(req.body.author!==req.session.uname)
        return res.json({
            success:false,
            err:new Err('用户名不一致')
        });
    (new Blog(req.body)).save(function(err){
       if(!err) res.json({
           success:true,
           err:null
       });
        else res.json({
           success:false,
           err: new Err('后台错误,稍后再试')
       });
    });
}

function editBlog(req,res){
    Then(function(cont){
        if(!req.session.uname) return new Err('未登录');
        Blog.findById(req.params.blogID,cont);
    }).then(function(cont,doc){
        if(!doc) return new Err(msg.BLOG.blogNone);
        if(doc.author!==req.session.uname) return new Err('权限不足');
        delete req.body._id;
        doc=tool.union(doc,req.body);
        doc.save(cont);
    }).then(function(cont){
        res.json({
            success:true,
            err:null
        });
    }).fail(EndHandler);
}

function getBlog(req,res){
    var tmp={};
    tmp.user={};
    tmp.author={};
    Then(function(cont){
        Blog.findById(req.params.blogID,cont);
    }).then(function(cont,doc){
        if(!doc) return new Err(msg.BLOG.blogNone);
        tmp.blog=doc;
        User.findOne({username:doc.author},cont);
    }).then(function(cont,doc){
        if(!doc) return new Err('数据错误');
        tmp.author.name=doc.username;
        tmp.author=tool.union(tmp.author,doc.profile);
        if(req.session.uname) User.findOne({username:req.session.uname},cont);
        else cont();
    }).then(function(cont,doc){
        if(doc){
            tmp.user.name=doc.username;
            tmp.user=tool.union(tmp.user,doc.profile);
        }
        res.json({
            success:true,
            user:tmp.user,
            author:tmp.author,
            blog:tmp.blog,
            err:null
        });
    }).fail(EndHandler);
}
module.exports= {
    writeBlog: writeBlog,
    editBlog:  editBlog,
    getBlog:   getBlog
};

你可能感兴趣的:(Web实战之文章阅览与编辑)