当前位置: 首页 > 编程日记 > 正文

我希望支持JavaScript GraphQL实现的API

The GraphQL schema language is great! It is certainly the best way to communicate anything about a GraphQL service. No wonder all documentations now use it!

GraphQL 模式语言很棒! 当然,这是传达与GraphQL服务有关的任何东西的最佳方法。 难怪所有文档现在都在使用它!

模式语言 (The Schema Language)

Imagine that you’re building a blog app (with GraphQL) that has "Articles" and "Comments" . You can start thinking about its API schema by basing it on what you plan for its UI. For example, the main page will probably have a list of articles and an item on that list might display a title, subtitle, author’s name, publishing date, length (in reading minutes), and a featured image. A simplified version of Medium itself if you may:

想象一下,您正在构建一个具有“ Articles”和“ Comments”的博客应用程序(使用GraphQL)。 您可以根据其UI计划来开始考虑其API模式。 例如,主页可能会包含文章列表,并且该列表上的项目可能会显示标题,副标题,作者姓名,出版日期,时长(以分钟为单位)和特色图片。 如果可以的话,Medium本身的简化版本:

We can use the schema-language to plan what you need so far for that main page. A basic schema might look like:

我们可以使用模式语言来计划到目前为止该主页所需的内容。 基本模式可能如下所示:

type Query {articleList: [Article!]!
}
type Article {id: ID!title: String!subTitle: StringfeaturedImageUrl: StringreadingMinutes: Int!publishedAt: String!author: Author!
}
type Author {name: String!
}

When a user navigates to an article, they’ll see the details of that article. We’ll need the API to support a way to retrieve an Article object by its id. Let’s say an article can also have rich UI elements like headers and code snippets. We would need to support a rich-text formatting language like Markdown. We can make the API return an article’s content in either Markdown or HTML through a field argument (format: HTML). Let’s also plan to display a "likes" counter in that view.

当用户导航到文章时,他们将看到该文章的详细信息。 我们将需要API支持一种通过ID检索Article对象的方法。 假设文章还可以包含丰富的UI元素,例如标题和代码段。 我们需要支持诸如Markdown之类的富文本格式语言。 我们可以通过字段参数( format :HTML)使API以Markdown或HTML format返回文章的内容。 我们还计划在该视图中显示一个“点赞”计数器。

Put all these ideas on paper! The schema language is the most concise structured way to describe them:

将所有这些想法写在纸上! 模式语言是描述它们的最简洁的结构化方式:

type Query {# ...article(id: String!): Article!
}
enum ContentFormat {HTMLMARKDOWN
}
type Article {# ...content(format: ContentFormat): String!likes: Int!
}

The one article’s UI view will also display the list of comments available on an article. Let’s keep the comment UI view simple and plan it to have a text content and an author name fields:

一篇文章的UI视图还将显示文章上可用的评论列表。 让我们保持注释UI视图简单,并计划它具有文本内容和作者姓名字段:

type Article {# ...commentList: [Comment!]!
}
type Comment {id: ID!content: String!author: Author!
}

Let’s focus on just these features. This is a good starting point that’s non-trivial. To offer these capabilities we’ll need to implement custom resolving logic for computed fields like content(format: HTML) and readingMinutes. We’ll also need to implement 1–1 and 1-many db relationships.

让我们仅关注这些功能。 这是一个重要的起点。 为了提供这些功能,我们需要为诸如content(format: HTML)readingMinutes类的计算字段实现自定义解析逻辑。 我们还需要实现1-1和1-db关系。

Did you notice how I came up with the whole schema description so far just by thinking in terms of the UI. How cool is that? You can give this simple schema language text to the front-end developers on your team and they can start building the front-end app right away! They don’t need to wait for your server implementation. They can even use some of the great tools out there to have a mock GraphQL server that resolves these types with random test data.

