小程序 graphql_GraphQL應用程序中的五個常見問題(以及如何解決)

小程序 graphql

by Sacha Greif

由Sacha Greif

GraphQL應用程序中的五個常見問題(以及如何解決) (Five Common Problems in GraphQL Apps (And How to Fix Them))

了解如何釋放GraphQL的強大功能而不會遭受缺點 (Learn to unlock the power of GraphQL without suffering its drawbacks)

GraphQL is all the rage these days, and for good reason: it’s an elegant approach that solves many of the problems associated with traditional REST APIs.

GraphQL如今風靡一時,這是有充分理由的:這是一種優雅的方法,可以解決與傳統REST API相關的許多問題。

Yet I’d be lying if I told you that GraphQL doesn’t come with its own set of issues. And if you’re not careful, these issues might not only lead to a bloated codebase, but even to a dramatically slowed-down app.

但是,如果我告訴您GraphQL沒有它自己的問題,那我會撒謊。 而且,如果您不小心,這些問題可能不僅會導致代碼庫過大,甚至會導致應用程序速度大大降低。

I’m talking about problems such as:

我說的是諸如以下的問題:

  • Schema duplication

    模式復制

  • Server/client data mismatch

    服務器/客戶端數據不匹配

  • Superfluous database calls

    多余的數據庫調用

  • Poor performance

    表現不佳

  • Boilerplate overdose

    樣板過量

I’m willing to bet your app suffers from at least one of them. Good news is, none of them are incurable!

我敢打賭,您的應用至少會遭受其中之一的困擾。 好消息是,沒有一個是無法治愈的!

For each issue, I’ll describe the problem, and then explain how I’m addressing it inside Vulcan, a React/GraphQL open-source framework I’ve been working on over the past year (you should check it out!). But hopefully, you’ll be able to apply the same strategies to your own codebase whether you use Vulcan or not.

對于每個問題,我將描述問題,然后解釋如何在過去一年來一直在致力于的React / GraphQL開源框架Vulcan中解決它(您應該檢查一下!)。 但是希望無論您是否使用Vulcan,您都可以將相同的策略應用于自己的代碼庫。

問題:模式復制 (Problem: Schema Duplication)

One of the first things you realize when coding a GraphQL back-end from scratch is that it involves a lot of similar-but-not-quite-identical code, especially when it comes to schemas.

從頭開始編寫GraphQL后端時,您會意識到的第一件事是,它涉及許多相似但不完全相同的代碼,尤其是涉及架構時。

Namely, you need one schema for your database, and another one for your GraphQL endpoint. Not only is it frustrating to have to write more or less the same thing twice, but you now have two independent sources of truths that you need to constantly keep in sync.

即,您需要一個數據庫架構,另一個需要GraphQL端點。 不得不多寫或少寫兩次相同的東西不僅令人沮喪,而且您現在擁有兩個獨立的真理來源,需要不斷保持同步。

解決方案:GraphQL模式生成 (Solution: GraphQL Schema Generation)

A number of solutions to this problem have emerged in the GraphQL ecosystem. For example, PostGraphile generates a GraphQL schema from your PostgreSQL database, and Prisma will also help you generate types for your queries and mutations.

GraphQL生態系統中出現了許多解決此問題的方法。 例如, PostGraphile從PostgreSQL數據庫生成GraphQL模式, Prisma也將幫助您生成查詢和變異的類型。

I also remember hearing Laney Zamore & Adam Kramer from the GraphQL team describe how they directly generated their GraphQL schema from their PHP type definitions.

我還記得GraphQL團隊的Laney Zamore和Adam Kramer講述了他們如何直接從PHP類型定義中生成GraphQL模式。

For Vulcan, I independently stumbled on a very similar solution. I was using SimpleSchema to describe my schemas as JavaScript objects, and I started simply by converting JavaScript’s String type into a GraphQL String, Number into Int or Float, and so on.

對于Vulcan,我獨立地偶然發現了一個非常相似的解決方案。 我當時使用SimpleSchema將模式描述為JavaScript對象,然后開始將JavaScript的String類型轉換為GraphQL String ,將Number轉換為IntFloat ,等等。

