![最终产品图片](https://cms-assets.tutsplus.com/uploads/users/435/posts/24208/final_image/00-final.png)
在前六个会话中,您已经从头开始构建了博客系统。 一切正常,那太好了! 但是,代码本身很乱-我们一直将所有东西引导在一起,并留下了很多重复的代码和临时解决方案。 本课程将重点讨论如何清理问题并解决我们遇到的一些问题。
1.合并index.html和admin.html
首先,由于现在有了路由器(如果您错过了该会话,请参阅第5部分:路由器 ),我们不再需要两个单独的.html
和.js
文件。 让我们将它们合并在一起。
步骤1:合并档案
在这一点上,我建议合并admin.html
和admin.js
并将它们重命名为index.html
和blog.js
因为它们具有更多的逻辑和代码,但是您可以采用任何一种方式。 这应该很简单。
如果您重命名这些文件,只要确保你链接到blog.js
新index.html
(以前admin.html
)。 另外,请记住将#blogs-tpl
从旧的index.html
文件复制到新文件,并将BlogsView
从旧的blog.js
文件复制到新文件。
现在访问http:// localhost / your-directory / ,默认情况下,您应该会看到登录屏幕(如果已经登录,则为管理屏幕)。
![重命名管理页面](https://i-blog.csdnimg.cn/blog_migrate/1576fbf41b6c1b3c5bd942948b2fd3f5.png)
步骤2:更新路由器
然后,我们可以在路由器中添加新的URL模式,以将根URL匹配到新功能; 我们可以称之为index()
:
routes: {
'': 'index',
...
},
此index()
函数应呈现主页上的先前内容。
index: function() {
this.blogs.fetch({
success: function(blogs) {
var blogsView = new BlogsView({ collection: blogs });
blogsView.render();
$('.main-container').html(blogsView.el);
},
error: function(blogs, error) {
console.log(error);
}
});
}
为了使其正常工作,让我们在路由器启动时默认重定向到该URL:
start: function(){
Parse.history.start({pushState: true});
this.navigate('', { trigger: true });
}
第3步:更新导航
接下来是更新顶部的导航栏。 让我们在这里将这些HTML文件更改为URL:
<nav class="blog-nav">
<a class="blog-nav-item active" href="">Home</a>
<a class="blog-nav-item" href="admin">Admin</a>
</nav>
对于那些有效的方法,我们需要向.blog-nav-item
添加一个事件以使用blogRouter.navigate()
而不是默认的链接事件:
$(document).on('click', '.blog-nav-item', function(e) {
e.preventDefault();
var href = $(e.target).attr('href');
blogRouter.navigate(href, { trigger: true });
});
让我们也添加逻辑来切换.active
类:
$(document).on('click', '.blog-nav-item', function(e) {
e.preventDefault();
var href = $(e.target).attr('href');
blogRouter.navigate(href, { trigger: true });
$(this).addClass('active').siblings().removeClass('active');
});
现在,如果您单击一下,一切都应该正常工作!
2.合并添加和编辑
继续,我们可以看到AddBlogView
和EditBlogView
非常相似。 Blog
类中的update()
和create()
函数也是如此。 让我们也合并它们。
步骤1:合并#add-tpl和#edit-tpl
首先,让我们将index.html
的两个模板合并为#write-tpl
。
<script id="write-tpl" type="text/x-handlebars-template">
<h2>{{form_title}}</h2>
<form class="form-write" role="form">
<div class="form-group">
<label for="title">Title</label>
<input name="title" type="text" class="form-control" id="title" value="{{title}}"></input>
</div>
<div class="form-group">
<label for="content">Content</label>
<textarea name="content" class="form-control" rows="20">{{{content}}}</textarea>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">Submit</button>
</form>
</script>
您可以看到它基本上是#edit-tpl
具有类名更改和动态表单标题。 添加新博客时,我们只会在title
和content
传递""
。
步骤2:合并update()和create()函数
接下来,让我们在Blog类中合并update()
和create()
函数。 我们可以将this.set().save()
函数链接到update()
和create()
。 对于不需要使用update()
函数的字段,我们可以填充当前值:
update: function(title, content) {
this.set({
'title': title,
'content': content,
// Set author to the existing blog author if editing, use current user if creating
// The same logic goes into the following three fields
'author': this.get('author') || Parse.User.current(),
'authorName': this.get('authorName') || Parse.User.current().get('username'),
'time': this.get('time') || new Date().toDateString()
}).save(null, {
success: function(blog) {
alert('You updated a new blog: ' + blog.get('title'));
},
error: function(blog, error) {
console.log(blog);
console.log(error);
}
});
}
步骤3:合并AddBlogView和EditBlogView
现在,该合并两个视图了:
WriteBlogView = Parse.View.extend({
template: Handlebars.compile($('#write-tpl').html()),
events: {
'submit .form-write': 'submit'
},
submit: function(e) {
e.preventDefault();
var data = $(e.target).serializeArray();
// If there's no blog data, then create a new blog
this.model = this.model || new Blog();
this.model.update(data[0].value, data[1].value);
},
render: function(){
var attributes;
// If the user is editing a blog, that means there will be a blog set as this.model
// therefore, we use this logic to render different titles and pass in empty strings
if (this.model) {
attributes = this.model.toJSON();
attributes.form_title = 'Edit Blog';
} else {
attributes = {
form_title: 'Add a Blog',
title: '',
content: ''
}
}
this.$el.html(this.template(attributes)).find('textarea').wysihtml5();
}
})
注意如何使用if(this.model)
在添加和编辑功能之间进行if(this.model)
。
步骤4:更新路由器
最后,让我们链接到路由器中的此新WriteBlogView
。 只需将两个视图都更改为WriteBlogView
,它仍将照常工作。
add: function() {
// Check login
if (!Parse.User.current()) {
this.navigate('login', { trigger: true });
} else {
var writeBlogView = new WriteBlogView();
writeBlogView.render();
$container.html(writeBlogView.el);
}
},
edit: function(id) {
// Check login
if (!Parse.User.current()) {
this.navigate('login', { trigger: true });
} else {
var query = new Parse.Query(Blog);
query.get(id, {
success: function(blog) {
var writeBlogView = new WriteBlogView({ model: blog });
writeBlogView.render();
$container.html(writeBlogView.el);
},
error: function(blog, error) {
console.log(error);
}
});
}
}
请注意,如果访客未登录,您还应该将访客带回到登录页面。
3.将访问控制列表添加到博客
现在,我们已经删除了所有重复的代码,现在我们可以继续进行一些改进的功能。
你们中的许多人都问过,如果代码中包含API,我们如何才能确保数据安全。 Parse.js同时提供类级别和项目级别的访问控制列表(ACL),以帮助管理用户访问。 在第3部分:用户登录中,我们讨论了类级ACL。 今天,我将向您展示如何添加项目级ACL。
作为示例,假设我们只希望每个博客只能由其原始作者编辑。
为此,我们需要在update()
函数中设置ACL
字段:
update: function(title, content) {
// Only set ACL if the blog doesn't have it
if ( !this.get('ACL') ) {
// Create an ACL object to grant access to the current user
// (also the author of the newly created blog)
var blogACL = new Parse.ACL(Parse.User.current());
// Grant read-read only access to the public so everyone can see it
blogACL.setPublicReadAccess(true);
// Set this ACL object to the ACL field
this.setACL(blogACL);
}
this.set({
...
});
}
4.根URL和静态URL
你们中许多人可能会感到的另一个问题是,很难测试正在创建的博客系统。 每次测试时,您都必须返回http:// localhost / your-directory /来触发路由器。
让我们首先解决这个问题。
步骤1:在BlogRouter.start()中添加一个根
使用Parse.js可以很容易地做到这一点,因此我们只需要更改BlogRouter.start()
函数来设置文件根即可。
start: function(){
Parse.history.start({
// put in your directory below
root: '/tutorial_blog/'
});
}
注意,我们现在可以取出this.navigate()
函数。
步骤2:静态网址
我们目前拥有的网址的另一个问题是无法将其添加为书签或重新访问。 您想要做的所有事情,都需要从主URL开始。 例如,如果您访问http:// localhost / blog / admin ,则将路由器设置为接受此URL模式,但服务器仍返回404。这是因为,当您访问/admin
,服务器并不知道它应该实际运行到index.html
首先启动路由器。
解决此问题的一种方法是配置服务器,以便将所有URL重定向到index.html
。 但是,这实际上不在本课程的讨论范围内。 我们将尝试另一种方法:在所有URL之前添加#/
。
管理面板的网址如下所示: http:// localhost / blog /#/ admin 。 这不是很理想,但这是一个简单的方法。 当浏览器遇到/#
,它不会将URL的其余部分视为文件路径; 相反,它将引导用户访问index.html,以便我们的路由器可以接管其余部分。
现在,让我们继续从index.html
更改所有<a>
标记的href
属性,如下所示:
<a class="app-link" href="edit/{{url}}">Edit</a>
像这样:
<a class="app-link" href="#/edit/{{url}}">Edit</a>
同样,让我们改变所有BlogApp.navigate()
在blog.js
从这样的事情:
BlogApp.navigate('admin', { trigger: true });
像这样:
BlogApp.navigate('#/admin', { trigger: true });
您也可以删除一些事件以使用<a>
标记。
例如,用于添加事件的“ 添加新博客 ”按钮:
events: {
'click .add-blog': 'add'
},
add: function(){
blogRouter.navigate('#/add', { trigger: true });
}
我们可以将其删除并将其更改为index.html
的链接:
<a href="#/add" class="add-blog btn btn-lg btn-primary">Add a New Blog</a>
您也可以使用此功能,因为URL可以自己使用:
$(document).on('click', '.blog-nav-item', function(e) {
e.preventDefault();
var href = $(e.target).attr('href');
blogRouter.navigate(href, { trigger: true });
$(this).addClass('active').siblings().removeClass('active');
});
现在让我们也删除active
类,但是我们将其添加回去,并以另一种方式在以后的会话中使用。
<nav class="blog-nav">
<a class="blog-nav-item" href="">Home</a>
<a class="blog-nav-item" href="#/admin">Admin</a>
</nav>
好的,浏览您的博客,进行测试,并确保除主页外,所有链接现在都指向http:// localhost /#/...。
现在,您有了可以刷新和重新访问的URL。 希望这会使您的生活更轻松!
奖金:其他修复和改进
如果您不介意这个超长的教程,并且想做一些进一步的改进,那么这里可以做一些其他的修复和改进。
步骤1:排序
您可能还会注意到的一件事是,博客是从最早到最新的排序。 通常,我们希望首先看到最新的博客。 因此,让我们更改Blogs
集合以按以下顺序对其进行排序:
Blogs = Parse.Collection.extend({
model: Blog,
query: (new Parse.Query(Blog)).descending('createdAt')
})
步骤2:在update()之后重定向到WelcomeView
这是我们可以改进的另一件事。 在更新博客后,我们无需重定向到警告窗口,而只需重定向到/admin
页面即可:
this.set({
...
}).save(null, {
success: function(blog) {
blogRouter.navigate('#/admin', { trigger: true });
},
error: function(blog, error) {
...
}
});
步骤3:在AdminView中合并AdminView
如果您要进行清洁,还可以将AdminView和WelcomeView合并为一个-并不需要两个独立的视图。
再次,HTML模板首先:
<script id="admin-tpl" type="text/x-handlebars-template">
<h2>Welcome, {{username}}!</h2>
<a href="#/add" class="add-blog btn btn-lg btn-primary">Add a New Blog</a>
<table>
<thead>
<tr>
<th>Title</th>
<th>Author</th>
<th>Time</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{{#each blog}}
<tr>
<td><a class="app-link" href="#/edit/{{objectId}}">{{title}}</a></td>
<td>{{authorName}}</td>
<td>{{time}}</td>
<td>
<a class="app-link app-edit" href="#/edit/{{objectId}}">Edit</a> |
<a class="app-link" href="#">Delete</a>
</td>
</tr>
{{/each}}
</tbody>
</table>
</script>
然后让我们更改BlogRouter.admin()
以将username
传递给AdminView
:
admin: function() {
var currentUser = Parse.User.current();
// Check login
if (!currentUser) BlogApp.navigate('#/login', { trigger: true });
this.blogs.fetch({
success: function(blogs) {
var blogsAdminView = new BlogsAdminView({
// Pass in current username to be rendered in #admin-tpl
username: currentUser.get('username'),
collection: blogs
});
blogsAdminView.render();
$('.main-container').html(blogsAdminView.el);
},
error: function(blogs, error) {
console.log(error);
}
});
}
然后传递要在#admin-tpl
呈现的username
:
BlogsAdminView = Parse.View.extend({
template: Handlebars.compile($('#admin-tpl').html()),
render: function() {
var collection = {
// Pass in username as variable to be used in the template
username: this.options.username,
blog: this.collection.toJSON()
};
this.$el.html(this.template(collection));
}
})
步骤4:$ container
最后,我们可以将$('.main-container')
为变量,以避免进行多个查询。
var $container = $('.main-container');
只需将所有$('.main-container')
替换$container
。
结论
首先,恭喜您成功! 这是一个很长时间的会议,但是您已经清理了整个项目。 此外,您还向博客添加了ACL,实现了静态URL,并进行了大量其他修复。 现在,这是一个非常可靠的项目。
在下一个会话中,我们将加快速度并添加三个新功能:单个博客视图,删除博客和注销,因为现在您已经对Parse.js有了很好的了解,并且可以更快地前进。 我建议您考虑一下如何提前编写这些函数,以便您可以稍微测试一下知识。 除此之外,请继续关注!
翻译自: https://code.tutsplus.com/tutorials/get-started-building-your-blog-with-parsejs-refactor--cms-24208