您是否注意到到目前为止,仅通过UI方面的考虑,我是如何想到整个架构描述的? 多么酷啊? 您可以将此简单的架构语言文本提供给团队中的前端开发人员,他们可以立即开始构建前端应用程序! 他们不需要等待您的服务器实施。 他们甚至可以使用一些出色的工具来拥有一个模拟GraphQL服务器,该服务器可以使用随机测试数据来解析这些类型。

The schema is often compared to a contract. You always start with a contract.
通常将模式与合同进行比较。 您总是从合同开始。

建立一个GraphQL模式 (Building a GraphQL Schema)

When you’re ready to start implementing your GraphQL service, you have 2 main options (in JavaScript) today:

准备开始实施GraphQL服务时,今天有2个主要选项(在JavaScript中):

  1. You can "build" a non-executable schema using the full schema language text that we have and then attach a set of resolver functions to make that schema executable. You can do that with GraphQL.js itself or with Apollo Server. Both support this method which is commonly known as "schema-first" or "SDL-first". I’ll refer to it here as the "full-schema-string method".

    您可以使用我们拥有的完整模式语言文本“构建”一个不可执行的模式,然后附加一组解析器函数以使该模式可执行。 您可以使用GraphQL.js本身或Apollo Server来实现 。 两者都支持这种方法,通常称为“模式优先”或“ SDL优先”。 我在这里将其称为“ 全模式字符串方法 ”。

  2. You can use JavaScript objects instantiated from the various constructor classes that are available in the GraphQL.js API (like GraphQLSchema, GraphQLObjectType, GraphQLUnionType, and many others). In this approach, you don’t use the schema-language text at all. You just create objects. This method is commonly known as "code-first" or "resolvers-first" but I don’t think these names fairly represent it. I’ll refer to it here as the "object-based method".

    您可以使用从GraphQL.js API中可用的各种构造函数类实例化JavaScript对象(例如GraphQLSchemaGraphQLObjectTypeGraphQLUnionType以及许多其他对象)。 在这种方法中,您根本不需要使用架构语言文本。 您只需创建对象。 这种方法通常称为“代码优先”或“解析程序优先”,但我认为这些名称不能公平地代表它。 我在这里将其称为“ 基于对象的方法 ”。

Both approaches have advantages and disadvantages.

两种方法都有优点和缺点。

The schema language is a great programming-language-agnostic way to describe a GraphQL schema. It’s a human-readable format that’s easy to work with. The frontend people on your team will absolutely love it. It enables them to participate in the design of the API and, more importantly, start using a mocked version of it right away. The schema language text can serve as an early version of the API documentation.

模式语言是描述GraphQL模式的一种很棒的与编程语言无关的方式。 这是一种易于阅读的格式。 您团队中的前端人员绝对会喜欢它。 它使他们能够参与API的设计,更重要的是,立即开始使用其模拟版本。 模式语言文本可以用作API文档的早期版本。

However, completely relying on the full schema language text to create a GraphQL schema has a few drawbacks. You’ll have to put in some effort to make the code modularized and clear and you have to rely on coding patterns and tools to keep the schema-language text consistent with the tree of resolvers (AKA resolvers map). These are solvable problems.

但是,完全依赖完整的模式语言文本来创建GraphQL模式有一些缺点。 您必须付出一些努力才能使代码模块化和清晰,并且您必须依靠编码模式和工具来使架构语言文本与解析器树保持一致(AKA解析器映射)。 这些是可解决的问题。

The biggest problem I see with the full-schema-string method is that you lose some flexibility in your code. You don’t have objects associated with types. You just have strings! And although these strings make your types more readable, in many cases you’ll need the flexibility over the readability.

我看到的全模式字符串方法的最大问题是,您的代码失去了灵活性。 您没有与类型关联的对象。 你只有弦! 并且尽管这些字符串使您的类型更具可读性,但在许多情况下,您需要在可读性上具有灵活性。

The object-based method is flexible and easier to extend and manage. It does not suffer from any of the mentioned problems. You have to be modular with it because your schema is a bunch of objects. You also don’t need to merge modules together because these objects are designed and expected to work as a tree.