So this JavaScript field:

所以這個JavaScript字段:

title: {  type: String}

Would become this GraphQL field:

將成為此GraphQL字段:

title: String

But of course, a GraphQL schema can also have custom types: User, Comment, Event, and so on.

但是,當然,GraphQL架構也可以具有自定義類型: UserCommentEvent等等。

I didn’t want to add too much magic to the schema generation step, so I came up with field resolvers, a simple way to let you specify these custom types. So that this JavaScript field:

我不想在架構生成步驟中添加太多的魔力,所以我想出了字段解析器 ,這是一種讓您指定這些自定義類型的簡單方法。 這樣這個JavaScript字段:

userId{  type: String,  resolveAs: {    fieldName: 'user',    type: 'User',    resolver: document => {      return Users.findOne(document.userId)    }  }}

Becomes:

成為:

user: User

As you can see, we’re defining the actual resolver function on the field as well, since it’s also directly related to the GraphQL field.

如您所見,由于它也與GraphQL字段直接相關,因此我們也在該字段上定義了實際的解析程序功能。

So whether you use something like PostGraphile or write your own schema generation code, I encourage you to avoid schema duplication in your own app.

因此,無論您使用PostGraphile之類的東西還是編寫自己的模式生成代碼,我都建議您避免在自己的應用程序中重復模式。

Or of course, you can also use a hosted service such as Graphcool to manage your schema using their dashboard and bypass that issue entirely.

或者,當然,您也可以使用諸如Graphcool之類的托管服務通過其儀表板管理您的架構,并完全繞開該問題。

問題:服務器/客戶端數據不匹配 (Problem: Server/Client Data Mismatch)

As we’ve just seen, your database and GraphQL API will have different schemas, which translate into different document shapes.

如我們所見,您的數據庫和GraphQL API將具有不同的架構,這些架構將轉換為不同的文檔形狀。

So while a post fresh out of the database will have a userId property, the same post as fetched through your API will instead have a user property.

因此,雖然從數據庫中重新post將具有userId屬性,但與通過您的API提取的post相同,將具有一個user屬性。

This means that getting a post author’s name on the client will look like:

這意味著在客戶端上獲得帖子作者的姓名將類似于:

const getPostNameClient = post => {  return post.user.name}

But on the server, it’ll be a different story altogether:

但是在服務器上,這將是完全不同的故事:

const getPostNameServer = post => {  const postAuthor = Users.findOne(post.userId)  return postAuthor.name}

This can be a problem anytime you’re trying to share code between client and server to simplify your codebase. And even beyond that, it means you’re missing out on GraphQL’s great approach to data querying on the server.

每當您嘗試在客戶端和服務器之間共享代碼以簡化代碼庫時,這都是一個問題。 甚至除此之外,這意味著您會錯過GraphQL在服務器上進行數據查詢的出色方法。

I recently felt that pain when trying to build a system to generate weekly newsletters: each newsletter was composed of multiple posts and comments, along with info about their authors; in other words, a perfect use case for GraphQL. But this newsletter generation was happening on the server, meaning I didn’t have a way to query my GraphQL endpoint…

最近,當我嘗試構建一個每周新聞通訊系統時,我感到非常痛苦:每個新聞通訊由多個帖子和評論以及有關作者的信息組成; 換句話說,是GraphQL的完美用例。 但是,此新聞通訊正在服務器上發生,這意味著我無法查詢GraphQL端點…

解決方案:服務器到服務器的GraphQL查詢 (Solution: Server-to-Server GraphQL Queries)

Or did I? It turns out that you can run server-to-server GraphQL queries just fine! Just pass your GraphQL executable schema to the graphql function, along with your GraphQL query:

還是我? 事實證明,您可以運行服務器對服務器的GraphQL查詢! 只需將您的GraphQL可執行模式與GraphQL查詢一起傳遞給graphql函數 :

const result = await graphql(executableSchema, query, {}, context, variables);

