현재 이미지 읽기 지연 및 무한 스크롤

  • 지금이라 jQueryIntersectionObserver를 사용하지 않습니다!
  • 현재라서 TypeScript로 웹 구성 요소 만들기LitElement!!
  • 작업 URL창고.

    아래의 Polyfill을 사용하면 ES5 변환·gzip 후index.js의 사이즈는 11K 정도입니다.IE11, 사파리도 움직인다.
    index.html
    <script src="https://unpkg.com/@webcomponents/webcomponentsjs/webcomponents-loader.js"></script>
    <script src="https://unpkg.com/intersection-observer/intersection-observer.js"></script>
    
    ※ 그림은 여기.에서 빌린 것입니다.

    이미지 읽기 지연(lazy-image)


    장래lazylad 속성Blink LazyLoad(참고:원소와 iframe 원소의lazylad 속성의 보급을 기대하는 동시에 Let's Build Web Components! Part 5: LitElement의 글을 참고하다
    index.ts#LazyImage
    const isInters = ({isIntersecting}:IntersectionObserverEntry) => isIntersecting
    
    @customElement('lazy-image' as any)
    export class LazyImage extends LitElement {
    
      @property() load = false
    
      @property() src = ''
    
      constructor(){
        super()
        new IntersectionObserver((entries, observer)=>{
          if(entries.some(isInters)){
            this.load = true
            observer.unobserve(this)
          }
        }).observe(this)
      }
    
      render() {
        return html`<img src=${this.load ? this.src : ''}>`
      }
    
    }
    
    IntersectionObserver 자신을 감시하는 요소는 화면에 나타난 후this.load에서 true로 바뀌어 이미지를 나타낸다.
    const isInters = ({isIntersecting}:IntersectionObserverEntry) => isIntersecting
    ...
    new IntersectionObserver((entries, observer)=>{
      if(entries.some(isInters)){
         ...
    
    하하
    new IntersectionObserver((entries, observer)=>{
      entries.forEach( entry => {
        if(entry.isIntersecting){
          ...
    
    기본적으로 같은 처리지만 사용법이 멋있어요...

    무한 스크롤


    해보고 싶은데<virtual-scroller> 크롬에서만 움직였어요. 그래서 레이지-image가 쓴 말을 참고하세요.
    index.ts#infiniteScroll
    @customElement('infinite-scroll' as any)
    export class InfiniteScroll extends LitElement {
    
      @property({ type: { fromAttribute: (attr:string) => JSON.parse(attr) } })
      items: string[] = []
    
      @query('button') next?: HTMLButtonElement
    
      firstUpdated() {
        new IntersectionObserver( entries =>{
          if(entries.some(isInters)){
            this.items = [...this.items, ...this.items]
          }
        }).observe(this.next!)
      }
    
      render() {
        return html`
          <style>lazy-image { display: block; width: 100%; height: 480px; }</style>
          ${this.items.map(i=>html`<lazy-image src=${i}></lazy-image>`)}
          <button>next</button>
        `
      }
    
    }
    
    여기서 모니터링 페이지 하단의 <button>, 화면에 표시된 후items 속성이 지정한 데이터를 계속 읽습니다.
    index.html
    <infinite-scroll items='["URL1","URL2","URL3"...]'></infinite-scroll>
    
    LitElement에서 속성에서 전달된 값을 배열로 사용하려면fromAttribute 변환 처리를 정의할 수 있습니다(JSON을 전달할 때'シングルクォート.
    this.items = [...this.items, ...this.items]
    
    하하
    this.items.push( ...this.items)
    
    그럴 수도 있겠지만 배열에 값만 늘렸다면 LitElement 쪽에서는 눈치채지 못했을 거야
    this.items.push( ...this.items)
    this.requestUpdate // or this.requestUpdate('item')
    
    를 참고하십시오.
    그리고 실제로 무한 순환하는 페이지는 SEO한테 안 좋아요.인 것 같아요.
    new IntersectionObserver((entries, observer)=>{
      if(entries.some(isInters)){
        ...
        if(/* isItemsLast? */){
           this.next!.hidden = true
           observer.unobserve(this.next!)
        }
    
    Observer를 중지합니다.

    구문 정보


    제가 해봤는데rollup 결과polymer-cli가 제일 쉬웠어요.
    package.json
      "dependencies": {
        "@polymer/lit-element": "^0.6.4"
      },
      "devDependencies": {
        "polymer-cli": "^1.9.1",
        "typescript": "^3.1.3"
      }
    
    polymer.json
    {
      "entrypoint": "index.html",
      "shell": "index.js",
      "builds": [{
        "name": "default",
        "preset": "es5-bundled",
        "addServiceWorker": false
      }],
      "moduleResolution": "node",
      "npm": true
    }
    
    단독으로 사용하지 않는 것 같습니다. (기본적으로 서비스워커 같은 것을 만들 것입니다.) index.를 비롯한 Polyfill 및 minify는 편리합니다.
    그게 다야.

    좋은 웹페이지 즐겨찾기