ember js搭建web_使用Ember.js构建雄心勃勃的Web应用程序

ember js搭建web

Ember.js is a solid single page application framework for building modern web applications.Before Angular and React reached critical mass, Ember.js was leading the charge in building scalable single page applications. While the spotlight may have shifted, Ember.js remains a great and viable option for developers wanting to prototype and build modern front-end clients.

Ember.js是用于构建现代Web应用程序的可靠单页应用程序框架。AngularReact达到临界质量之前, Ember.js负责构建可扩展的单页应用程序。 尽管关注点可能已经转移,但对于希望制作原型和构建现代前端客户端的开发人员来说,Ember.js仍然是一个不错的选择。

Ember is a great alternative to Angular 2 due to it's maturity. The Ember CLI was even used as inspiration for building the Angular 2 CLI to help developers scaffold their applications more effectively. Compared to React, Ember offers a bit more out of the box such as a routing and a well defined model structure.

由于其成熟度,Ember是Angular 2的绝佳替代品。 Ember CLI甚至被用作构建Angular 2 CLI的灵感,以帮助开发人员更有效地搭建其应用程序。 与React相比,Ember提供了更多现成的功能,例如路由和定义明确的模型结构。

In today's tutorial we are going to build a single page application with Ember.js 2.x. Ember.js 2.x, like Angular 2, is more of a framework and boasts a 10x performance improvement over the 1.x iteration. For our backend, instead of building and deploying a traditional web server, we'll build a Webtask that will provide server-side functionality. With the stage set, let's get started.

在今天的教程中,我们将使用Ember.js 2.x构建一个单页应用程序。 与Angular 2一样,Ember.js 2.x更像是一个框架,与1.x迭代相比,其性能提高了10倍。 对于我们的后端,我们将构建一个将提供服务器端功能的Webtask,而不是构建和部署传统的Web服务器。 设置好舞台之后,我们开始吧。

使用Webtask构建后端 (Building the Back-end with Webtask)

The application we'll build with Ember.js will be an crowdsourcing app for events. The admins of the app will create events that the users of the platform can vote on. Each event will have a certain requirement of votes needed before that event can take place. Everyone will be able to view the events, but only authenticated users will be able to vote on events. We'll start by building our Webtask powered backend.

我们将使用Ember.js构建的应用程序将成为事件的众包应用程序。 该应用程序的管理员将创建事件,平台用户可以对其进行投票。 每个事件在活动发生前都会有一定的投票要求。 每个人都可以查看事件,但是只有经过身份验证的用户才能对事件进行投票。 我们将从构建支持Webtask的后端开始。

Webtask is a serverless, function-as-a-service, platform developed by Auth0 that allows developers to build micro-services and expose them via HTTP. If you don't already have a Webtask account, you can sign up for one free of charge here. Once you are signed up, you will need to install the Webtask CLI on your machine by running npm install wt-cli -g. Node.js and NPM are the only prerequisites needed.

Webtask是由Auth0开发的无服务器,功能即服务的平台,允许开发人员构建微服务并通过HTTP公开它们。 如果您还没有Webtask帐户,则可以在此处免费注册一个。 注册后,您将需要通过运行npm install wt-cli -g在计算机上安装Webtask CLINode.jsNPM是唯一需要的先决条件。

Once you have the Webtask CLI installed, run the wt-cli init command and you will be asked for an email or phone number. Provide one of these, and you will receive a confirmation code that you will need to input in the CLI to complete the authentication process. Once that is done you are ready to write and deploy Webtasks.

一旦安装了Webtask CLI,运行wt-cli init命令,系统将要求您提供电子邮件或电话号码。 提供其中之一,您将收到一个确认代码,您需要在该代码中输入CLI才能完成身份验证过程。 完成之后,您就可以编写和部署Webtasks了。

There are many different approaches to writing Webtasks. We can write a Webtask that performs a single function, such as send a welcome email when a user registers, or we can write an entire application within the Webtask. We'll opt for the second option and build our entire backend implementation with a single Webtask. We want to focus on Ember.js, so we'll quickly go over this section. You can always learn more about how Webtask works by reading the docs.