In Vulcan, I generalized this pattern into a runQuery helper, and I also added queryOne functions to each collection. These act just like MongoDB’s findOne except they return the document as fetched through the GraphQL API:

在Vulcan中, 我將此模式概括為runQuery helper ,并且還向每個集合添加了queryOne函數。 這些行為與MongoDB的findOne除了它們返回通過GraphQL API獲取的文檔:

const user = await Users.queryOne(userId, {  fragmentText: `    fragment UserFragment on User {      _id      username      createdAt      posts{        _id        title      }    }  `});

Server-to-server GraphQL queries have helped me drastically simplify my code. It let me refactor my newsletter generation call from a mess of successive database calls and loops to a single GraphQL query:

服務器到服務器的GraphQL查詢幫助我極大地簡化了代碼。 它使我可以從一堆連續的數據庫調用和循環中重構我的新聞通訊生成調用,以循環到單個GraphQL查詢:

query NewsletterQuery($terms: JSON){  SiteData{    title  }  PostsList(terms: $terms){    _id    title    url    pageUrl    linkUrl    domain    htmlBody    thumbnailUrl    commentsCount    postedAtFormatted    user{      pageUrl      displayName    }    comments(limit: 3){      user{        displayName        avatarUrl        pageUrl      }      htmlBody      postedAt    }  }}

The takeaway here: don’t see GraphQL as just a pure client-server protocol. GraphQL can be used to query data in any situation, including client-to-client with Apollo Link State or even during a static build process with Gatsby.

這里的要點:不要將GraphQL視為純粹的客戶端-服務器協議。 GraphQL可用于在任何情況下查詢數據,包括具有Apollo鏈接狀態的客戶端到客戶端,甚至在使用Gatsby的靜態構建過程中。

問題:多余的數據庫調用 (Problem: Superfluous Database Calls)

Imagine a list of posts, each of which has a user attached to it. You now want to display 10 of these posts, along with the name of their author.

想象一下一個帖子列表,每個帖子都具有一個用戶。 現在,您要顯示其中的10條帖子,以及其作者的姓名。

With a typical implementation, this would mean two database calls. One to get the 10 posts, and one to get the 10 users corresponding to these posts.

對于典型的實現,這將意味著兩個數據庫調用。 一個獲得10個帖子,一個獲得10個與這些帖子對應的用戶。

But what about GraphQL? Assuming our posts have a user field with its own resolver, we still have one initial database call to get the list of posts. But we now have an extra call to fetch each user per resolver, for a total of 11 database calls!

但是GraphQL呢? 假設我們的帖子有一個帶有自己的解析程序的user字段,我們仍然有一個初始數據庫調用來獲取帖子列表。 但是我們現在有一個額外的調用來為每個解析器獲取每個用戶,總共有11個數據庫調用!

Now imagine that each post also has 5 comments, each of which has an author. Our number of calls has now ballooned to:

現在想象每個帖子也有5條評論,每個評論都有一位作者。 我們的電話數量現已激增至:

  • 1 for the list of posts

    帖子列表1
  • 10 for the post authors

    帖子作者10個
  • 10 for each sub-list of 5 comments

    每5則評論的子清單10個
  • 50 for the comment authors

    評論作者50個

For a grand total of 71 database calls to display a single view!

共顯示71個數據庫調用,以顯示單個視圖

Nobody wants to have to explain to their boss why the homepage is taking 25 seconds to load. Thankfully, there’s a solution: Dataloader.

沒人愿意向老板解釋為什么首頁要花25秒鐘來加載。 幸運的是,有一個解決方案: Dataloader 。

解決方案:數據加載器 (Solution: Dataloader)

Dataloader will let you batch and cache database calls.

