如何在二十分钟内创建聊天应用

图片



我父亲想提醒我,作为1970年代的计算机工程师,“他是编程时尚之前的程序员”。他甚至展示了几次旧的Fortran和COBOL脚本。看完这段代码后,我可以自信地说,编程今天确实很酷。



现代编程语言和开发环境的标志是开发人员只需编写更少的代码。通过使用高级语言以及许多可用的API,开源软件包和付费服务,可以快速构建应用程序-即使是那些具有复杂要求的应用程序。



比较可以证明软件开发的发展。曾几何时,建造任何房屋都始于砍伐您现场的树木。但是,材料,工具和方法迅速出现,从而使施工更快完成,对象变得更坚固,并使工人摆脱了一些基本任务。



如果建设者开采自己的钢铁,将建造多少座摩天大楼?



直到今天仍在工作的软件开发人员,在其职业生涯的曙光中“砍伐了自己的树木”。同时,近十年来史无前例的创新导致软件行业开始以与建筑业几乎相同的方式发展。



简而言之,当今的开发人员现在拥有工具,技术和最佳实践,可以更快地完成项目,获得稳定的应用程序并使开发人员免于执行低级任务。



如何制作聊天应用



让我们快速创建过去需要几天或几周的时间。我们将制作一个使用WebSockets进行实时消息传递的公共聊天室应用程序。所有现代浏览器



都原生支持WebSockets 但是,我们的目标是找出可以在工作中使用的工具,而不是重新发明它们考虑到这一点,我们将使用以下技术:





可以在此GitHub存储库中找到入门项目和完整的README文件如果您只想查看完成的应用程序,请查看公共聊天室分支。



此外,以下视频(英语)更详细地说明了每个步骤。



开始吧。



创建聊天应用程序的七个步骤:



1.项目设置



克隆启动程序项目,然后转到群聊目录。您可以自己决定是使用yarn还是npm来安装项目依赖项。无论如何,我们都需要package.json文件中指定的所有NPM软件包。



#  
git clone https://github.com/8base/Chat-application-using-GraphQL-Subscriptions-and-Vue.git group-chat
#   
cd group-chat
#  
yarn


要与GraphQL API进行交互,我们需要设置三个环境变量。使用以下命令在根目录中创建一个.env.local文件,Vue应用程序在初始化后将自动设置我们添加到该文件的环境变量。 这两个值不应更改。您只需要设置该值 如果您要使用8base工作区来通过我们的教程创建聊天应用程序,请使用您的工作区ID更新.env.local文件。如果不是,请按照8base Quickstart的步骤1和2获取工作区ID



echo 'VUE_APP_8BASE_WORKSPACE_ID=<YOUR_8BASE_WORKSPACE_ID>

VUE_APP_8BASE_API_ENDPOINT=https://api.8base.com

VUE_APP_8BASE_WS_ENDPOINT=wss://ws.8base.com' \

> .env.local




VUE_APP_8BASE_API_ENDPOINTVUE_APP_8BASE_WS_ENDPOINTVUE_APP_8BASE_WORKSPACE_ID







2.导入模式



现在我们需要准备服务器端。在该存储库的根目录中,您应该找到文件chat-schema.json要将其导入到工作区中,只需安装8base命令行并登录,然后导入架构文件。



#  8base CLI
yarn global add 8base-cli
#  CLI
8base login
#      
8base import -f chat-schema.json -w <YOUR_8BASE_WORKSPACE_ID>


3. API访问



后端的最后任务是允许公众访问GraphQL API。



在8base控制台中,转到App Services > Roles > Guest更新为帖子和用户设置的权限,以进行检查或设置为“所有记录”(如下面的屏幕快照所示)。



来宾角色确定允许发出未经身份验证的API请求的用户做什么。



图片

8base控制台中的角色编辑器。



4.编写GraphQL查询



在这一步中,我们将定义并写出聊天组件所需的所有GraphQL查询。这将帮助我们了解使用API​​通过WebSockets读取,创建和收听的数据。



以下代码应放在文件中src / utils / graphql.js阅读每个导出常量上方的注释,以了解每个查询的作用。




/* gql      graphQL */
import gql from "graphql-tag";
/* 1.    -   10  */
export const InitialChatData = gql`
{
  usersList {
    items {
      id
      email
    }
  }
  messagesList(last: 10) {
    items {
      content
      createdAt
      author {
        id
        email
      }
    }
  }
}
`;
/* 2.          */
export const CreateUser = gql`
mutation($email: String!) {
  userCreate(data: { email: $email, roles: { connect: { name: "Guest" } } }) {
    id
  }
}
`;
/* 3.   */
export const DeleteUser = gql`
mutation($id: ID!) {
  userDelete(data: { id: $id, force: true }) {
    success
  }
}
`;
/* 4.        */
export const UsersSubscription = gql`
subscription {
  Users(filter: { mutation_in: [create, delete] }) {
    mutation
    node {
      id
      email
    }
  }
}
`;
/* 5.          */
export const CreateMessage = gql`
mutation($id: ID!, $content: String!) {
  messageCreate(
    data: { content: $content, author: { connect: { id: $id } } }
  ) {
    id
  }
}
`;
/* 6.     . */
export const MessagesSubscription = gql`
subscription {
  Messages(filter: { mutation_in: create }) {
    node {
      content
      createdAt
      author {
        id
        email
      }
    }
  }
}
`;