有许多不同的编写Web任务的方法。 我们可以编写执行单个功能的Webtask,例如在用户注册时发送欢迎电子邮件,也可以在Webtask中编写整个应用程序。 我们将选择第二个选项,并使用单个Webtask构建整个后端实现。 我们希望专注于Ember.js,因此我们将快速浏览本节。 通过阅读文档,您始终可以了解有关Webtask如何工作的更多信息。

Our Webtask will have four routes. The /events route will return a list of all available events, the /events/:id route will return a single event, a /events/:id PUT route will increment the vote count, and finally the ‘/seed' route will seed our database (Webtask storage) with some initial events to vote on.

我们的Webtask将有四个路线。 /events路由将返回所有可用事件的列表, /events/:id路由将返回单个事件, /events/:id PUT路由将增加投票计数,最后'/ seed'路由将成为种子我们的数据库(Webtask存储)中有一些初始事件需要投票。

Take a look at our backend implementation in the code below. The Webtask we are building will be very similar to a traditional Express.js application with some Webtask specific code. If any of the concepts do not make sense or you'd like some additional resources, check out the Webtask docs, specifically on storage and authentication to learn more. We will store this code in a file called api.js.

在下面的代码中查看我们的后端实现。 我们正在构建的Webtask与带有某些Webtask特定代码的传统Express.js应用程序非常相似。 如果有任何概念没有意义,或者您需要一些其他资源,请查阅Webtask文档 ,特别是有关存储身份验证的 文档 ,以了解更多信息。 我们会将这些代码存储在一个名为api.js的文件中。


// Get our dependencies
var app = new (require('express'))();
var wt = require('webtask-tools');

// Define the events route which will retrieve a list of all events
app.get('/events', function(req, res){
    req.webtaskContext.storage.get(function (error, data) {
        if (error) return res.send(error);
        res.json({event: data});
    });
})

// Return a specific event based on the event ID attribute
app.get('/events/:id', function(req,res){
  req.webtaskContext.storage.get(function(error, data){
    if(error) return res.send(error);
    for(var i = 0; i < data.length; i++){
      if(req.params.id == data[i].id){
        res.json({event : data[i]})
      }
    }
  })
})

// The PUT request to the events/:id route will increment the vote count of the particular event
app.put('/events/:id', function(req, res){
  req.webtaskContext.storage.get(function(error, data){
    for(var i = 0; i < data.length; i++){
      if(req.params.id == data[i].id){
        data[i].votes += 1;
        req.webtaskContext.storage.set(data, function(err){
          res.json({status: 'ok'})
        })
      }
    }
  })
})

// Once our Webtask is live, we'll hit this route once, to seed our event database
app.get('/seed', function(req, res){
  req.webtaskContext.storage.get(function (error, data) {
    if (error) return cb(error);
      data = events();
      req.webtaskContext.storage.set(data, function (error) {
        if (error) return cb(error);
        res.json({status:'ok'});
      });
  });
})

module.exports = wt.fromExpress(app)

// This function will return our seed data.
function events(){
  return [
    {
      id: 10432,
      name : "Meet and Greet: Kobe Bryant",
      description: "See the legendary Kobe Bryant talk about his career with the NBA and how he became one of the greatest players of all time.",
      img : "",
      votes: 10289,
      required: 25000,
      featured: true
    },
    {
      id: 14582,
      name : "Marvel vs. DC at San Diego Comic Con",
      description: "Watch the battle between the greatest superheros at Comic Con 2017.",
      img : "",
      votes: 14900,
      required: 20000,
      featured: false
    },
    {
      id: 42000,
      name : "AMA: Elon Musk",
      description: "Ask Elon Musk anything. The CEO of Tesla and Space X has agreed to answer any and all of your questions.",
      img : "",
      votes: 10289,
      required: 10000,
      featured: false
    },
    {
      id: 54200,
      name : "Secret Event",
      description: "This could be anything. Vote to find out!!!",
      img : "",
      votes: 4754,
      required: 7500,
      featured: false
    },
    {
      id: 55900,
      name : "Meet the Developers",
      description: "Meet the developers building this awesome platform.",
      img : "",
      votes: 5900,
      required: 5000,
      featured: false
    },
  ]
}