Dataloader使您可以批處理和緩存數據庫調用。

  • Batching means that if Dataloader figures out that you’re hitting the same database table multiple times, it’ll batch all calls together. In our example, the 10 post authors’ and 50 comment authors’ calls would all be batched into a single call.

    批處理意味著,如果Dataloader發現您多次訪問同一數據庫表,則它將所有調用一起批處理。 在我們的示例中,10個帖子作者的呼叫和50個評論作者的呼叫將全部合并為一個呼叫。

  • Caching means that if Dataloader detects that two posts (or a post and a comment) have the same author, it will reuse the user object it already has in memory instead of making a new database call.

    緩存意味著,如果Dataloader檢測到兩個帖子(或一個帖子和一個評論)具有相同的作者,它將重用它已經在內存中擁有的用戶對象,而不是進行新的數據庫調用。

In practice you don’t always achieve perfect caching and batching, but Dataloader is still a huge help.

在實踐中,您并不總是能夠實現完美的緩存和批處理,但是Dataloader仍然是一個巨大的幫助。

And Vulcan makes using Dataloader extra easy. Out of the box, every Vulcan model includes Dataloader functions as alternatives to the “normal” MongoDB query functions.

Vulcan使得使用Dataloader變得異常容易。 開箱即用, 每個Vulcan模型都包含Dataloader函數,以替代“常規” MongoDB查詢函數。

So in addition to collection.findOne and collection.find, you can use collection.loader.load and collection.loader.loadMany.

因此,除了collection.findOnecollection.find ,您還可以使用collection.loader.loadcollection.loader.loadMany

The one limitation is that Dataloader only works when querying using document IDs. So you can use it to query for a document whose ID is already known, but you’ll still need to hit your database if you want to ask for, say, the most recently created post.

一個限制是Dataloader僅在使用文檔ID查詢時才起作用。 因此,您可以使用它來查詢ID已知的文檔,但是如果您要查詢(例如)最近創建的帖子,仍然需要打數據庫。

問題:性能不佳 (Problem: Poor Performance)

Even with Dataloader enabled, complex views can still trigger multiple database calls, which in turn can make for slow loading times.

即使啟用了Dataloader,復雜的視圖仍然可以觸發多個數據庫調用,這又會導致加載時間變慢。

This can be frustrating: on one hand you want to take full advantage of GraphQL’s graph traversal features (“show me the authors of the comments of the author of the post of…” etc.). But on the other hand, you don’t want your app to become slow and unresponsive.

這可能令人沮喪:一方面,您想充分利用GraphQL的圖遍歷功能(例如,“向我顯示...帖子作者的評論的作者”等)。 但另一方面,您不希望您的應用變慢且無響應。

解決方案:查詢緩存 (Solution: Query Caching)

There is a solution though, which is to cache the entire GraphQL query response. Unlike Dataloader, whose scope is limited to the current request (meaning it will only cache documents within the same query), I’m talking here about caching the whole query for a period of time.

但是,有一個解決方案,就是緩存整個 GraphQL查詢響應。 不同的DataLoader,其范圍僅限于當前請求(這意味著它只會緩存在同一查詢的文件),我在這里談論緩存整個查詢一段時間。

Apollo Engine is a great way to do just that. It’s a hosted service that provides analytics about your GraphQL queries, but it also has a very useful caching feature.

Apollo Engine是做到這一點的好方法。 它是一項托管服務,可提供有關GraphQL查詢的分析,但它也具有非常有用的緩存功能 。

Vulcan comes with a built-in Engine integration, you just need to add your API key to your settings file. You can then add the enableCache: true argument to your GraphQL queries to cache them using Engine.

Vulcan帶有內置的Engine集成,您只需要將API密鑰添加到設置文件中即可。 然后,您可以向您的GraphQL查詢添加enableCache: true參數,以使用Engine對其進行緩存。

Or, using Vulcan’s built-in data-loading higher-order components:

或者,使用Vulcan的內置數據加載高階組件 :

withList({  collection: Posts,   enableCache: true})(PostsList)

The beauty of this approach is that you can easily control which queries are cached and which aren’t, even for the same resolver. For example, you might want to cache the list of recent posts featured on your frequently-accessed homepage, but not the full list of posts available on your archives page.

