Làm cách nào để nhắm mục tiêu các phần tử DOM bên trong một thành phần phản ứng hoặc tôi nên tránh nhắm mục tiêu tất cả các phần tử DOM cùng nhau?


8

Tôi đã tạo một tập lệnh kích hoạt di chuột trên thùng chứa cha mẹ và sẽ di chuyển phần tử con đó ra khỏi chuột. Hiện tại tôi đã làm cho nó hoạt động nhưng có một số phần của mã dường như mâu thuẫn với mã REACT sẽ trông như thế nào. Đặc biệt là hai phần.

  1. Tôi đang sử dụng một bộ đếm trong chức năng kết xuất để mỗi nhịp có thuộc tính tùy chỉnh chính xác từ state.customPropertiesđó là một mảng cập nhật các thuộc tính tùy chỉnh khi di chuột qua phần tử cha.

    render() {
        let counter = 0;
        const returnCustomProp = function(that) {
            counter++;
            let x = 0;
            if (that.state.customProperties[counter - 1]) {
                x = that.state.customProperties[counter - 1].x;
            }
            let y = 0;
            if (that.state.customProperties[counter - 1]) {
                y = that.state.customProperties[counter - 1].y;
            }
            return "customProperty(" + x + " " + y + ")";
        }
        return (
            <div onMouseMove={this._testFunction} id="ParentContainer">
                    <section custom={returnCustomProp(this)}>
                        <b>Custom content for part 1</b>
                        <i>Could be way different from all the other elements</i>
                    </section>
                    <section custom={returnCustomProp(this)}>
                        2
                    </section>
                    <section custom={returnCustomProp(this)}>
                        <div>
                            All content can differ internally so I'm unable to create a generic element and loop trough that
                        </div>
                    </section>
                    <section custom={returnCustomProp(this)}>
                        4
                    </section>
                    <section custom={returnCustomProp(this)}>
                        5
                    </section>
                    <section custom={returnCustomProp(this)}>
                        <div>
                            <b>
                                This is just test data, the actualy data has no divs nested inside secions
                            </b>
                            <h1>
                                6
                            </h1>
                        </div>
                    </section>
                    <section custom={returnCustomProp(this)}>
                        7
                    </section>
                    <section custom={returnCustomProp(this)}>
                        8
                    </section>
                </div>
        );
    }
  2. Trong hàm mousemove tôi đang sử dụng document.getElementByIdquerySelectorAllđể lấy tất cả các phần tử phần và so sánh tọa độ chuột từ chuột với tọa độ phần tử phần.

    var mouseX = e.pageX;
    var mouseY = e.pageY;
    var spans = document.getElementById('ParentContainer').querySelectorAll('section');
    var theRangeSquared = 10 * 10;
    var maxOffset = 5;
    var newCustomProperties = [];
    for (var i = 0; i < spans.length; i++) {
        var position = spans[i].getBoundingClientRect();
        var widthMod = position.width / 2;
        var heightMod = position.height / 2;
        var coordX = position.x + widthMod;
        var coordY = position.y + heightMod + window.scrollY;
        // Distance from mouse
        var dx = coordX - mouseX;
        var dy = coordY - mouseY;
        var distanceSquared = (dx * dx + dy * dy);
        var tx = 0,
            ty = 0;
        if (distanceSquared < theRangeSquared && distanceSquared !== 0) {
            // Calculate shift scale (inverse of distance)
            var shift = maxOffset * (theRangeSquared - distanceSquared) / theRangeSquared;
            var distance = Math.sqrt(distanceSquared);
            tx = shift * dx / distance;
            ty = shift * dy / distance;
        }
        newCustomProperties.push({
            x: tx,
            y: ty
        });
    }

Tôi có cảm giác tôi đang sai về điều này. Tôi không chắc làm thế nào tôi có thể tránh bộ đếm trong khi giữ một returnCustomProphàm chung để trả về các thuộc tính cho phần tử đã nói (trong mã trực tiếp tôi có khoảng 200 phần tử này nên việc đặt số mục mảng cho chúng theo cách thủ công là không hiệu quả) .