5.配置Apollo客户端进行订阅



编写了GraphQL查询后,就该设置API模块了。



首先,让我们ApolloClient使用必需的默认值处理API客户端createHttpLink我们提供完整的工作空间端点。该代码在中src/utils/api.js



import { ApolloClient } from "apollo-boost";
import { createHttpLink } from "apollo-link-http";
import { InMemoryCache } from "apollo-cache-inmemory";
const { VUE_APP_8BASE_API_ENDPOINT, VUE_APP_8BASE_WORKSPACE_ID } = process.env;

export default new ApolloClient({
link: createHttpLink({
  uri: `${VUE_APP_8BASE_API_ENDPOINT}/${VUE_APP_8BASE_WORKSPACE_ID}`,
}),
cache: new InMemoryCache(),
});

// Note:     ,    // ApolloClient,    .


然后,我们将使用subscriptions-transport-ws处理订阅客户端isomorphic-ws该代码比以前的代码长一点,因此值得花一些时间阅读代码中的注释。



我们SubscriptionClient使用WebSockets端点和workspaceIdin参数进行初始化connectionParams然后,我们使用subscriptionClient默认导出中定义的两种方法中的一种:subscribe()close()



subscribe允许我们使用数据和错误回调创建新的订阅。当我们离开聊天室时,可以使用close方法关闭连接。



import WebSocket from "isomorphic-ws";
import { SubscriptionClient } from "subscriptions-transport-ws";
const { VUE_APP_8BASE_WS_ENDPOINT, VUE_APP_8BASE_WORKSPACE_ID } = process.env;

/**
*   ,  
*     .
*/

const subscriptionClient = new SubscriptionClient(
VUE_APP_8BASE_WS_ENDPOINT,
{
  reconnect: true,
  connectionParams: {
    /**
      * Workspace ID    ,  
*  Websocket  
*    
      */
    workspaceId: VUE_APP_8BASE_WORKSPACE_ID,
  },
},
/**
  *    WebSocket,   W3C. * ,        *WebSocket (,   NodeJS)
  */
WebSocket
);
export default {
/**
  *   ,      *'data’  'error’
  */
subscribe: (query, options) => {
  const { variables, data, error } = options;
  /**
    *     .
    */
  const result = subscriptionClient.request({
    query,
    variables,
  });
  /**
    *       * ,     , 
* subscriptionClient
    */
  const { unsubscribe } = result.subscribe({
    /**
      *       
* ,  .
      */
    next(result) {
      if (typeof data === "function") {
        data(result);
      }
    },
    /**
      *          ,  .
      */
    error(e) {
      if (typeof error === "function") {
        error(e);
      }
    },
  });
  return unsubscribe;
},
/**
  *  subscriptionClient .
  */
close: () => {
  subscriptionClient.close();
},
};
// .     SubscriptionClient   , 
// ,    .


6.编写Vue组件



现在,我们拥有创建公共聊天所需的一切。仅剩一个组件需要编写GroupChat.vue



使用纱布加载组件,让我们继续。



重要说明:每个人对美容都有自己的想法,因此我只为使组件正常工作做出了必要的最少样式。



组件脚本



首先,我们需要导入模块,简单样式和GraphQL查询。这一切都在我们的手中 src / utils

在中声明以下进口GroupChat.vue



/* API  */
import Api from "./utils/api";
import Wss from "./utils/wss";

/* graphQL  */
import {
InitialChatData,
CreateUser,
DeleteUser,
UsersSubscription,
CreateMessage,
MessagesSubscription,
} from "./utils/graphql";
/*  */
import "../assets/styles.css";


成分数据



我们可以定义要在组件的数据功能中使用的数据属性。我们需要的是一种存储聊天用户,消息,“当前”用户的名称以及尚未发送的消息的方法。可以按以下方式添加这些属性:



/* imports ... */

export default {
name: "GroupChat",
data: () => ({
  messages: [],
  newMessage: "",
  me: { email: "" },
  users: [],
}),
};


生命周期挂钩



我们的生命周期挂钩在Vue组件生命周期的不同点运行。例如,在安装或更新时。在这种情况下,我们只对创建和beforeDestroy组件感兴趣在这种情况下,我们想打开或关闭聊天订阅。



/* ... */