這種方法的優點在于,即使對于同一個解析器,您也可以輕松控制哪些查詢被緩存,哪些不緩存。 例如,您可能想緩存您經常訪問的主頁上的最新帖子列表,而不是存檔頁面上可用帖子的完整列表。

A final note: caching might not always be possible. For example, it’s not advisable for data that changes frequently, or for data that depends on the currently logged-in user.

最后一點:并非總是可能進行緩存。 例如,對于頻繁更改的數據或依賴于當前登錄用戶的數據,建議不要這樣做。

問題:樣板過量 (Problem: Boilerplate Overdose)

This is by no means an issue exclusive to GraphQL apps, but it’s true that they generally require you to write a lot of similar boilerplate code.

這絕不是GraphQL應用程序獨有的問題,但確實,它們通常需要您編寫很多類似的樣板代碼。

Typically, adding a new model (e.g. Comments) to your app will involve the following steps:

通常,向您的應用添加新模型(例如Comments )將涉及以下步驟:

  • Writing a resolver to get a list of comments.

    編寫解析器以獲取評論列表。
  • Writing a higher-order component (a.k.a. container) to load that list of comments.

    編寫一個高階組件(也稱為容器)以加載該評論列表。
  • Optionally, writing a resolver to get a single comment by ID or slug along with the corresponding higher-order component.

    (可選)編寫解析器以獲取ID或Slug以及相應的高階組件的單個注釋。
  • Writing mutations for inserting a new comment, editing a comment, and deleting a comment.

    編寫用于插入新注釋,編輯注釋和刪除注釋的變體。
  • Adding the corresponding forms and form-handling code.

    添加相應的表單和表單處理代碼。

That’s a whole lot of CRUD!

這是很多CRUD!

解決方案:通用解析器,突變和高階組件 (Solution: Generic Resolvers, Mutations, and Higher-Order Components)

Vulcan’s approach is to give you smart, easy-to-use generic options for each of these. You’ll get:

Vulcan的方法是為每個選項提供智能,易于使用的通用選項。 你會得到:

  • Default resolvers for displaying lists of documents and single documents.

    用于顯示文檔列表和單個文檔的默認解析器 。

  • Pre-made higher-order components for loading a list of documents or a single document.

    預制的高級組件,用于加載文檔列表或單個文檔。

  • Default mutation resolvers for inserting, editing, and removing documents.

    用于插入,編輯和刪除文檔的默認突變解析器 。

  • Generated forms based on your schema that work with all the above.

    根據您的架構生成的表單可與以上所有功能一起使用。

These are all written in a generic enough way that they’ll work with any new model out of the box.

這些都以足夠通用的方式編寫,可以與任何新模型一起使用。

To be sure, this “one-size-fits-all” approach is not without its downsides. For example, because queries are generated dynamically by the generic higher-order components, it’s a bit harder to use static queries.

可以肯定的是,這種“千篇一律”的方法并非沒有缺點。 例如,由于查詢是由通用的高階組件動態生成的,因此使用靜態查詢會有點困難。

But this strategy is still a great way to get started, at least until you have time to refactor each part of your app to a more tailor-made solution.

但是,至少在您有時間將應用程序的每個部分重構為更量身定制的解決方案之前,這種策略仍然是入門的好方法。

GraphQL is still relatively new, which means that while everybody is busy extolling its virtues, it’s easy to overlook the very real challenges involved with building GraphQL apps.

GraphQL還是一個??相對較新的概念,這意味著盡管每個人都在忙于贊美自己的優點,但很容易忽略構建GraphQL應用程序所涉及的真正挑戰。

Thankfully these challenges all have solutions, and the more we discuss them (the Vulcan Slack is a great place for that by the way!), the better these solutions will become!

值得慶幸的是,這些挑戰都有解決方案,而我們討論的內容越多(順便說一下, Vulcan Slack是一個絕佳的選擇!),這些解決方案將變得更好!

翻譯自: https://www.freecodecamp.org/news/five-common-problems-in-graphql-apps-and-how-to-fix-them-ac74d37a293c/