Phần thứ hai cảm thấy khó khăn khi nhắm mục tiêu một yếu tố bằng ID nằm trong thành phần thực tế. Tôi cảm thấy mình có thể nhắm mục tiêu này mà không cần vượt qua DOM. Tham chiếu các phần tử phần có thể là một giải pháp, nhưng tôi tin rằng các tham chiếu nên được giữ ở mức tối thiểu và như đã nêu, mã thực tế bao gồm hàng trăm phần này.

NHANH CHÓNG

Mã không làm nhiều atm hơn cập nhật custom="customProperty(0 0)"tài sản. Bạn có thể thấy điều này xảy ra qua máng thanh tra phần tử trên mouseover.

Tôi có thể làm cho chức năng này hoạt động mà không phải đếm các <section>yếu tố bên trong chức năng kết xuất và không phải sử dụng document.querySelectorAllkhông?

Câu trả lời:


7

Làm cách nào để nhắm mục tiêu các phần tử DOM bên trong một thành phần phản ứng?

Theo tài liệu chính thức của React, bạn có thể truy cập các phần tử dom bằng cách sử dụng ref. Bạn phải tạo một ref bằng cách sử dụng React.createRef()cuộc gọi.

Tôi có nên tránh nhắm mục tiêu các yếu tố DOM hoàn toàn không?

Chuyển qua dom để lấy một phần tử dom cụ thể không phải là một cách thực hành tốt với React vì nó sẽ gây ra vấn đề về hiệu năng. Tuy nhiên, phản ứng cho phép một cách khác để làm điều tương tự bằng cách sử dụng createRef().

Tôi có thể làm cho chức năng này hoạt động mà không phải đếm các thành phần bên trong chức năng kết xuất và không phải sử dụng document.querySelectorAll không?

Có, hãy xem xét các bước sau để thực hiện việc này:

Bên trong hàm tạo, tạo một ref cho ParentContainer như thế này:

  this.ParentContainer=React.createRef();

Sau đó sử dụng ref chaContainer trong kết xuất:

    <div onMouseMove={this._testFunction} id="ParentContainer" 
      ref={this.ParentContainer} >

Bên trong thành phần thử nghiệm, sử dụng this.parentContainer như:

//replace this 
//var spans = document.getElementById('ParentContainer').querySelectorAll('section');
//with this
  var spans = this.parentContainer.current.childNodes;

Bạn có thể kiểm tra nó ở đây

BIÊN TẬP

Mọi suy nghĩ về cách tôi có thể làm việc xung quanh việc phải sử dụng bộ đếm cho phép bên trong chức năng kết xuất

Bạn có thể xác định returnCustomPropkết xuất bên ngoài như thế này: (Ở đây bạn sẽ cần phải vượt qua chỉ mục của từng phần thay vì thistham chiếu)

    returnCustomProp = (index)=> {
      let x = 0;
      if(this.state.customProperties[index]) {
          x = this.state.customProperties[index].x;
      }
      let y = 0;
      if(this.state.customProperties[index]) {
          y = this.state.customProperties[index].y;
      }
      return "customProperty("+x+" "+y+")";
    }

Và sử dụng nó với phần như thế này:

   <section custom={returnCustomProp(0)}>
            <b>Custom content for part 1</b>
            <i>Could be way different from all the other elements</i>
        </section>
        <section custom={returnCustomProp(1)}>
            2
        </section>
        <section custom={returnCustomProp(2)}>
            <div>
                All content can differ internally so I'm unable to create a generic element and loop trough that
            </div>
        </section>
        <section custom={returnCustomProp(3)}>
            4
        </section>
        <section custom={returnCustomProp(4)}>
            5
        </section>
        <section custom={returnCustomProp(5)}>
            <div>
                <b>
                    This is just test data, the actual data has no divs nested inside sections
                </b>
                <h1>
                    6
                </h1>
            </div>
        </section>
        <section custom={returnCustomProp(6)}>
            7
        </section>
        <section custom={returnCustomProp(7)}>
            8
        </section>