基于对象的方法非常灵活,并且易于扩展和管理。 它没有任何上述问题。 您必须对其进行模块化,因为架构是一堆对象。 您也不需要将模块合并在一起,因为这些对象经过设计并且可以像树一样工作。

The only problem I see with the object-based method is that you have to deal with a lot more code around what’s important to manage in your modules (types and resolvers). A lot of developers see that as "noise" and you can’t blame them. We’ll work through an example to see that.

我发现基于对象的方法的唯一问题是,您必须处理更多代码,以围绕模块中重要的内容(类型和解析器)进行处理。 许多开发人员将其视为“噪音”,您不能责怪他们。 我们将通过一个示例来说明这一点。

If you’re creating a small-scope and well-defined GraphQL service, using the full-schema-string method is probably okay. However, in bigger and more agile projects I think the more flexible and more powerful object-based method is the way to go.

如果要创建一个范围较小且定义明确的GraphQL服务,则可以使用全模式字符串方法。 但是,在更大,更敏捷的项目中,我认为更灵活,更强大的基于对象的方法是可行的方法。

You should still leverage the schema-language text even if you’re using the object-based method. At jsComplete, we use the object-based method but every time the schema is built we use the graphql.printSchema function to write the complete schema to a file. We commit and track that file in the Git repository of the project and that proved to be a very helpful practice!

即使您使用的是基于对象的方法,您仍然应该使用架构语言文本。 在jsComplete ,我们使用基于对象的方法,但是每次构建架构时,我们都使用graphql.printSchema函数将完整的架构写入文件。 我们在项目的Git存储库中提交并跟踪该文件,事实证明这是非常有用的做法!

To compare the 2 methods, I’ve implemented an executable schema for the blog example we started with using both of them. I’ve omitted some code for brevity but kept what matters for the comparison.

为了比较这两种方法,我为我们从使用这两种方法开始的博客示例实现了一个可执行模式。 为了简洁起见,我省略了一些代码,但保留了重要的比较信息。

全模式字符串方法 (The full-schema-string method)

We start with the schema-language text which defines 3 main custom types (Article, Comment, and Author). The fields under the main Query type are article and articleList which will directly resolve objects from the database. However, since the GraphQL schema we planned has custom features around an article object and since we have relations that we need to resolve as well we’ll need to have custom resolvers for the 3 main custom GraphQL types.

我们从定义3种主要自定义类型( ArticleCommentAuthor )的模式语言文本开始。 主要Query类型下的字段是articlearticleList ,它们将直接从数据库中解析对象。 但是,由于我们计划的GraphQL模式在文章对象周围具有自定义功能,并且由于我们还需要解析关系,因此我们需要为3种主要的自定义GraphQL类型提供自定义解析器。

Here are a few screenshots for the code I wrote to represent the full-schema-string method. I’ve used Apollo Server here but this is also possible with vanilla GraphQL.js (and a bit more code).

这是我编写的代表全模式字符串方法的代码的一些屏幕截图。 我在这里使用过Apollo Server,但香草GraphQL.js(以及更多代码)也可以使用。

Please note that this is just ONE way of implementing the full-schema-string method for this service. There are countless other ways. I am just presenting the simplest modular way here to help us understand the true advantages and disadvantages.
请注意,这只是实现此服务的全模式字符串方法的一种方法。 还有无数其他方法。 我只是在这里介绍最简单的模块化方法,以帮助我们了解真正的优缺点。

This is nice! We can see the types in the schema in one place. It’s clear where the schema starts. We’re able to modularize the code by type/feature.

太好了! 我们可以在一处看到架构中的类型。 很明显,架构从哪里开始。 我们能够按类型/功能对代码进行模块化。

This again is really great! Resolvers are co-located with the types they implement. There is no noise. This file beautifully contains what matters in a very readable format. I love it!

这真的很棒! 解析器与它们实现的类型位于同一位置。 没有噪音。 这个文件精美易懂地包含了重要内容。 我喜欢它!