小程序 graphql

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/394943.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/394943.shtml
英文地址,請注明出處:http://en.pswp.cn/news/394943.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

又拍云 php5月18號那,又拍云文檔中心

移動流量平臺概述又拍云手機流量營銷平臺,整合移動、電信、聯通三大運營商流量資源,將強大的流量營銷服務,通過接口等形式提供給商家合作伙伴,幫助商家開展品牌宣傳、APP/游戲/微信公眾號/網站的拉新與促活等多種營銷活動。通過接…

SQL SERVER2000將多行查詢結果拼接到一行數據及函數的創建

處理前的查詢結果如上圖: 通過借助SQL變量的定義 DECLARE Scope varchar(1000) DECLARE Num int SET Scope SET Num 1 SELECT ScopeScopeconvert(varchar(8),Num)、DescScope DescOper;, Num Num1 From fuel_contractQualityNew Where ContractID0120090001…

kindeditor簡單使用

先引入&#xff1a; <script src"/static/jquery-3.3.1.min.js"></script><script src"/static/kindeditor-4.1.11-zh-CN/kindeditor/kindeditor-all.js"></script> 基本使用參數&#xff1a; $(function () {KindEditor.create(#…

windows nginx c++讀取請求數據_輕松應對百萬并發的Nginx,搞懂LinuxC/C++這些技術棧升職加薪...

在深入了解 Nginx 各種原理及在極端場景下的一些錯誤場景處理時&#xff0c;需要首先理解什么是網絡事件。Nginx 是一個事件驅動的框架&#xff0c;所謂事件主要指的是網絡事件&#xff0c;Nginx 每個網絡連接會對應兩個網絡事件&#xff0c;一個讀事件一個寫事件。在深入了解 …

github 6月開源項目_我的開源項目如何在短短5天內在GitHub上贏得6,000顆星

github 6月開源項目Last month I launched two open source projects on GitHub. A few days later, my Front-End Checklist was showing more than 6,000 stars (17,000 as of writing). And I got 600 stars for my Resources-Front-End-Beginner project!上個月&#xff0c…

如何成為一位牛逼的高手

鄭昀 演講稿 創建于2016/9/15 最后更新于2016/9/21 很多人都在思考一個問題&#xff1a; 怎樣才能想出來一個牛逼的 idea&#xff1f; 有一位喜歡抽煙喝酒燙頭的大師 給出了答案&#xff1a; 這事兒吧&#xff0c;簡單&#xff0c;一共分兩步。 第一步先讓自己成為一個牛逼的人…

thinkphp html php文件,ThinkPHP生成靜態HTML文件