With the implementation in place, we are ready to deploy our backend. Run the wt-cli create api.js command in the directory where your newly created api.js file resides and in a few seconds your Webtask will be created and deployed. Head over to the URL provided in the CLI and you'll see your code running. The first endpoint you should go to should be the /seed route as this will seed your Webtask storage with some events. So far so good. Let's get to building our front-end next.

完成实施后,我们就可以部署后端了。 在新创建的api.js文件所在的目录中运行wt-cli create api.js命令,然后在几秒钟内将创建并部署Webtask。 转到CLI中提供的URL,您将看到代码正在运行。 您应该转到的第一个端点应该是/seed路由,因为这将为您的Webtask存储注入一些事件。 到目前为止,一切都很好。 接下来让我们构建前端。

使用Ember.js构建我们的SPA (Building our SPA with Ember.js)

Ember.js pioneered the use of a command-line interface (CLI) for easily scaffolding and aiding in the development of web applications. In building our application, we'll make use of the CLI. To install the CLI, run the npm install ember-cli -g command. Again, Node.js and NPM are prerequisites to get the CLI. Once the CLI is installed, you are ready to start building your application.

Ember.js率先使用命令行界面 (CLI)来轻松构建和帮助开发Web应用程序。 在构建应用程序时,我们将使用CLI。 要安装CLI,请运行npm install ember-cli -g命令。 同样,Node.js和NPM是获取CLI的前提条件。 一旦安装了CLI,就可以开始构建应用程序了。

To create a new Ember.js application, run ember new and a name for the app. Let's run ember new events-app. Ember will automatically create a new directory titled events-app, scaffold a basic application structure and get all the dependencies needed. This may take a few minutes to complete. Once the install is complete, navigate to the events-app directory by typing cd events-app and hitting the return key on your keyboard.

要创建新的Ember.js应用程序,请运行ember new和该应用程序的名称。 让我们运行ember new events-app 。 Ember将自动创建一个名为events-app的新目录,搭建基本的应用程序结构并获取所需的所有依赖项。 这可能需要几分钟才能完成。 安装完成后,通过键入cd events-app并按键盘上的回车键,导航到events-app目录。

To make sure our app was initialized properly, let's run the ember server command and navigate to localhost:4200 in your browser. If you see a message saying “Congratulations you made it!”, then you are good to go. If not, I would suggest rerunning the ember new command as NPM and Bower can sometimes fail to download all the dependencies correctly.

为了确保我们的应用正确初始化,让我们运行ember server命令并在浏览器中导航到localhost:4200 。 如果您看到一条消息“恭喜您成功!”,那么您就很好了。 如果没有,我建议重新运行ember new命令,因为NPM和Bower有时可能无法正确下载所有依赖项。

Scaffolding an app in this manner gives us a very basic starting point great for building applications from scratch. We have an ambitious goal in this tutorial and a lot of ground to cover so we'll use a different starter project to continue our development. We'll use the Auth0 Ember.js Quickstart seed project as we are going to be adding user authentication to our app. Many of the topics we'll cover would be exactly the same as if you continued from the scaffold we created earlier, but this will allow us to move a little faster.

以这种方式搭建应用程序为我们提供了一个非常基础的起点,非常适合从头开始构建应用程序。 在本教程中,我们有一个雄心勃勃的目标,并且有很多基础,因此我们将使用另一个入门项目来继续我们的开发。 我们将使用Auth0 Ember.js快速入门种子项目,因为我们将向应用程序添加用户身份验证。 我们将涵盖的许多主题与您继续我们之前创建的支架一样完全相同,但是这将使我们的操作更快一些。

Head over to the Auth0 Ember.js 2 Quickstart and download the seed project provided. You will need to sign up for an Auth0 account to implement the authenticated user functionality, so if you don't already have an account you can sign up for one here. Once you've downloaded the quickstart, open the directory and run npm install followed by bower install. This will download and install all of the dependencies we'll need. With the dependencies installed, run ember server and navigate to localhost:4200 to see the default quickstart application.