export default {
/*   ... */

/**
  *   ,    .
  */
created() {
  /**
    *   ,       
    */
  Wss.subscribe(UsersSubscription, {
    data: this.handleUser,
  });
  /**
    *   ,     
    */
  Wss.subscribe(MessagesSubscription, {
    data: this.addMessage,
  });
  /**
    *     (   10 )
    */
  Api.query({
    query: InitialChatData,
  }).then(({ data }) => {
    this.users = data.usersList.items;
    this.messages = data.messagesList.items;
  });
  /**
    *     ,   
    */
  window.onbeforeunload = this.closeChat;
},
/**
  *   ,    .
  */
beforeDestroy() {
  this.closeChat();
},
};


组成方法



我们需要添加一些方法来处理每个呼叫/ API响应(createMessageaddMessagecloseChat等)。所有这些都将存储在组件的method对象中。

有必要

注意一件事:大多数突变不等待也不处理答案。这是因为我们有订阅可跟踪这些突变。成功启动后,订阅将处理事件数据。 这些方法

大多数

无论如何,请阅读以下代码中的注释。



/*  ... */

export default {
/*   ... */
methods: {
  /**
    *   ,     .
    */
  createUser() {
    Api.mutate({
      mutation: CreateUser,
      variables: {
        email: this.me.email,
      },
    });
  },
  /**
    *     ID.
    */
  deleteUser() {
    Api.mutate({
      mutation: DeleteUser,
      variables: { id: this.me.id },
    });
  },
  /**
    *        ,   
*           
* .
*
*    ,      ,  
*   ,   .
    */
  handleUser({
    data: {
      Users: { mutation, node },
    },
  }) {
    ({
      create: this.addUser,
      delete: this.removeUser,
    }[mutation](node));
  },
  /**
    *      users,  , *     .
    */
  addUser(user) {
    if (this.me.email === user.email) {
      this.me = user;
    }
    this.users.push(user);
  },
  /**
    *     users  ID.
    */
  removeUser(user) {
    this.users = this.users.filter(
      (p) => p.id != user.id
    );
  },
  /*    */
  createMessage() {
    Api.mutate({
      mutation: CreateMessage,
      variables: {
        id: this.me.id,
        content: this.newMessage,
      },
    }).then(() => (this.newMessage = ""));
  },
  /**
    *        .  * ,    ,       *.
    */
  addMessage({
    data: {
      Messages: { node },
    },
  }) {
    this.messages.push(node);
  },
  /**
    *        .          beforeDestroy     .
    */
  closeChat () {
    /*     */
    Wss.close()
    /*   */
    this.deleteUser();
    /*     */
    this.me = { me: { email: '' } }
  }
},
/*  ... */
}


组件模板



最后但并非最不重要的一点是,我们有一个component GroupChat.vue 关于如何创建漂亮的用户界面,



这不是其中的一个。

以下

模式符合聊天应用程序的最低要求。使它美丽与否取决于您。就是说,让我们快速回顾一下我们在这里实现的关键标记。



往常一样,阅读代码的内联注释。



<template>
<div id="app">
  <!--
           ,     .      ..
    -->
  <div v-if="me.id" class="chat">
    <div class="header">
      <!--
           ,      ,  ,     ,   .
        -->
      {{ users.length }} Online Users
      <!--
           ,   closeChat..
        -->
      <button @click="closeChat">Leave Chat</button>
    </div>
    <!--
     ,      ,      div.  ,         ,     me.
      -->
    <div
      :key="index"
      v-for="(msg, index) in messages"
      :class="['msg', { me: msg.participant.id === me.id }]"
    >
      <p>{{ msg.content }}</p>
      <small
        ><strong>{{ msg.participant.email }}</strong> {{ msg.createdAt
        }}</small
      >
    </div>
    <!--
      newMessage.
      -->
    <div class="input">
      <input
        type="text"
        placeholder="Say something..."
        v-model="newMessage"
      />
      <!--
           ,    createMessage.
        -->
      <button @click="createMessage">Send</button>
    </div>
  </div>
  <!--
          .     ,   createUser.
    -->
  <div v-else class="signup">
    <label for="email">Sign up to chat!</label>
    <br />
    <input
      type="text"
      v-model="me.email"
      placeholder="What's your email?"
      @blur="createUser"
      required
    />
  </div>
</div>
</template>


现在已经建立了公共聊天室。如果在本地网络上打开它,则可以开始发送和接收消息。但是,要证明这是真正的群聊,请打开多个窗口并观察对话进度。



7.结论与测试



在本教程中,我们探讨了如何使用现代开发工具在几分钟内创建真实的应用程序。



我希望您也了解了如何在8base工作区中有效地初始化ApolloClientSubscriptionClient执行GraphQL查询,变异和订阅,以及有关VueJS的一些知识。



无论您是在玩手机游戏,Messenger,通知应用程序还是需要实时数据的其他项目,订阅都是一个很好的工具。现在我们才开始考虑它们。



使用8base构建聊天应用



8base是由开发人员为开发人员构建的即用型无服务器后端后端服务。8base平台使开发人员可以使用JavaScript和GraphQL构建出色的云应用程序。在此处了解有关8base平台的更多信息



All Articles