The modularity here is only possible with Apollo Server. If we’re to do this with vanilla GraphQL.js we will have to monkey with data objects to make them suitable to be a "resolvers tree". The mixing between the data structures and the resolvers graph is not ideal.
这里的模块化仅适用于Apollo Server。 如果我们要使用普通的GraphQL.js进行此操作,则必须使用数据对象,使其适合作为“解析器树”。 数据结构和解析器图之间的混合并不理想。

So what’s the downside here?

那这里有什么缺点呢?

If you use this method then all your types have to be written in that certain way that relies on the schema language text. You have less flexibility. You can’t use constructors to create some types when you need to. You’re locked down to this string-based approach.

如果使用此方法,则必须以依赖于模式语言文本的某种特定方式编写所有类型。 您的灵活性较差。 需要时,不能使用构造函数来创建某些类型。 您只能使用这种基于字符串的方法。

If you’re okay with that then ignore the rest of this article. Just use this method. It is so much cleaner than the alternative.

如果您对此表示满意,请忽略本文的其余部分。 只需使用此方法。 它比替代品干净得多。

基于对象的方法 (The object-based method)

Let’s now look at the object-based approach. Here’s the starting point of an executable schema built using that method:

现在让我们看一下基于对象的方法。 这是使用该方法构建的可执行模式的起点:

We don’t need a separate resolvers object. Resolvers are part of the schema object itself. That makes them easier to maintain. This code is also easier to programmatically extend and analyze!

我们不需要单独的resolvers对象。 解析器是架构对象本身的一部分。 这使它们更易于维护。 此代码也更容易以编程方式扩展和分析!

It’s also so much more code that’s harder to read and reason about! Wait until you see the rest of the code. I couldn’t take the Article type screenshot on the laptop screen. I had to use a bigger screen.

还有太多难以理解的代码! 等到看到其余的代码。 我无法在笔记本电脑屏幕上拍摄“ Article类型的屏幕截图。 我不得不使用更大的屏幕。

No wonder the full-schema-string method is popular! There is certainly a lot of "noise" to deal with here. Types are not clear at first glance. Custom resolvers are mixed in one big configuration object.

难怪全模式字符串方法很流行! 这里肯定要处理很多“噪音”。 乍一看类型不明确。 自定义解析器混合在一个大的配置对象中。

My favorite part is when you need to create a non-null list of non-null items like [Article!]!. Did you see what I had to write?

我最喜欢的部分是需要创建诸如[Article!]!类的非空项目的非空列表时[Article!]! 。 你看到我写的东西了吗?

new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(Article))),

new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(Article))),

However, while this is indeed a lot more code that’s harder to understand, it is still a better option than having one big string (or multiple strings combined into one) and one big root resolvers object (or multiple resolvers objects combined into one). It’s better than having all the dependencies of your app managed in one single entry point.

但是,尽管确实有很多代码难以理解,但与将一个大字符串(或将多个字符串组合成一个)和一个大根解析器对象(或将多个分解器对象组合成一个)相比,它仍然是一个更好的选择。 这比在单个入口点管理应用程序的所有依赖关系要好。

There is a lot of power in modularizing your code using objects (that may depend on each other). It’s cleaner that way and it also makes writing tests and validations easier. You get more helpful error messages when you debug problems. Modern editors can provide more helpful hints in general. Most importantly, you have a lot more flexibility to do anything with these objects. The GraphQL.js constructors API itself also uses JavaScript objects. There is so much you can do with them.

使用对象(可能相互依赖)将代码模块化的功能非常强大。 这样更清洁,也使编写测试和验证更加容易。 调试问题时,您会获得更多有用的错误消息。 一般而言,现代编辑人员可以提供更多有用的提示。 最重要的是,您具有更大的灵活性来处理这些对象。 GraphQL.js构造函数API本身也使用JavaScript对象。 他们可以为您做很多事情。

But the noise is real too.

但是噪音也是真实的。

无噪声的基于对象的方法 (The object-based method without the noise)