À, tôi hình dung tôi phải đặt một ref cho từng yếu tố cá nhân. Không biết tôi có thể truy vấn máng các phần tử con như thế. Điều đó hoàn hảo cho phần nhắm mục tiêu DOM. (Có lỗi trên this.parentContainerbtw, nên được this.ParentContainerviết hoa). Bạn có suy nghĩ gì về cách tôi có thể sử dụng let counterchức năng kết xuất bên trong không?
timo

1. có thể là cái này.ParentContainer viết hoa: có 2.Bạn có suy nghĩ gì về cách tôi có thể làm việc xung quanh việc phải sử dụng bộ đếm cho phép bên trong chức năng kết xuất không? tôi đã cố gắng loại bỏ nó trên fiddle đã cho
Jatin Parmar

Có thể tôi đang nhìn vào phiên bản sai của câu đố của bạn, nhưng tôi đang nói về các dòng 49-61. Tốt nhất là tôi nên di chuyển chúng ra bên ngoài chức năng kết xuất. Có lẽ đây là ngoài phạm vi của câu hỏi ban đầu.
timo

Các giải pháp cho phần truy cập là không hiệu quả khi có rất nhiều sections. Tôi muốn giữ chức năng chung. Từ câu hỏi: (in the live code I've got about 200 of these elements so setting the array item number for them manually is not efficient).Có lẽ đếm bên trong chức năng kết xuất là cách hiệu quả nhất sau tất cả.
timo

0

Bạn không nên thao tác trực tiếp với DOM vì quá trình phản ứng trên dom ảo. Theo tài liệu React, bạn nên sử dụng chuyển tiếp Ref. Để biết thêm chi tiết xin vui lòng đọc này .


Bạn có thể cung cấp một Fiddle với điều này? Ngoài ra, bạn có thể cung cấp thông tin về nhận xét đã nêu của tôi trong câu hỏi về việc sử dụng tài liệu tham khảo không? : "" ... nhưng tôi tin rằng các tài liệu tham khảo nên được giữ ở mức tối thiểu và như đã nêu, mã thực tế bao gồm hàng trăm phần này ... "
timo

0

Bạn có thể sử dụng phương pháp findDOMNode()của ReactDOM nếu bạn không tìm thấy giải pháp khác nhưng làm thế nào các tài liệu cho biết:

findDOMNodelà một lối thoát được sử dụng để truy cập vào nút DOM bên dưới. Trong hầu hết các trường hợp, việc sử dụng lối thoát này không được khuyến khích vì nó xuyên qua sự trừu tượng thành phần.

Ví dụ: tôi muốn chia sẻ trường hợp sử dụng ứng dụng của mình, nơi tôi cần tham chiếu đến div DOM container để thực hiện thao tác kéo và thả cho các thư viện mà tôi đang sử dụng.

Thí dụ:

import React, { forwardRef } from 'react'
import _ from 'lodash'
import { List } from 'office-ui-fabric-react'
import { Draggable } from 'react-beautiful-dnd'
import ReactDOM from 'react-dom'

export const BasicItemList = forwardRef((
  {
    items,
    onClickItem,
    innerRef,
    ...rest
  }, ref) => {
  const itemToCell = (i, idx) => {
    return (
      <Draggable draggableId={id} index={idx} key={idx}>
        {
          (provided, snapshot) => {
            return (
              <MyCell item={i}
                      onClick={onClickItem}
                      innerRef={provided.innerRef}
                      isDragging={snapshot.isDragging}
                      {...provided.dragHandleProps}
                      {...provided.draggableProps}
              />
            )
          }
        }
      </Draggable>
    )
  }
  const refGetter = (comp) => {
    const div = ReactDOM.findDOMNode(comp)
    if (_.isFunction(ref)) {
      ref(comp)
    } else if (ref) {
      ref.current = comp
    }
    if (_.isFunction(innerRef)) {
      innerRef(div)
    }
  }

  return (
    <List items={items}
          onRenderCell={itemToCell}
          componentRef={refGetter}
          {...rest}
    />
  )
})
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.