react發送和接收請求_React行為編程簡介:請求,等待和阻止

react發送和接收請求

by Luca Matteis

盧卡·馬蒂斯(Luca Matteis)

React行為編程簡介:請求,等待和阻止 (An intro to Behavioral Programming with React: request, wait, and block)

Behavioral Programming (BP) is a paradigm coined in the 2012 article by David Harel, Assaf Marron, and Gera Weiss.

行為編程(BP)是David Harel,Assaf Marron和Gera Weiss在2012年的文章中提出的范式。

Directly from the abstract:

直接摘自:

Behavioral programming simplifies the task of dealing with underspecification and conflicting requirements by enabling the addition of software modules that can not only add to but also modify existing behaviors.

行為編程通過啟用添加不僅可以添加而且可以修改現有行為的軟件模塊,簡化了處理規格不足和沖突需求的任務。

高級概念 (High-level concepts)

I’ll first explain the high-level concepts using an example of two React components MoviesList and MoviesCount. One displays a list of movies, the other a number of how many movies there are. Then I will dive into how exactly behavioral programming works.

我將首先使用兩個React組件MoviesListMoviesCount的示例來解釋高級概念。 一個顯示電影列表,另一個顯示電影數量。 然后,我將深入探討行為編程的工作原理。

Both components fetch data from the same HTTP URL. They were developed by two different teams in a large organization. When we render both components on a page, we have a problem as they perform the same request:

這兩個組件都從相同的HTTP URL獲取數據。 它們是由大型組織中的兩個不同團隊開發的。 當我們將兩個組件都呈現在頁面上時,我們會遇到一個問題,因為它們執行相同的請求:

<>  <MoviesList />  <MoviesCount /></>

Little did we know that these are behavioral components. This means that we can do something quite clever to avoid both requests firing:

我們幾乎不知道這些是行為成分 。 這意味著我們可以做一些非常聰明的事情來避免兩個請求都被觸發:

const MoviesCountFromList = withBehavior([  function* () {    // block FETCH_COUNT from happening    yield { block: ['FETCH_COUNT'] }  },  function* () {    // wait for FETCH_LIST, requested by the other    // MoviesList component, and derive the count    const response = yield { wait: ['FETCH_LIST'] }    this.setState({      count: response.length    })  }])(MoviesCount)

In the above example, we stepped inside the MoviesCount component. We waited and requested for something to happen. And, more uniquely to behavioral programming, we also blocked something from happening.

在上面的示例中,我們進入了MoviesCount組件。 我們等待要求發生一些事情。 而且,對于行為編程而言,更獨特的是,我們還阻止了某些事情的發生。

Because we were trying to avoid both requests from firing, we blocked the FETCH_COUNT event from being triggered (since the same data was already acquired by the FETCH_LIST event).

因為我們試圖避免觸發兩個請求,所以我們阻止了FETCH_COUNT事件的觸發(因為FETCH_LIST事件已經獲取了相同的數據)。

<>  <MoviesList />  <MoviesCountFromList /></>

Adding functionality to existing components without modifying their code is the novelty of the behavioral programming paradigm.

在不修改其代碼的情況下向現有組件添加功能是行為編程范例的新穎之處。

Intuitively, this can allow the creation of more reusable components.

直觀地講,這可以允許創建更多可重用的組件。

In the rest of the article, I’ll go more in depth into how behavioral programing (BP) works, specifically in the context of React.

在本文的其余部分,我將更深入地研究行為編程(BP)的工作方式,特別是在React的上下文中。

重新思考編程流程 (Rethinking programming flow)

To achieve the above functionality, we need to think about programming behaviors a bit differently. Specifically, events play a crucial role in orchestrating the synchronization between the various behaviors we define for our components.

為了實現上述功能,我們需要對編程行為有所考慮。 具體而言, 事件在協調我們為組件定義的各種行為之間的同步中起著至關重要的作用。

const addHotThreeTimes = behavior(  function* () {    yield { request: ['ADD_HOT'] }    yield { request: ['ADD_HOT'] }    yield { request: ['ADD_HOT'] }  })
const addColdThreeTimes = behavior(  function* () {    yield { request: ['ADD_COLD'] }    yield { request: ['ADD_COLD'] }    yield { request: ['ADD_COLD'] }  })
run(  addHotThreeTimes,  addColdThreeTimes)

When we run the above code, we get back a list of requested events:

當我們運行上面的代碼時,我們返回一個請求事件的列表:

ADD_HOTADD_HOTADD_HOTADD_COLDADD_COLDADD_COLD

As expected, the first behavior executes. Once it’s done, the second behavior continues. However, new specifications for our component require us to change the order in which both events are triggered. Rather than triggering ADD_HOT three times, and then ADD_COLD three times, we want them to interleave and trigger ADD_COLD right after a ADD_HOT . This will keep the temperature somewhat stable.

如預期的那樣,將執行第一個行為。 完成后,第二個行為繼續。 但是,針對組件的新規范要求我們更改觸發兩個事件的順序。 而不是觸發ADD_HOT三次,然后ADD_COLD三次,我們希望他們交織和觸發ADD_COLD一個之后ADD_HOT 。 這樣可以使溫度保持穩定。

...
const interleave = behavior(  function* () {    while (true) {      // wait for ADD_HOT while blocking ADD_COLD      yield { wait: ['ADD_HOT'], block: ['ADD_COLD'] }
// wait for ADD_COLD while blocking ADD_HOT      yield { wait: ['ADD_COLD'], block: ['ADD_HOT'] }    }  })
run(  addHotThreeTimes,  addColdThreeTimes,  interleave)

In the above example, we introduce a new interleave behavior which does exactly what we need.

在上面的示例中,我們引入了一種新的交錯行為,該行為正是我們需要的。

ADD_HOTADD_COLDADD_HOTADD_COLDADD_HOTADD_COLD

We changed the order of when things get executed, without having to modify the code of already-written behaviors.

我們更改了事情執行的順序 ,而不必修改已經編寫的行為的代碼。

The process is summarized in the graphic below.

下圖總結了該過程。

The key concepts of this way of programming are the request, wait, and block operators. The semantics for these operators are:

這種編程方式的關鍵概念是requestwaitblock運算符。 這些運算符的語義是:

  • Requesting an event: proposing that the event be considered for triggering, and asking to be notified when it is triggered

    請求事件:建議考慮將事件觸發,并要求在事件觸發時得到通知

  • Waiting for an event: without proposing its triggering, asking to be notified when the event is triggered

    等待事件:不建議觸發事件,而是要求在事件觸發時得到通知

  • Blocking an event: forbidding the triggering of the event, vetoing requests of other b-threads.

    阻止事件:禁止事件觸發,否決其他b線程的請求。

Each b-thread (behavioral thread) lives on its own and is unaware of other threads. But they’re all interwoven at runtime, which allows them to interact with each-other in a very novel way.

每個b線程(行為線程)獨立存在,并且不知道其他線程。 但是它們都是在運行時交織在一起的,這使它們可以以一種非常新穎的方式彼此交互。

The generator syntax is essential to the functioning of a behavioral program. We need to control when to proceed to the next yield statement.

生成器語法對于行為程序的運行至關重要。 我們需要控制何時進行下一個yield語句。

回到React (Back to React)

How can these BP concepts be used in the context of React?

這些BP概念如何在React的上下文中使用?

Turns out that through high-order components (HOCs), you can add this behavioral idiom to existing components in a very intuitive fashion:

事實證明,通過高階組件(HOC),您可以以非常直觀的方式將此行為習慣用法添加到現有組件中:

class CommentsCount extends React.Component {  render() {    return <div>{this.state.commentsCount}</div>  }}
const FetchCommentsCount = withBehavior([  function* () {    yield { request: ['FETCH_COMMENTS_COUNT']}    const comments = yield fetchComments()    yield { request: ['FETCH_COMMENTS_COUNT_SUCCESS']}    this.setState({ commentsCount: comments.length })  },])(CommentsCount)

Here we are using withBehavior, from the b-thread library, to make CommentsCount a behavioral component. Specifically, we are making it fetch the comments and display the data once the data is ready.

在這里,我們使用來自b線程庫的withBehavior ,使CommentsCount成為行為組件。 具體來說,我們正在使它獲取注釋并在數據準備好后顯示數據。

For simple components, this might not be such a game-changer. But let’s imagine more complex components, with lots of logic and other components inside of them.

對于簡單的組件,這可能不會改變游戲規則。 但是,讓我們想象一下更復雜的組件,其中包含許多邏輯和其他組件。

We might imagine the entire Netflix website as a <Netflix /> component:

我們可以將整個Netflix網站想象為<Netflix />組件:

When we use this component in our app, we’d like to interact with it. Specifically, when a movie is clicked, we don’t want to start the movie immediately, but instead we want to make an HTTP request, show other data about the movie, and then start the movie.

當我們在應用程序中使用此組件時,我們希望與其進行交互。 具體來說,當單擊電影時,我們不想立即啟動該電影,而是希望發出HTTP請求,顯示有關該電影的其他數據,然后啟動該電影。

Without changing code inside the <Netflix /> component, I’d argue that this would be impossible to achieve without it being a behavioral component.

如果不更改<Netflix />組件內部的代碼,我認為如果沒有行為組件就無法實現。

Instead let’s imagine that <Netflix /> was developed using behavioral programming:

相反,讓我們想象<Netflix />是使用行為編程開發的:

const NetflixWithMovieInfo = withBehavior([  function* () {    // First, block the MOVIE_START from happening     // within <Netflix /> until a new     // FETCH_MOVIE_INFO_SUCCESS event has been requested.    // The yield statement below can be read as:    // wait for FETCH_MOVIE_INFO_SUCCESS while blocking MOVIE_START    yield {       wait: ['FETCH_MOVIE_INFO_SUCCESS'],       block: ['MOVIE_START']     }  },  function* () {    // Here we wait for MOVIE_CLICKED, which is    // triggered within <Netflix />, and we fetch our    // movie info. Once that's done we request a new event    // which the earlier behavior is waiting upon    const movie = yield { wait: ['MOVIE_CLICKED'] }    const movieInfo = yield fetchMovieInfo(movie)    yield {       request: ['FETCH_MOVIE_INFO_SUCCESS'],       payload: movieInfo     }  }])(Netflix)

Above we’ve created a new NetflixWithMovieInfo component which modifies the behavior of the <Netflix /> component (again, without changing its source code). The addition of the above behaviors makes it so that MOVIE_CLICKED will not trigger MOVIE_START immediately.

上面,我們創建了一個新的NetflixWithMovieInfo組件,該組件修改了<Netflix />組件的行為(同樣,不更改其源代碼)。 上述行為的添加使that MOVIE_C LICKED不會立即igger MOVIE _START。

Instead, it uses a combination of “waiting while blocking”: a wait and a block can be defined within a single yield statement.

相反,它使用“等待時阻塞”的組合:可以在單個yield語句中定義等待阻塞

The picture above describes, more in detail, what is happening within our behavioral components. Each little box within the components is a yield statement. Each vertical dashed arrow represents a behavior (aka b-thread).

上圖更詳細地描述了我們的行為組件中正在發生的事情。 組件中的每個小方框都是yield語句。 每個垂直虛線箭頭代表行為(又稱b線程)。

Internally, the behavioral implementation will start by looking at all the yield statements of all b-threads at the current synchronization point, depicted using an horizontal yellow line. It will only continue to the next yield statement within a b-thread if no events in other b-threads are blocking it.

在內部,行為實現將從查看當前同步點處所有b線程的所有yield語句開始,并使用水平黃線描繪。 如果其他b線程中沒有任何事件阻止它,它將僅繼續到b線程中的下一個yield語句。

Since nothing is blocking MOVIE_CLICKED , it will be requested. We can then continue to the next yield statement for the Netflix behavior. At the next synch point, the b-thread on the far right, which is waiting for MOVIE_CLICKED, will proceed to its next yield statement.

由于沒有什么阻止MOVIE_CLICKED ,因此將請求它。 然后,我們可以繼續執行下一個關于Netflix行為的收益聲明。 在下一個同步點,最右邊的b線程正在等待MOVIE_CLICKED ,將繼續執行下一個yield語句。

The middle behavior that is waiting-and-blocking does not proceed. FETCH_MOVIE_INFO_SUCCESS was not requested by other b-threads, so it still waits-and-blocks. The next synchronization point will look something like this:

等待和阻止的中間行為不會繼續。 其他b線程未請求FETCH_MOVIE_INFO_SUCCESS ,因此它仍在等待并阻塞。 下一個同步點將如下所示:

As before, we will look at all the yield statement at this synchronization point. This time, however, we cannot request MOVIE_START because there’s another b-thread that is blocking it (the black yield statement). The Netflix component will therefore not start the movie.

和以前一樣,我們將在此同步點查看所有yield語句。 但是,這一次我們無法請求MOVIE_START因為還有另一個b線程正在阻止它(黑色yield語句)。 Netflix組件因此將無法開始播放電影。

FETCH_MOVIE_INFO_SUCCESS on the far right, however, is free to be requested. This will unblock MOVIE_START at the next synch point.

但是,最右邊的FETCH_MOVIE_INFO_SUCCESS是免費的。 這將在下一個同步點取消阻止MOVIE_START

All this in practice allowed us to change the order of things happening within other components, without directly modifying their code. We were able to block certain events from firing until other conditions were met in other components.

實際上,所有這些使我們能夠更改其他組件中發生的事情的順序,而無需直接修改它們的代碼。 我們能夠阻止某些事件觸發,直到在其他組件中滿足其他條件為止。

This changes the way we might think of programming: not necessarily a set of statements executed in order, but rather an interleaving of yield statements all synchronized through specific event semantics.

這改變了我們對編程的思考方式:不一定是按順序執行的一組語句,而是交織了所有通過特定事件語義同步的yield語句。

Here’s a simple animation depicting the way b-threads are executed and interwoven at runtime.

這是一個簡單的動畫,描繪了b線程在運行時執行和交織的方式。

無需更改舊代碼即可編程 (Programming without changing old code)

There is another way we can understand this programming idiom. We can compare the way we currently program as specifications change, versus how it would be done with behavioral programming.

我們可以用另一種方式來理解這種編程習慣。 我們可以將當前隨著規范變化而編程的方式與行為編程的方式進行比較。

In the above caption, we imagine how behavior may be added to a non-behavioral program. We start with a program described only using three black rectangles (on the left).

在上面的標題中,我們想象了如何將行為添加到非行為程序中。 我們從僅使用三個黑色矩形(左側)描述的程序開始。

As specifications change, we realize we need to modify the program and add new behavior in various sections of the program, depicted as newly added colored rectangles. We continue doing this as requirements for our software change.

隨著規范的變化,我們意識到我們需要修改程序并在程序的各個部分添加新行為,以新添加的彩色矩形表示。 作為軟件更改的要求,我們將繼續這樣做。

Every addition of behavior requires us to change code that was written, which possibly litters the old behavior with bugs. Furthermore, if the program we are changing is part of various other modules used by different people, we might be introducing unwanted behavior to their software. Finally, it may not be possible to change specific programs as they might be distributed as libraries with licensed source code.

行為的每次添加都要求我們更改所編寫的代碼,這可能會用錯誤掩蓋舊行為。 此外,如果我們要更改的程序是不同人使用的其他模塊的一部分,那么我們可能會在他們的軟件中引入不必要的行為。 最后,可能無法更改特定程序,因為它們可能作為具有許可源代碼的庫分發。

In the above figure, we see how the same program-modifications can be achieved using behavioral programming idioms. We still start with our three rectangles on the left as we did before. But as new specifications arise, we don’t modify them. Instead we add new b-threads, represented as columns.

在上圖中,我們看到了如何使用行為編程習慣來實現相同的程序修改。 我們仍然像以前一樣從左側的三個矩形開始。 但是隨著新規范的出現,我們不會對其進行修改。 相反,我們添加了新的b線程,以列表示。

The resulting program is the same, although constructed in a very different way. One of the advantages of the behavioral approach is that we don’t have to modify old code as requirements change.

生成的程序是相同的,盡管構造方式非常不同。 行為方法的優點之一是,隨著需求的變化,我們不必修改舊代碼。

You can also imagine developing each b-thread in parallel, possibly by different people in a large organization, since they do not directly depend on each other.

您也可以想象大型機構中的不同人員可能并行開發每個b線程,因為它們并不直接相互依賴。

The benefit of this approach also seems to be with packaging: we can change the behavior of a library without needing to access or modify its source-code.

這種方法的好處似乎還在于打包:我們可以更改庫的行為,而無需訪問或修改其源代碼。

API不僅作為道具,而且作為事件 (APIs not only as props, but as events)

Currently, the only way for a React component to communicate with the outside world is via props (apart from the Context API).

當前,React組件與外界通信的唯一方法是通過props(除了Context API)。

By making a component behavioral, instead of using props, we tell the outside world about when things happen within the component by yielding events.

通過使組件具有行為性,而不是使用道具,我們通過產生事件來告知外界組件中何時發生事件。

To allow other developers to interact with the behavior of a component, we must therefore document the events that it requests, the events it waits for, and finally the events it blocks.

因此,為了允許其他開發人員與組件的行為進行交互,我們必須記錄其請求的事件,其等待的事件以及最終阻止的事件。

Events become the new API.

事件成為新的API。

For instance, in a non-behavioral Counter component, we tell the outside world when the counter is incremented and what the current count is, using an onIncrement prop:

例如,在一個非行為Counter組件中,我們使用onIncrement道具告訴外界計數器何時遞增以及當前計數是onIncrement

class Counter extends React.Component {  state = { currentCount: 0 }  handleClick = () => {    this.setState(prevState => ({      currentCount: prevState.currentCount + 1    }), () => {      this.props.onIncrement(this.state.currentCount)    })  }  render() {    {this.state.currentCount}    <button onClick={this.handleClick}>+</button>  }}
<Counter   onIncrement={(currentCount) =>     console.log(currentCount)  }/>

What if we want to do something else before the counter’s state gets incremented? Indeed we could add a new prop such as onBeforeIncrement, but the point is that we don’t want to add props and refactor code every time a new specific arises.

如果我們想在計數器狀態遞增之前做其他事情怎么辦? 確實,我們可以添加一個新的道具,例如onBeforeIncrement ,但要點是,我們不想在每次出現新的道具時都添加道具和重構代碼。

If we transform it into a behavioral component we can avoid refactoring when new specifications emerge:

如果我們將其轉換為行為組件,則可以避免在出現新規范時進行重構:

class Counter extends React.Component {  state = { currentCount: 0 }  handleClick = () => {    bp.event('CLICKED_INCREMENT')  }  render() {    {this.state.currentCount}    <button onClick={this.handleClick}>+</button>  }}
const BehavioralCounter = withBehavior([  function* () {    yield { wait: ['CLICKED_INCREMENT'] }    yield { request: ['UPDATE_CURRENT_COUNT'] }
this.setState(prevState => ({      currentCount: prevState.currentCount + 1    }), () => {      this.props.onIncrement(this.state.currentCount)    })  }])(Counter)

Notice how we moved the logic for when the state is updated inside a b-thread. Furthermore, before the update actually takes place, a new event UPDATE_CURRENT_COUNT is requested.

注意,如何在b線程中更新狀態時如何移動邏輯。 此外,在實際進行更新之前,請求一個新事件UPDATE_CURRENT_COUNT

This effectively allows other b-threads to block the update from happening.

這有效地允許其他b線程阻止更新的發生。

Components can also be encapsulated and shared as different packages, and users can add behavior as they see fit.

組件也可以封裝和共享為不同的包,用戶可以根據自己的喜好添加行為。

// package-name: movies-listexport const function MoviesList() {  ...}
// package-name: movies-list-with-paginationexport const MoviesListWithPagination = pipe(  withBehavior(addPagination))(MoviesList)
// package-name: movies-list-with-pagination-logicexport const MoviesListWithDifferentPaginationLogic = pipe(  withBehavior(changePaginationLogic))(MoviesListWithPagination)

Again this is different from simply enhancing a component, as a regular HOC would do. We can block certain things from happening in the components we extend from, effectively modifying their behavior.

再次,這不同于常規HOC所做的簡單地增強組件。 我們可以阻止某些事情在擴展組件中發生,從而有效地修改其行為。

結論 (Conclusion)

This new programming idiom might feel uncomfortable at first, but it seems to alleviate a prominent issue we have when using UI components: it is hard to reuse components, because they don’t blend with the environment they were put into.

剛開始時,這種新的編程習慣可能會讓您感到不舒服,但是它似乎減輕了我們在使用UI組件時遇到的一個突出問題: 很難重用組件,因為它們不會與所放置的環境融合在一起。

In the future, perhaps using these behavioral concepts, we will be able to add new behavior to apps by simply mounting new components. Stuff like this will be possible:

將來,也許使用這些行為概念,我們將能夠通過簡單地安裝新組件來向應用程序添加新行為。 這樣的東西將是可能的:

<Environment>  <Netflix />  <Twitter />  <WaitForTwitterBeforeNetflix />  <OnTwitterClickShowLoader /></Environment>

Additionally, events don’t need to pollute the whole app and can be broadcast only within a specific environment.

此外,事件并不需要污染整個應用程序,而只能在特定環境中廣播。

Thanks for reading! If you’re interested in an actual implementation of behavioral programming, please see my current work in progress library that works with React: https://github.com/lmatteis/b-thread. The Behavioral Programming homepage also contains various implementations.

謝謝閱讀! 如果您對行為編程的實際實現感興趣,請參見我當前與React一起使用的進度庫: https : //github.com/lmatteis/b-thread 。 行為編程主頁還包含各種實現。

For more information on this exciting new concept, I suggest you read the scientific papers on Behavioral Programming or check some of my other articles on the subject.

有關此令人興奮的新概念的更多信息,建議您閱讀有關行為編程的科學論文,或查看我 有關該主題的 其他文章 。

翻譯自: https://www.freecodecamp.org/news/an-intro-to-behavioral-programming-with-react-request-wait-and-block-ad876e2d235e/

react發送和接收請求

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

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

相關文章

leetcode96. 不同的二叉搜索樹(動態規劃)

給定一個整數 n&#xff0c;求以 1 … n 為節點組成的二叉搜索樹有多少種&#xff1f; 解題思路 *數組含義&#xff1a;dp[i] i個節點的不同組成結構 狀態轉移&#xff1a;任取節點為根節點&#xff0c;遍歷左右子樹可能出現的個數,dp[i]dp[left]dp[right] 初始化&#xff1a…

“康園圈--互聯網+校園平臺“項目之成果展示及項目總結

一、總體效果&#xff08;ipad端截圖&#xff09; 網站前臺頁面網站后臺管理臺頁面二、前臺訪問鏈接&#xff08;用pc訪問效果最佳&#xff09;&#xff1a;http://www.liangzhilin.cn:9100/kangyuanquan/ &#xff08;為保證數據安全&#xff0c;后臺管理鏈接不對外公開&#…

ajax jq 圖片上傳請求頭_Jquery ajaxsubmit上傳圖片實現代碼

這是數月前的事情了&#xff0c;場景是這樣的&#xff1a; 在進行圖片上傳的時&#xff0c;我發現開發人員使用的上傳圖片方式是Iframe 傳統的 http post 來處理的。而且未建立統一上傳函數。于是將代碼改造了。心想來個ajax異步上傳圖片吧&#xff0c;這技術應該很老套了。于…

這個免費的交互式課程在一小時內學習JavaScript

JavaScript is the most popular programming language on the web. You can use it to create websites, servers, games and even native apps. So no wonder it’s such a valuable skill in today’s job market.JavaScript是網絡上最流行的編程語言。 您可以使用它來創建網…

java中二進制怎么說_面試:說說Java中的 volatile 關鍵詞?

volatile 這個關鍵字可能很多朋友都聽說過&#xff0c;或許也都用過。在 Java 5 之前&#xff0c;它是一個備受爭議的關鍵字&#xff0c;因為在程序中使用它往往會導致出人意料的結果。在 Java 5之后&#xff0c;volatile 關鍵字才得以重獲生機。volatile 關鍵字雖然從字面上理…

類的詳解

面向對象是一種編程方式&#xff0c;此編程方式的實現是基于對類和對象的使用。類是一個模板&#xff0c;模板中包裝了多個“函數”供使用&#xff08;可以講多函數中公用的變量封裝到對象中&#xff09;。對象&#xff0c;根據模板創建的實例&#xff08;即對象&#xff09;&a…

leetcode279. 完全平方數(動態規劃)

給定正整數 n&#xff0c;找到若干個完全平方數&#xff08;比如 1, 4, 9, 16, …&#xff09;使得它們的和等于 n。你需要讓組成和的完全平方數的個數最少。 示例 1: 輸入: n 12 輸出: 3 解釋: 12 4 4 4. 解題思路 數組含義&#xff1a;dp[i]數字i對應組成和的完全平方…

什么情況不能辦理房產抵押貸款 房產抵押貸能貸多少?

所謂房產抵押貸款是指以自己或親友的房產作為抵押物向貸款機構申請貸款&#xff0c;款項可用于企業經營、買房、買車、裝修及其他用途的融資方式。但是有些情況是規定不能申請房產抵押貸款的&#xff0c;而且貸款的數額是有限的&#xff0c;不是想貸多少就多少。那么&#xff0…

Android RecyclerView 二級列表實現

Android RecyclerView 二級列表實現

2數據庫表增加一個字段_14個實用的數據庫設計技巧!

1. 原始單據與實體之間的關系可以是一對一、一對多、多對多的關系。在一般情況下&#xff0c;它們是一對一的關系&#xff1a;即一張原始單據對應且只對應一個實體。在特殊情況下&#xff0c;它們可能是一對多或多對一的關系&#xff0c;即一張原始單證對應多個實體&#xff0c…

錯誤: 找不到或無法加載主類 helloworld_全面剖析虛擬機類加載機制

1.引言java源文件經過編譯后生成字節碼class文件&#xff0c;需要經過虛擬機加載并轉換成匯編指令才能執行&#xff0c;那么虛擬機是如何一步步加載這些class文件的對于java程序員是完全透明的&#xff0c;本文嘗試全面分析jvm類加載機制。2.思考開始之前我們來簡單思考一下&am…

nginx反向代理和shiro權限校驗產生的404問題

問題描述: 我們的項目A&#xff08;以下簡稱A&#xff09;用了shiro做權限校驗&#xff0c;nginx做反向代理&#xff0c;在另一個項目B&#xff08;以下簡稱B&#xff09;中點擊某個A的鏈接時實現單點登錄并會跳轉到該路徑。跳轉到原路徑的時候nginx報了404。出現404之后再次點…

android 揭示動畫_如何使用意圖揭示函數名稱使代碼更好

android 揭示動畫Discover Functional JavaScript was named one of the best new Functional Programming books by BookAuthority!“發現功能JavaScript”被BookAuthority評為最佳新功能編程書籍之一 &#xff01; Code is a way to communicate with developers reading it…

200道物理學難題——038蚱蜢躍樹

轉載于:https://www.cnblogs.com/hanford/p/6168514.html

(轉)dp動態規劃分類詳解

dp動態規劃分類詳解 轉自&#xff1a;http://blog.csdn.NET/cc_again/article/details/25866971 動態規劃一直是ACM競賽中的重點&#xff0c;同時又是難點&#xff0c;因為該算法時間效率高&#xff0c;代碼量少&#xff0c;多元性強&#xff0c;主要考察思維能力、建模抽象能力…

strcmp可以比較數組么_大家都用過百度云,但你面試過百度云么

作者&#xff1a;黃小斜百度研發面經百度智能云軟件研發工程師百度智能云研發崗好像是做控制臺方面的組一面&#xff1a;1自我介紹&#xff0c;項目2 static關鍵字有什么用&#xff0c;static修飾不同東西時有什么作用&#xff0c;內部類用static修飾和不用static修飾有何區別。…

leetcode785. 判斷二分圖(dfs和bfs染色)

給定一個無向圖graph&#xff0c;當這個圖為二分圖時返回true。 如果我們能將一個圖的節點集合分割成兩個獨立的子集A和B&#xff0c;并使圖中的每一條邊的兩個節點一個來自A集合&#xff0c;一個來自B集合&#xff0c;我們就將這個圖稱為二分圖。 graph將會以鄰接表方式給出…

bdd cucumber_如何使用BDD構建堅如磐石的Ruby on Rails應用

bdd cucumberby Marko Anastasov通過Marko Anastasov 如何使用BDD構建堅如磐石的Ruby on Rails應用 (How to build rock-solid Ruby on Rails apps with BDD) 了解通過行為驅動開發來構建可持續Web應用程序的最佳實踐。 (Learn best practices for building sustainable web a…

go kegg_KEGG分析及可視化

上一篇推文中我們解釋了GO富集分析及可視化&#xff08;GO富集分析及可視化&#xff09;&#xff0c;除了GO富集分析&#xff0c;我們經常在paper中看到KEGG分析&#xff0c;KEGG是什么呢&#xff0c;Kyoto Encyclopedia of Genes and Genomes&#xff0c;京都基因和基因組百科…

IntelliJ IDEA注冊碼

IntelliJ IDEA注冊碼 http://idea.lanyus.com/ 1.導航欄下 2.help下 3.register點擊 4.單選Activation code 5.粘貼注冊碼 轉載于:https://www.cnblogs.com/YUJIE666/p/10662561.html