I am sticking with the object-based method but I sure wish the JavaScript GraphQL implementations had a better API that can give us some of the power of the full-schema-string method.

我坚持使用基于对象的方法,但是我希望JavaScript GraphQL实现具有更好的API,可以为我们提供全模式字符串方法的某些功能。

Wouldn’t be nice if we can write the Article type logic exactly as we did in the full-schema-string method but in a way that generates the flexible GraphQLObjectType that we can plug into an object-based schema?

如果我们可以像在全模式字符串方法中那样完全编写Article类型逻辑,但是以一种生成可以插入到基于对象的模式中的灵活GraphQLObjectType的方式GraphQLObjectType ,那会不好吗?

Something like:

就像是:

Wouldn’t that be ideal? We get the benefits of the full-schema-string method for this type but with no lockdown! Other types in the system can be maintained differently. Maybe other types will be dynamically constructed using a different maker logic!

那不是理想吗? 对于这种类型,我们可以使用全模式字符串方法的好处,但是没有锁定! 系统中的其他类型可以不同地维护。 也许其他类型将使用不同的制造商逻辑动态构建!

All we need to make this happen is a magical typeMakerMethod to take the parts that matter and transform them into the complete GraphQLObjectType for Article.

我们要做的就是使用一个神奇的typeMakerMethod来处理重要的部分,并将其转换为Article的完整GraphQLObjectType

The typeMakerMethod will need to parse a string into an AST, use that to build a GraphQLObjectType, then merge the set of custom resolver functions with the fieldsconfiguration that’ll be parsed from the typeDef string.

typeMakerMethod将需要将字符串解析为AST,使用该字符串来构建GraphQLObjectType ,然后将自定义解析器功能集与将从typeDef字符串解析的fields配置typeDef

I like a challenge so I dug a little bit deeper to see how hard would it be to implement the typeMakerMethod. I knew I couldn’t use the graphql.buildSchema function because it only parses one full schema string to make a non executable schema object. I needed a lower-level part that parses a string that has exactly ONE type and then attaches custom resolvers to it. So I started reading the source code of GraphQL.js to look for clues. A few cups of coffee later, I found some answers (in 2 places):

我喜欢挑战,所以我更深入地研究了实现typeMakerMethod 。 我知道我不能使用graphql.buildSchema函数,因为它仅解析一个完整的模式字符串以构成一个不可执行的模式对象。 我需要一个较低级的部分来解析一个字符串,该字符串具有一个唯一的类型,然后将自定义解析器附加到该字符串。 因此,我开始阅读GraphQL.js的源代码以寻找线索。 几杯咖啡之后,我在2个地方找到了一些答案:

That’s the core method used in buildSchema to construct ONE type from a type definition node (which we can easily get by parsing the typeDef string).

这是buildSchema用于从类型定义节点构造ONE类型的核心方法(我们可以通过解析typeDef字符串轻松获得该typeDef )。

And:

和:

That’s how easy it is to extend an object type and attach any logic needed in fields and interfaces!

扩展对象类型并附加fieldsinterfaces所需的任何逻辑都是那么容易!

All I needed to do is put a few pieces together and the dream can be true.

我需要做的就是将几部分放在一起,梦想就可以实现。

I did.

我做到了 。

Ladies and gentlemen. I present to you the magical "typeMakerMethod" (which I named objectType):

女士们先生们。 我向您展示了神奇的“ typeMakerMethod”(我将其命名为objectType ):

That’s it (in its most basic form)! This will take a typeDef string that defines a single GraphQL type, an object of resolvers and a map of dependencies (for that type), and it’ll return a GraphQLObjectType ready to be plugged into your object-based schema as if it was defined normally with the object constructor.

就是这样(以最基本的形式)! 这将使用一个typeDef字符串,该字符串定义一个GraphQL类型,一个解析器对象和一个依赖关系映射(针对该类型),并将返回一个GraphQLObjectType可以将其插入到基于对象的模式中,就像定义了它一样通常使用对象构造函数。