转到Auth0 Ember.js 2快速入门并下载提供的种子项目。 您将需要注册一个Auth0帐户以实现经过身份验证的用户功能,因此,如果您还没有一个帐户,则可以在此处注册一个帐户。 下载快速入门后,打开目录并运行npm install然后运行bower install 。 这将下载并安装我们需要的所有依赖项。 安装依赖项后,运行ember server并导航到localhost:4200以查看默认的快速入门应用程序。

Not much to it so far. Let's first configure some of the environmental settings and then we'll get on our way to building the application. Open the environement.js file located under the config directory. Within this file, navigate to the attribute titled Auth0 and change the clientID and domain settings to your Auth0 ClientID and Domain. You can find these values in your Auth0 management dashboard.

到目前为止还不多。 首先,我们配置一些环境设置,然后开始构建应用程序。 打开位于config目录下的environement.js文件。 在此文件中,导航到标题为Auth0的属性,并将clientIDdomain设置更改为Auth0 ClientID和Domain。 您可以在Auth0 管理仪表板中找到这些值。

If you have your Ember server still running, you will notice that any changes you make are reflected in real time. This is another benefit of building the app with the CLI. The ember server command runs live-sync and watches your application, any time a change is made the server is automatically restarted.

如果您的Ember服务器仍在运行,您会注意到所做的任何更改都会实时反映。 这是使用CLI构建应用程序的另一个好处。 ember server命令运行实时同步并监视您的应用程序,无论何时进行更改,服务器都会自动重新启动。

We have a pretty good scaffold of our app now. Next, we'll want to do add the Bootstrap CSS library so we can easily style our application. Open the index.html file and in the head section add the Bootstrap 3 library from a CDN. We'll get Bootstrap from MaxCDN and add the following in our index.html page: <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" > . If you look at your app now you will notice that it looks much better.

我们现在有一个非常不错的应用程序支架。 接下来,我们要添加Bootstrap CSS库,以便我们可以轻松地对应用程序进行样式设置。 打开index.html文件,然后在头部添加CDN中的Bootstrap 3库。 我们将从MaxCDN获得Bootstrap,并在index.html页面中添加以下内容: <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" > 。 如果现在查看您的应用程序,您会发现它看起来要好得多。

Let's go ahead and open the application.hbs file next. Edit the contents of the application.hbs file as follows:

让我们继续并接下来打开application.hbs文件。 如下编辑application.hbs文件的内容:

{{outlet}}

For now, we will just have the file contain the single line {{outlet}}. If you have worked with previous SPA frameworks before, you may already know what this is for, but if not, this is where we will display components based on our router. Let's go ahead and create a route to see how this functionality works. The {{main-navigation}} component that we removed displayed our top navigation. We'll come back to it later.

现在,我们仅使文件包含单行{{outlet}} 。 如果您以前使用过以前的SPA框架,则可能已经知道这是做什么用的,但是如果没有,这就是我们将根据路由器显示组件的地方。 让我们继续创建一条路线,以了解此功能的工作原理。 我们删除的{{main-navigation}}组件显示了顶部导航。 我们稍后会再讨论。

In your terminal window type the following command ember generate route events and hit enter. This command will create a couple of different files for us. The first will be an events.js file where we can add in our front-end logic for the events route. Next, an events.hbs file for our template, and lastly the Ember CLI has taken care of adding the events route to our routes.js file.

在终端窗口中,键入以下命令ember generate route events然后按Enter。 此命令将为我们创建几个不同的文件。 第一个是events.js文件,我们可以在其中添加事件路由的前端逻辑。 接下来,为我们的模板创建一个events.hbs文件,最后,Ember CLI负责将事件路由添加到我们的routes.js文件中。

For now, just go ahead and open the events.hbs file and add a title to our page. Add the following code: <h1>Events</h1>. Save the file and navigate to localhost:4200/events. You will see your title displayed. So far so good.

现在,只需打开打开events.hbs文件,然后在页面上添加标题即可。 添加以下代码: <h1>Events</h1> 。 保存文件并导航到localhost:4200/events 。 您将看到显示的标题。 到目前为止,一切都很好。

