天看到一個面試題,是關于img圖片加載方面的,有必要記錄一下。其實關于這個問題,只要知道圖片什么時候加載完成就能解決了。
實現邏輯:新建一個Image對象實例,為實例對象設置src屬性等,在onload事件中添加此實例對象到父元素中,然后將圖片地址數組中的第一個元素剔除,繼續調用此方法直到存儲圖片地址的數組為空。
const imgArrs=[...]; // 圖片地址
const content=document.getElementById('content');
const loadImg=()=> {
if (!imgArrs.length) return;
const img=new Image(); // 新建一個Image對象
img.src=imgArrs[0];
img.setAttribute('class', 'img-item');
img.onload=()=> { // 監聽onload事件
// setTimeout(()=> { // 使用setTimeout可以更清晰的看清實現效果
content.appendChild(img);
imgArrs.shift();
loadImg();
// }, 1000);
}
img.onerror=()=> {
// do something here
}
}
loadImg();
</script>
加上setTimeout后,看到的效果更加明顯,我這里加了500毫秒的延遲(錄屏軟件只支持錄制8秒的時間...)
其實我在網上還看到了一種答案,通過onreadystatechange事件實現監聽,于是在我本地調試了一下,發現并不能實現,img實例對象上并沒有這個屬性方法。查了查MDN,發現目前僅有XmlHttpRequest對象和Document對象中存在onreadystatechange屬性,而對于其它元素onreadystatechange此屬性并不存在。
因此對于其它元素需要慎用onreadystatechange事件。
不過我電腦上目前只有Chorme和Safari兩種瀏覽器,對于onreadystatechange測試的覆蓋面不全,所以我上面的結論可能還需要進一步驗證才行,感興趣的掘友可以調試一下~。
// 例1:
const img=new Image();
img.src='http://xxxx.com/x/y/z/ccc.png';
上面的代碼如果運行起來后,就會發送請求。 如圖:
再看一個例子:創建了一個div元素,然后將存放img標簽元素的變量添加到div元素內,而div元素此時并不在dom文檔中,頁面不會展示該div元素,那么瀏覽器會發送請求嗎?
// 例2:
const img=`<img src='http://xxxx.com/x/y/z/ccc.png'>`;
const dom=document.createElement('div');
dom.innerHtml=img;
答案:會請求。如圖:
<img src="http://xxx.com/x/sdf.png" style="display: none;">
或者
<img src="http://xxx.com/x/sdf.png" style="visibility: hidden;">
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<title></title>
<style>
.test {
height: 200px;
background-image: url('http://eb118-file.cdn.bcebos.com/upload/39148b2a545b48bf9b4ee95fd1b7f1eb_1515564089.png?');
}
</style>
</head>
<body>
<div></div>
</body>
</html>
dom文檔中不存在test元素時,即使設置了背景圖片,也不會發送請求,只有test元素存在時才會發送請求。
另外這個例子其實有點不太貼切,img標簽和background-image二者有著本質的區別。一個屬于HTML標簽,另一個屬于css樣式,加載機制和解析順序也不同。
一個完整的頁面是由js、html、css組成的,按照解析機制,html元素會優先解析,盡管css樣式是放在head標簽內的,但也不意味著它會優先加載,它只有等到html文檔加載完成后才會執行。而img標簽屬于網頁內容,所以img標簽會隨著網頁解析渲染優先于css樣式表加載出來。
作者:娜個小部呀
鏈接:https://juejin.cn/post/7340167256267391012
在學習之初,我們需要認識一下網頁的概念,因為網頁與我們的 html是息息相關的。
那么接下來我們來看一下,我們經常去通過瀏覽器查看的網頁,它的本質是什么?在此我們需要去做一個對比。我們眼中看到的網頁與程序員眼中看到的網頁,到底有什么不同?
首先就是我們用戶眼中看到的網頁,這是一個普通的網頁,它的一個首頁的效果。這個里面大家可以看到有很多的文字內容,包括一些圖片內容,并且呢它按照一定的格式去進行了一個排版,那么這些就是我們用戶看到的網頁。
用戶眼中看到的網頁
而同樣這樣一個網頁,在程序員眼中是什么樣的效果呢?實際上程序員眼中的網頁,都是由這樣一系列的代碼組成,這個代碼里面并不能直觀的去展示成我們眼中看到的,比如圖片以及其他的內容效果。那么程序員的這眼中的網頁是怎么制作出來的。而用戶眼中的這個網頁又是怎么去呈現出來的?這是我們需要去思考的問題?
程序員眼中看到的網頁
接下來我們先解決第一個問題,程序員是如何去制作網頁文件的,其實程序員用的就是我們的 html 技術來去制作網頁文件。而我們通過瀏覽器查看到的網頁都是這種擴展名為點 html 或者是點 htm 的文件。
HTML叫做超文本標記語言(Hypertext Markup Language),它是一種標記語言,主要就是用來去搭建網頁的結構用的。
那么程序員制作的網頁就是 html 文件嗎?也不全是。網頁的組成呢很復雜 它除了 HTML之外,還有其他的內容。
首先我們來看一下我們網頁的里面,組成的一個相關技術,也就是我們前端所需要學習的三層技術:
這個里面 html 實際上它是我們制作網頁的時候,第一層叫做結構層,他用來去搭建網頁的整個的結構骨架;
第二層 css 是樣式層,用來去美化我們的網頁結構;
第三層叫做 javascript,它是行為層,這個行為實際上就是用來去制作,我們網頁中的很多交互效果;比如用戶點擊的效果,我們的頁面切換的其他效果等等;
我們通過一個小小的案例,來帶大家好好理解一下什么是前端三層,大家都去自己繪畫或者是觀察過別人繪畫的過程。如果我們去繪制一個人物的時候,那么我們首先需要繪制的就是這個人物的結構,這個結構比如說人物包含頭部、身體以及四肢、我們需要去首先繪制一下它的輪廓,哪個地方是頭部,哪個地方是身體,其實這個過程就相當于前端里面 html 在搭建結構;
搭建完結構之后,這樣的一個人物是不好看的,所以我們需要用到 css 去對它進行美化,我可以給他去化妝穿衣服,這樣我們就可以得到一個類似照片效果的人物,但是真正的人物效果它是可以去動的,是有各種各樣的運動,各種各樣的動作,這個動作和運動效果由誰來制作呢?就是我們 javascript 它的一個功能,它就相當于我們把一個靜態的,美化之后的一個人物讓它動起來。
當然我們網頁除了這三層技術之外,它還包含其他的內容,就比如說我們看到的圖片、視頻、音頻、超級鏈接等等;那么這些內容包括我們之前所講的前端三層,它都是我們要去制作的具體存在的文件。
wagger 是一個簡單、功能強大、非常流行的API 表達工具。基于Swagger 生成API,可以得到交互式文檔、自動生成代碼的SDK,以及API 的發現方式。
Swagger 允許用戶在一個html5 web 頁面中,對API 進行文檔化和交互。
優點:
主要是 添加 swagger2 核心包 以及 swagger-ui界面包的依賴。
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.7.0</version>
</dependency>
package com.rickie;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class Swagger2 {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.rickie.rest"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Swagger構建RESTful API")
.description("")
.termsOfServiceUrl("")
.version("1.0")
.build();
}
}
如下是ProductController.java 的示例代碼。
package com.rickie.rest;
import com.rickie.dto.Product;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping(value="/products") // 通過這里配置使下面的映射都在/products下
public class ProductController {
private List<Product> productList;
//初始化
public ProductController(){
productList=new ArrayList<Product>();
for (int i=0; i < 10; i++) {
Product product=new Product();
product.setId(i);
product.setCount(i+10);
product.setName("watch"+i);
product.setDesc("watch desc"+i);
productList.add(product);
}
}
@ApiOperation(value="獲取產品列表", notes="獲取產品列表")
@RequestMapping(value={""}, method=RequestMethod.GET)
public List<Product> getProductList() {
return productList;
}
@ApiOperation(value="獲取產品詳細信息", notes="根據url的id來獲取產品詳細信息")
@ApiImplicitParam(name="id", value="產品ID", required=true, dataType="Integer",paramType="path")
@RequestMapping(value="/{id}", method=RequestMethod.GET)
public Product getProduct(@PathVariable Integer id) {
return productList.get(id);
}
}
@ApiOperation:
作用在方法上,表示一個http請求的操作 。
@ApiImplicitParam:
作用在方法上,表示單獨的請求參數
參數:
1. name :參數名。
2. value : 參數的具體意義,作用。
3. required : 參數是否必填。
4. dataType :參數的數據類型。
5. paramType :查詢參數類型,這里有幾種形式:
@ApiImplicitParams:
用于方法,包含多個 @ApiImplicitParam。
@Api:
作用在類上,用來標注該類具體實現內容。標識這個類是swagger的資源 。
參數:
1. tags:允許您為操作設置多個標簽的屬性。
2. description:可描述該類的作用。
訪問如下鏈接,可以看到第一張圖片所示,顯示所有的API 列表方法。
http://localhost:8080/swagger-ui.html
點擊查看第一個方法/products,如下圖所示,可以進行交互操作。
訪問 http://localhost:8080/v2/api-docs 可以獲取接口的JSON 描述文件,如下圖所示。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。