Now you can use the object-based method but you have the option to define SOME types using an approach similar to the full-schema-string method. You have the power.

现在,您可以使用基于对象的方法,但是您可以选择使用类似于全模式字符串方法的方法来定义某些类型。 你有力量。

What do you think of this approach? I’d love to hear your feedback!

您如何看待这种方法? 我希望听到您的反馈!

Please note that the objectType code above is just the basic use case. There are many other use cases that require further code. For example, if the types have circular dependencies (articleauthorarticle) then this version of objectType will not work. We can delay the loading of the circular dependencies until we’re in the fields thunk (which is the current approach to solve this problem in the object-based method). We can also use the "extend" syntax to design the schema in a way that avoids circular dependencies in the first place. I’ve skipped this part to keep the example simple.

请注意,上面的objectType代码只是基本用例 。 还有许多其他用例需要更多代码。 例如,如果类型具有循环依赖关系( articleauthorarticle ),则此版本的objectType将不起作用。 我们可以延迟循环依赖项的加载,直到我们进入thunk fields为止(这是在基于对象的方法中解决此问题的当前方法)。 我们还可以使用“ extend”语法来设计架构,从而避免循环依赖。 为了使示例简单,我已跳过了这一部分。

If you’d like to give it a spin I published a more polished version of objectType and a few other maker functions like it under the graphql-makers npm package.

如果您想尝试一下,我在graphql-makers npm软件包下发布了一个更完善的objectType版本和其他一些maker函数。



Originally published at https://jscomplete.com on June 9, 2019.

最初于 2019年6月9日 发布在 https://jscomplete.com

翻译自: https://www.freecodecamp.org/news/graphql-makers/

相关文章:

2_Selenium对象识别

1 准备工作 firebug和firepath我们使用xpath进行元素定位,所以需要安装firefox的两个插件,帮助编写xpath html知识在编写xpath的时候,需要查看html代码,所以需要理解html知识,可以到http://www.w3school.com.cn/去自学…

Mac OS Terminal Commands

转自 : http://www.renfei.org/blog/mac-os-x-terminal-101.html Mac OS X Terminal 101:终端使用初级教程 July 29, 2012 / 编程指南最近学习苹果认证的《Mac OS X Support Essentials》教程,看到 Command Line 一节有很多实用的知识&#x…

封装一个计时器,记录页面的停留时间

在页面加载时初始化计时器&#xff0c;页面结束时取值。 效果如图&#xff1a; 下面是uniapp的代码示例&#xff1a; <template><view class"aaaacc"><view class"aaa">{{time}}</view></view> </template><scri…

ess用户名和密码_陈ess洁如何从摄影系学生转变为成功的自由职业者和内容创作者(播客)...

ess用户名和密码This week, for our last podcast episode of 2019, I got to chat with freelancer and content creator Jessica Chan - known as CoderCoder on social media - about how she got into tech and started her educational website and YouTube channel.本周&…

安装wxpython——python程序GUI图形界面使用

一、本机使用python版本 1、本机使用python版本为3.6.2&#xff0c;windows系统。 二、安装步骤 1、开始-运行-cmd 2、python3.x 需要进入python安装位置下是pip目录&#xff0c;再执行pip 命令 其中&#xff1a;python F:\Users\Administrator\AppData\Local\Programs\Python\…

ASP.NET全球化与本地化 c#多国语言的支持 (项目支持多国语言的开发)

ASP.NET 2.0及以上的开发平台&#xff0c;为全球化本地化应用程序提供了工具&#xff0c;而且实现起来非常简单。以下内容是使用c#&#xff0c;按照帮助一步步做的&#xff0c;将为初学者提供详细的实现步骤。 一 几个必要概念 &#xff08;一&#xff09; 支持全球化  由于…

promise 和 async await区别

什么是Async/Await? async/await是写异步代码的新方式&#xff0c;以前的方法有回调函数和Promise。   async/await是基于Promise实现的&#xff0c;它不能用于普通的回调函数。   async/await与Promise一样&#xff0c;是非阻塞的。   async/await使得异步代码看起来像…