View.class.php/*** 加載模板和頁面輸出 可以返回輸出內容* access public* param string $templateFile 模板文件名* param string $charset 模板輸出字符集* param string $contentType 輸出類型* param string $content 模板輸出內容* param string $prefix 模板緩存前綴* r…

day01語法python入門_2

十&#xff1a;while循環 1.基本循環 while條件#循環體#如果條件為真&#xff0c;那么循環體則執行#如果條件為假&#xff0c;那么循環體不執行。2.break break 用于退出所有循環 while True:print "123"breakprint "456"3.continue while True:print &quo…

Python dict() 函數

Python dict() 函數 Python 內置函數 描述 dict() 函數用于創建一個字典。 語法 dict 語法&#xff1a; class dict(**kwarg) class dict(mapping, **kwarg) class dict(iterable, **kwarg) 參數說明&#xff1a; **kwargs -- 關鍵字mapping -- 元素的容器。iterable -- 可迭代…

貝塞爾曲線:原理、自定義貝塞爾曲線View、使用!!!

一、原理 轉自&#xff1a;http://www.2cto.com/kf/201401/275838.html Android動畫學習Demo(3) 沿著貝塞爾曲線移動的Property Animation Property Animation中最重要&#xff0c;最基礎的一個類就是ValueAnimator了。Property Animation利用ValueAnimator來跟蹤記錄對象屬性已…

ios pusher使用_如何使用JavaScript和Pusher構建實時圖

ios pusher使用by Rahat Khanna通過拉哈特漢娜 如何使用JavaScript和Pusher構建實時圖 (How to build a Realtime Graph using JavaScript and Pusher) The world needs everything uber-fast now. There are plenty of data streams being generated by different systems ev…

python數據分析與基礎實戰_《python數據分析與挖掘實戰》基礎概念

數據建模.png 數據挖掘的基本任務:利用分類與預測、聚類分析、關聯規則、時序模式、偏差檢測、智能推薦等方法&#xff0c;幫助企業提取數據中蘊含的商業價值&#xff0c;提高企業競爭力。 數據探索&#xff1a;異常值分析、缺失值分析、相關分析和周期性分析。 數據預處理:數據…

簡述JAVA線程調度的原理,Rxjava原理(二)--線程調度

1. 創建線程池和線程管理策略分析// 在開發中使用Rxjava來完成線程切換會調用到以下方法(還有幾個就不一一列舉了&#xff0c;原理一樣的)&#xff0c;那么就從這里開始分析Schedulers.io()Schedulers.computation()Schedulers.newThread()AndroidSchedulers.mainThread()當我們…

[前端隨筆][css] 彈性布局

說在前面 彈性布局&#xff0c;顧名思義就是有彈性&#xff0c;能夠根據屏幕/當前空間大小自由伸縮的。使用彈性布局可以很好的適應各種尺寸的客戶端。 關鍵代碼 display:flex;    設定元素為彈性布局  <文檔傳送門> box-flex: 參數;   設定元素為彈性布局  &…

不同的模塊中定義同樣的宏為不同的值合法嗎_如何創建自定義的建模規范

本文摘要&#xff1a;主要介紹如何創建自定義的建模規范檢查&#xff0c;以及在建模規范檢查中&#xff0c;如何增加自動修正模型使之符合規范。比如我們想創建一個自定義的規則&#xff0c;對于constant模塊&#xff0c;1. 如果value是參數的話&#xff0c;則輸出數據類型必須…

DBCP連接池配置常用參數說明

參數默認值說明username\傳遞給JDBC驅動的用于建立連接的用戶名password\傳遞給JDBC驅動的用于建立連接的密碼url\傳遞給JDBC驅動的用于建立連接的URLdriverClassName\使用的JDBC驅動的完整有效的Java 類名initialSize 0初始化連接:連接池啟動時創建的初始化連接數量,1.2版本后…

科大訊飛 ai算法挑戰賽_為井字游戲挑戰構建AI算法

科大訊飛 ai算法挑戰賽by Ben Carp通過本卡爾普 為井字游戲挑戰構建AI算法 (Building an AI algorithm for the Tic-Tac-Toe challenge) As part of the freeCodeCamp curriculum, I was challenged build a Tic-Tac-Toe web app. It was a real pleasure.作為freeCodeCamp課程…

js serialize php 解,[轉]JavaScript 版本的 PHP serialize/unserialize 完整實現

下載: phpserializer.js/* phpserializer.js - JavaScript to PHP serialize / unserialize class.** This class is designed to convert php variables to javascript* and javascript variables to php with a php serialize unserialize* compatible way.** Copyright (C) …

Git 的 .gitignore 配置

.gitignore 配置文件用于配置不需要加入版本管理的文件&#xff0c;配置好該文件可以為我們的版本管理帶來很大的便利&#xff0c;以下是個人對于配置 .gitignore 的一些心得。 1、配置語法&#xff1a; 以斜杠“/”開頭表示目錄&#xff1b; 以星號“*”通配多個字符&#xff…

wsdl文件是怎么生成的_C++ 動態庫.dll的生成---超級詳細!!!

怎么將建好的工程生成.dll工程&#xff1f;1、在C中打開工程2、運行結果&#xff1a;輸出Print修改開始&#xff1a;1、打開屬性。2、修改以下內容&#xff1a;目標文件擴展名&#xff0c;由.exe--》.dll,直接刪除修改即可配置類型&#xff0c;由.exe--》.dll,下拉菜單可選擇最…