The next concept I'd like to introduce you to is components. Components in Ember.js allow us to build reusable snippets of functionality. We'll add a component that will display the details of each of our events. To create a component run ember generate component app-event. Each component you create will need to have a hyphen in it. The reason for this is compatibility. If you create a component called event and use it as <event></event> in your application and sometime in the future the W3C decides to implement an <event> tag - your application would likely break. The component we created will be implemented a little later, for now we are going to scaffold the rest of our routes.

我想向您介绍的下一个概念是组件 。 Ember.js中的组件使我们能够构建可重用的功能片段。 我们将添加一个组件,该组件将显示每个事件的详细信息。 要创建组件,请运行ember generate component app-event 。 您创建的每个组件都需要在其中带有连字符。 这样做的原因是兼容性。 如果您创建了一个名为event的组件并将其用作应用程序中的<event></event> ,并且将来某个时候W3C决定实现一个<event>标记-您的应用程序可能会损坏。 我们创建的组件将在稍后实现,目前,我们将架设其余路线。

We already have the events route that will display a list of all of our events. Next, let's create a route for displaying just a single event. Run ember generate route event. Once this is done, go ahead and open up the router.js file located under the app directory. This file contains our router data. We will want to do two things here. First we'll set a default route, to be our events route, next, we'll edit our event route to accept a route parameter. Take a look at the implementation below:

我们已经有了事件路由,它将显示所有事件的列表。 接下来,让我们创建一条仅显示单个事件的路线。 运行ember generate route event 。 完成此操作后,继续打开app目录下的router.js文件。 该文件包含我们的路由器数据。 我们将要在这里做两件事。 首先,我们将默认路由设置为事件路由,其次,我们将编辑事件路由以接受路由参数。 看一下下面的实现:


Router.map(function() {
  // Existing Routes added by the Auth0 Quickstart
  // We'll have a template for the existing index from the quick start.
  this.route(‘index');
  // Sets the default route to events
  this.route('events', { path: '/' });
  this.route('events')
  // Changes the default /event route to /event/:id where the :id is a variable
  this.route('event', {path: '/event/:id'});
});



We already had a couple of routes from the Auth0 Ember.js Quickstart, so we'll leave those as is for now, we'll just make some edits to our routes. Now that we have our routes defined, let's go and build our application.

我们已经从Auth0 Ember.js快速入门中获得了两条路线,因此我们现在将其保留不变,我们只对路线进行一些编辑。 现在我们已经定义了路由,我们开始构建应用程序。

Let's start with the root of our application. Open the main-navigation.hbs file located under templates/components. Replace the existing template code with:

让我们从应用程序的根开始。 打开位于templates/components下的main-navigation.hbs文件。 将现有的模板代码替换为:


<nav class="navbar navbar-default navbar-fixed-top">
  <div class="container-fluid">
    <div class="navbar-header">
      {{#link-to 'index' classNames='navbar-brand'}}
        Home
      {{/link-to}}
    </div>
    <ul class="nav navbar-nav navbar-left">
      {{#link-to 'events' tagName='li'}}
        <a>Events</a>
      {{/link-to}}
    </ul>
    {{! display logout button when the session is authenticated, login button otherwise }}
    {{#if session.isAuthenticated}}
      <a {{action 'logout'}} class="btn btn-danger navbar-btn navbar-right">Logout</a>
    {{else}}
      <a href="/login" class="btn btn-success navbar-btn navbar-right">Login</a>
    {{/if}}
  </div>
</nav>
 


Open the application.hbs file and add in the {{main-navigation}} component above the {{outlet}}. Check your application to make sure the new navigation bar is properly displayed. We'll also add a simple footer to our application.hbs file. Check out the completed implementation below:

打开application.hbs文件,并在{{outlet}}上方的{{outlet}} {{main-navigation}}组件中添加。 检查您的应用程序,以确保新的导航栏正确显示。 我们还将在我们的application.hbs文件中添加一个简单的页脚。 在下面查看完成的实现:


{{main-navigation}}
{{outlet}}

<footer>
  <p class="text-center text-muted"><small>&copy; 2016 Events!</small></p>
</footer>



If you navigate to localhost:4200 now, you'll see the header and footer as well as the content of whichever page you are on displayed. We've added a bit of Ember.js functionality with the logical condition check, let's continue building our app. The next page we're going to build out is the homepage and events page. Open the events.hbs file and add the following code:

如果现在导航到localhost:4200 ,则将显示页眉和页脚以及所显示页面的内容。 我们通过逻辑条件检查添加了一些Ember.js功能,让我们继续构建我们的应用程序。 我们要扩展的下一页是主页和事件页面。 打开events.hbs文件并添加以下代码:


<div class="jumbotron text-center">
  <h1>Events</h1>
</div>

<div class="container">
  <div class="row">
    {{#each model as |event|}}
      {{app-event event=event}}
    {{/each}}
  </div>
</div>



Open the app-event.hbs template next and add the following code:

接下来打开app-event.hbs模板,并添加以下代码:


<div class="col-sm-6">
  <div class="panel panel-default">
    <div class="panel-heading">
      <h3 class="panel-title">{{event.name}}</h3>
    </div>
    <div class="panel-body" style="min-height: 80px;">
      {{event.description}}
    </div>
    <div class="panel-footer">
      <ul class="list-inline">
        <li><a class="btn btn-sm btn-success"><span class="glyphicon glyphicon-thumbs-up"></span> {{event.votes}}</a></li>
        <li class="pull-right">
          <a class="btn btn-sm btn-default">Required: {{event.required}}</a>
        </li>
      </ul>
    </div>
  </div>
</div>



Let's explain a bit about what is happening. When the user hits the events page (or the homepage since that is our default page). We'll load our model data and run it through a forEach loop in events page. Then, for each event we get, we'll use our app-event.hbs template and build a UI for the event passing in the data from our events page. If you look at your app now though, you will just see the header. Let's get our events from the Webtask we created and display them on the page. To be able to make requests, we'll first need to make a couple of edits to our application adapter. Open the file titled application.js located in the adapters directory. Add the following code:

让我们来解释一下正在发生的事情。 当用户点击事件页面(或主页,因为这是我们的默认页面)时。 我们将加载模型数据,并通过事件页面中的forEach循环运行它。 然后,对于收到的每个事件,我们将使用app-event.hbs模板并为事件构建UI,以将事件页面中的数据传入。 如果现在查看您的应用程序,您只会看到标题。 让我们从创建的Webtask中获取事件并将其显示在页面上。 为了能够发出请求,我们首先需要对我们的应用程序适配器进行一些编辑。 打开位于adapters目录中的标题为application.js的文件。 添加以下代码:


// We are changing our default adapter to use a REST Adapter
export default DS.RESTAdapter.extend(DataAdapterMixin, {
  // The host will be where our Webtask lives
  host: 'YOUR-WEBTASK-URL/api',
  authorizer: 'authorizer:application',
  // We will want to add an Authorization header containing our JSON Web Token with each request to our server. We'll get to this functionality a little later, but we can configure it now.
  headers : Ember.computed(function(){
    var token = JSON.parse(localStorage.getItem('ember_simple_auth:session'));

    return {"Authorization": 'Bearer ' + token.authenticated.id_token};
  })
});



With our adapter set, open up the events.js file next. Next add the following code to the events.js file:

设置好我们的适配器后,接下来打开events.js文件。 接下来,将以下代码添加到events.js文件:


import Ember from 'ember';

export default Ember.Route.extend({
  model() {
    // This will make a GET request to our webtask and get all of the events
    return this.store.findAll('event');
  }
});


Now if you visit your localhost:4200 or localhost:4200/events route you will notice that your application has crashed. Ember.js does not know how to handle the events we are returning. We'll need to build a model that will tell Ember.js how to consume the data it gets. To add a model with Ember.js, we'll run the ember generate model event command. Next open the event.js file located under the models directory and add the following code:

现在,如果您访问localhost:4200localhost:4200/events路由,您会注意到您的应用程序已崩溃。 Ember.js不知道如何处理我们返回的事件。 我们需要构建一个模型,该模型将告诉Ember.js如何使用其获取的数据。 要使用Ember.js添加模型,我们将运行ember generate model event命令。 接下来,打开位于models目录下的event.js文件,并添加以下代码:


import DS from 'ember-data';

export default DS.Model.extend({
  name: DS.attr('string'),
  description: DS.attr('string'),
  votes: DS.attr('number'),
  required: DS.attr('number'),
  featured: DS.attr('boolean')
});



Our model describes all the properties that that a particular event will have. Now if we go to localhost:4200 we'll see all of our events properly displayed. The UI looks a little weird though. We have an odd number of events. Let's make a few changes to our events.hbs file to have a much cleaner ui. We'll make the following edits in the loop where we iterate over our events:

我们的模型描述了特定事件将具有的所有属性。 现在,如果我们转到localhost:4200我们将看到正确显示了所有事件。 用户界面看起来有些奇怪。 我们发生的事件数量奇多。 让我们对events.hbs文件进行一些更改,以使用户界面更加简洁。 我们将在循环访问事件的循环中进行以下编辑:


...
{{#each model as |event|}}
      {{#if event.featured}}
        <div class="jumbotron">
          <h2>Featured</h2>
          <h1>{{event.name}}</h1>
          <p>{{event.description}}</p>
          <a class="btn btn-lg btn-primary" href="/event/{{event.id}}">View</a>
        </div>
      {{else}}
       {{app-event event=event}}
      {{/if}}
{{/each}}
...


If you look at the page now, you'll see a featured event at the very top. This looks much better. Next, let's edit our event.hbs file and add the user interface for viewing a single event. Our code will be very simple here since we are reusing a component we've already created:

如果您现在查看该页面,您将在顶部看到一个精选事件。 看起来好多了。 接下来,让我们编辑event.hbs文件,并添加用于查看单个事件的用户界面。 我们的代码在这里非常简单,因为我们正在重用已经创建的组件:


<div class="container">
  <div class="row">
      {{app-event event=model}}
  </div>
</div>



To add the functionality to retrieve and display a single event, let's go ahead and open the event.js file in our routes and add the following:

要添加检索和显示单个事件的功能,让我们继续并在路线中打开event.js文件并添加以下内容:


import Ember from 'ember';

export default Ember.Route.extend({
  // We'll capture the route parameters and use the id to retrieve a single record from our Webtask that matches the id of the event
  model(params){
    return this.store.findRecord('event', params.id);
  }
});



So far so good. Our app is really coming together. The last piece of functionality we'll add is the ability for a user to vote on which events they'd like to happen. To do this, let's open our app-event.js file under the components directory. Here we will add an action called vote which will allow a user to vote for an event. The implementation is as follows:

到目前为止,一切都很好。 我们的应用程序真的在一起了。 我们要添加的最后一个功能是用户可以对他们希望发生的事件进行投票的能力。 为此,我们打开components目录下的app-event.js文件。 在这里,我们将添加一个名为表决的操作,该操作将允许用户对事件进行投票。 实现如下:


import Ember from 'ember';

export default Ember.Component.extend({
  // We'll inject our store service
  store: Ember.inject.service(),
  actions: {
    vote: function(event) {
       var store = this.get('store');
       // We'll find the event by id and if we get an event from the Webtask, we'll increment its votes attribute by one and save the data by making a POST request to our Webtask.
       store.findRecord('event', event.id).then(function(event) {
        event.incrementProperty('votes');
        event.save();
      });
    }
  }
});



With the functionality in place, let's go ahead and add the action to our template. Open the app-event.hbs file and add the action {{action 'vote' event}} to our success button. Save the file and let's test the functionality by navigating to localhost:4200 and voting on a couple of different events. You should see the counters incremented in real time. We don't want just anyone to be able to vote though, so we'll require the user to be authenticated before they can cast a vote. Let's implement this final functionality next.

有了功能,让我们继续并将操作添加到模板中。 打开app-event.hbs文件,然后将操作{{action 'vote' event}} app-event.hbs {{action 'vote' event}}到我们的成功按钮中。 保存文件,然后通过导航到localhost:4200并对几个不同的事件进行投票来测试功能。 您应该看到计数器实时增加。 不过,我们不希望任何人都能投票,因此我们要求用户经过身份验证后才能投票。 接下来,让我们实现此最终功能。

We already have a pretty good base for authentication since we are using the Auth0 quickstart and have already done some configuration to ensure that we can implement our login system quickly. Our implementation is actually all ready to go. All we will need to ensure is that in our Auth0 management dashboard, we have localhost:4200/callback as an allowed callback URL. Once that is ready, click on the Login button and either login or register. If all went well you will be logged in and the green login button will be replaced with a red logout button.

因为我们正在使用Auth0快速入门,并且已经进行了一些配置以确保我们可以快速实现我们的登录系统,所以我们已经为身份验证奠定了良好的基础。 我们的实现实际上已经准备就绪。 我们需要确保的是在Auth0 管理仪表板中 ,将localhost:4200/callback作为允许的回调URL。 准备就绪后,单击“登录”按钮,然后登录或注册。 如果一切顺利,您将登录,绿色的登录按钮将替换为红色的注销按钮。

Now let's ensure that only users who are authenticated can make a request to our backend. Open the app-event.js. We are going to replace the current implementation with the following:

现在,让我们确保只有经过身份验证的用户才能向我们的后端发出请求。 打开app-event.js 。 我们将用以下内容替换当前的实现:


vote: function(event) {
      var store = this.get('store');
        store.findRecord('event', event.id).then(function(event) {
          event.incrementProperty('votes');
          event.save().catch(function(error){
            event.decrementProperty('votes');
            alert(‘You must be logged in to vote');
          });
      });
}



We'll also need to make one edit to our Webtask. Open up the api.js Webtask file and add the following to the module.exports function:

我们还需要对Webtask进行一次编辑。 打开api.js Webtask文件,并将以下内容添加到module.exports函数中:


...
module.exports = wt.fromExpress(app).auth0({
  clientId: function(ctx, req){return 'YOUR-AUTH0-CLIENT-ID'},
  clientSecret: function(ctx,req){return 'YOUR-AUTH0-CLIENT-SECRET'},
  domain: function(ctx,req){return 'YOUR-AUTH0-DOMAIN'},
  exclude: function (ctx, req, appPath) { return req.method === 'GET'; }
});
...



Redeploy your Webtask by running wt-cli deploy api.js. When your Webtask is finished deploying, we'll have secured the PUT method. Now when a PUT request is made to the events/:id, the Webtask will make sure that the request is accompanied by a valid JSON Web Token (JWT). If it is, then the process will continue, otherwise, the Webtask will return a 401 Unauthorized. The rest of the routes will continue to work as they have before and anyone will be able to access them. To learn more about how Webtasks are authenticated check out our docs.

通过运行wt-cli deploy api.js重新wt-cli deploy api.js 。 当您的Webtask完成部署后,我们将确保PUT方法安全。 现在,当对events/:id发出PUT请求时,Webtask将确保该请求随附有效的JSON Web令牌(JWT)。 如果是,则该过程将继续,否则,Webtask将返回“ 401未经授权”。 其余路由将继续像以前一样工作,任何人都可以访问它们。 要了解有关如何验证Webtask的更多信息,请查看我们的文档。

That's it! Today we've built a complete application with the latest release of Ember.js. We showed how you can easily add user authentication and protect your backend with Auth0. We also created an Express.js based backend with the Webtask serverless platform. I know this was a lot to digest, so if you have any questions, please let me know and I will do my best to answer them. If you are feeling adventurous on the other hand, why don't you expand on the Webtask functionality and add the ability for admins to create new events and test to see what you've learned.

而已! 今天,我们已经使用最新版本的Ember.js构建了一个完整的应用程序。 我们展示了如何轻松添加用户身份验证并使用Auth0保护后端。 我们还使用Webtask无服务器平台创建了一个基于Express.js的后端。 我知道这需要消化很多,因此,如果您有任何问题,请告诉我,我会尽力解答。 另一方面,如果您感到冒险,为什么不扩展Webtask功能并添加管理员创建新事件并测试以了解所学知识的功能。

翻译自: https://davidwalsh.name/ember-web-apps

ember js搭建web

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值