mac 制作usb启动盘_如何使用Mac制作Windows 10 USB-从Mac终端构建可启动的ISO

mac 制作usb启动盘Most new PCs dont come with DVD drives anymore. So it can be a pain to install Windows on a new computer.大多数新PC不再附带DVD驱动器。 因此&#xff0c;在新计算机上安装Windows可能会很痛苦。 Luckily, Microsoft makes a tool that you can use …

作业05-继承、多态、抽象类与接口

1. 本周学习总结 1.1 写出你认为本周学习中比较重要的知识点关键词 接口&#xff0c;Comparable&#xff0c;Comparator 1.2 尝试使用思维导图将这些关键词组织起来。 1.3 可选&#xff1a;使用常规方法总结其他上课内容。 1.接口特点&#xff1a;一个公开的界面 有统一定义的规…

炫彩流光按钮 html+css

话不多&#xff0c;先上效果&#xff1a; 简介&#xff1a; 用基础css做一个有一点炫酷的流光按钮&#xff0c;不止按钮&#xff0c;只要是盒子就行。 具体步骤&#xff1a; 1.先定义一个盒子当做按钮&#xff0c;如我就用a标签&#xff1a; <body><a href"#…

SQL取上一条, 下一条记录方法

如果我们需要取id为3的前后的1条记录. 就可以用以下方法 取上一条记录: select * from 表名 where id<3 order by id desc limit 1取下一条记录: select * from 表名 where id>3 order by id asc limit 1大小于比较 order limit 转载于:https://www.cnblogs.com/…

react中使用构建缓存_通过构建海滩度假胜地网站,了解如何使用React,Contentful和Netlify...

react中使用构建缓存In this full course from John Smilga you will learn React by building a beach resort website project. The project uses React router for routing, React context API for state management, Contentful headless CMS for data management, and Net…

R语言实战 - 基本统计分析(2)- 频数表和列联表

数据&#xff1a; > library(vcd) > head(Arthritis)ID Treatment Sex Age Improved 1 57 Treated Male 27 Some 2 46 Treated Male 29 None 3 77 Treated Male 30 None 4 17 Treated Male 32 Marked 5 36 Treated Male 46 Marked 6 23 …

随机位置显示图片不重叠前端实现详细讲解附效果图,代码可直接使用

目录先看看效果图所要实现的功能看看代码js代码讲解&#xff1a;下面看看完整代码吧小程序版本完整代码VUE版本的代码&#xff1a;先看看效果图 所要实现的功能 在页面上随机的位置显示随机大小的图片&#xff0c;并且每个图片不能重叠&#xff0c;完整实现代码。 看看代码 …

MVC缓存OutPutCache学习笔记 (一) 参数配置

OutPutCache 参数详解 Duration : 缓存时间&#xff0c;以秒为单位&#xff0c;这个除非你的LocationNone&#xff0c;可以不添加此属性&#xff0c;其余时候都是必须的。 Location : 缓存放置的位置; 该值为枚举值: None: 当被设置为None时&#xff0c;其余的任何设置将不起作…

在Mac上控制Alt Delete-如何在Macbook上打开任务管理器

It happens to the best of us: were working away on some important project, and our trusty computer freezes. Or rather, a program were in just stops responding. So what do you do?这对我们最好的人来说是偶然的&#xff1a;我们正在做一些重要的项目&#xff0c;而…

HEW MAP文件使用

参考资料转载于:https://www.cnblogs.com/iluzhiyong/p/5145396.html

算法导论九章 答案

http://blog.csdn.net/z84616995z/article/details/18840823?reload 9.3-8题&#xff1a; http://blog.csdn.net/z84616995z/article/details/18938181 9.3-9题&#xff1a; http://blog.csdn.net/z84616995z/article/details/18889535转载于:https://www.cnblogs.com/sa51718…

小程序实现瀑布流,获取图片高度分成两组数据的函数封装代码

把一个数组根据数组内部的图片的高度&#xff0c;拆分成两个数组&#xff0c;组成瀑布流数据的方法。 使用方式&#xff1a; async created() {var arr this.$mock.sssdata.data.lists;//arr 是一个数组&#xff0c;里面包含若干对象&#xff0c;对象里面有图片var myArr a…

实现线程哪种方法更好_实施数据以实现更好的用户体验设计的4种方法

实现线程哪种方法更好Gone are the days when design used to rely mainly on the color palettes and the creativity of the designer. In the rapidly expanding technological world of today, it is essential to work across departments to enhance the screen experien…

String比较.equals

首先定义四个变量str public class SIzhui {public static void main(String[] args) {String str1"wang";String str2"li";String str3"wang";String str4new String("wang");} } 然后进行比较 public class SIzhui {public static …

mac下mysql5.7.10密码问题

mysql5.7.10刚安装好&#xff0c;会生成一个随机密码。 如果没记住这个随机密码&#xff0c;那么到mysql/bin/下执行mysql_secure_installation命令 按照提示重置密码和其他选项。 ps&#xff1a;找了一下午终于找到方法了&#xff01;&#xff01;&#xff01; 转载于:https:/…

Error: Cannot find module ‘express‘

解决方案&#xff1a;把node_module整个文件夹删掉,然后npm clean cache,看下package.json里有没有express的依赖项,有的话直接npm install,没有的话 npm install express --save

Observables简介以及它们与Promise有何不同

‘Observables’, ‘Observables’, ‘Observables’...Yes! Today, we will talk about this often discussed word of the market. Well also learn how they are different from Promises (havent heard about Promises? Not to worry! You will know more soon). Let’s s…

Spring Boot项目错误:Error parsing lifecycle processing instructions

pom.xml文件错误&#xff1a;Error parsing lifecycle processing instructions 解决方法&#xff1a;清空.m2/repository下的所有依赖文件&#xff0c;重新下载即可解决该问题。转载于:https://www.cnblogs.com/EasonJim/p/7724683.html

oracle执行计划连接方式

嵌套循环&#xff08;Nested Loops &#xff08;NL&#xff09;&#xff09;假如有A、B两张表进行嵌套循环连接&#xff0c;那么Oracle会首先从A表中提取一条记录&#xff0c;然后去B表中查找相应的匹配记录&#xff0c;如果有的话&#xff0c;就把该条记录的信息推到等待返回的…

大转盘完整源码附效果图,可以下载直接用

本转盘实现功能&#xff0c;可以动态配置奖品和转盘相关的任何图片&#xff0c;可以灵活配置使用。是基于 uni-app 实现的。可以在小程序或者H5&#xff0c;各端兼容使用。 效果图&#xff1a;因为GIF图的掉帧&#xff0c;所以显示抽奖的转动速度慢&#xff0c;实际上转动比较…

使用FortJs使用现代JavaScript开发Node.js

介绍 (Introduction) Nodejs gives you the power to write server side code using JavaScript. In fact, it is very easy and fast to create a web server using Nodejs. There are several frameworks available on Node package manager which makes the development eve…

find 按时间查找

find 按时间查找 转载▼分类&#xff1a; linuxShell日记-mtime 修改时间-ctime 改变时间-atime 访问时间-mtime 5 至少5天之前修改过的文件&#xff0c;至少5天没修改过-mtime -5 5天之内修改过的文件-mtime 5 刚好5天前修改的文件 -perm 按权限查找 -perm 001 精确匹配权限…

转:从零开始做app需要做的事情列表

https://qdan.me/list/VaXl7N8emfv1ayWg 从零开始做App的Bootstrap 做一个App&#xff0c;需要很多东西。 不定期更新。 团队 工欲善其事&#xff0c;必先利其器。 需求管理 支持版本、迭代、需求的创建与管理。 产品经理在上面录入需求&#xff0c;开发参照开发&#xff0c;测…