jquery 데이터 선택기


184

요소의 .data()객체에 저장된 값을 기반으로 요소를 선택해야 합니다. 최소한 선택기를 사용하여 최상위 데이터 속성을 선택하고 싶습니다.

$('a').data("category","music");
$('a:data(category=music)');

또는 선택기는 일반 속성 선택기 형식 일 수 있습니다.

$('a[category=music]');

또는 속성 형식이지만 지정자를 지정하여 다음을 나타냅니다 .data().

$('a[:category=music]');

내가 발견 한 제임스 Padolsey의 구현 봐 간단하면서도 좋은으로합니다. 위의 선택기는 해당 페이지에 표시된 미러 방법을 포맷합니다. 이 Sizzle 패치도 있습니다.

어떤 이유로 jQuery 1.4에 jquery .data()객체의 값에 대한 선택기 지원이 포함되어 있다는 것을 잠시 되돌아 본 적이 있습니다. 그러나 이제는 찾고 있는데 찾을 수 없습니다. 어쩌면 내가 본 기능 요청 일 수도 있습니다. 이것에 대한 지원이 있고 그것을 보지 못하고 있습니까?

이상적으로는 점 표기법을 사용하여 data ()의 하위 속성을 지원하고 싶습니다. 이처럼 :

$('a').data("user",{name: {first:"Tom",last:"Smith"},username: "tomsmith"});
$('a[:user.name.first=Tom]');

또한 모든 지정된 데이터 선택기가있는 요소 만있는 여러 데이터 선택기를 지원하고 싶습니다. 일반 jquery 다중 선택기는 OR 연산을 수행합니다. 예를 들어 class 또는 )가있는 태그를 $('a.big, a.small')선택 a합니다 . AND를 찾고 있는데 아마도 다음과 같습니다.bigsmall

$('a').data("artist",{id: 3281, name: "Madonna"});
$('a').data("category","music");
$('a[:category=music && :artist.name=Madonna]');

마지막으로 비교 연산자와 정규식 기능을 데이터 선택기에서 사용할 수 있다면 좋을 것입니다. 따라서 $(a[:artist.id>5000])가능할 것입니다. 나는 아마도 이것을 사용하여 이것을 많이 할 수 있다는 것을 알고 filter()있지만 간단한 선택기 형식을 갖는 것이 좋을 것입니다.

이를 위해 어떤 솔루션을 사용할 수 있습니까? 현재 Jame의 Padolsey가 최고의 솔루션입니까? 내 관심사는 주로 성능뿐만 아니라 하위 속성 점 표기법 및 여러 데이터 선택기와 같은 추가 기능에 관한 것입니다. 이러한 것들을 지원하거나 어떤면에서 더 나은 다른 구현이 있습니까?


JQuery와 UI 코어 사용 api.jqueryui.com/category/ui-core를 데이터 () 선택 : 그것은이
regisbsb

답변:


101

data중첩 된 쿼리 및 AND 조건을 수행 할 수 있는 새로운 선택기를 만들었습니다 . 용법:

$('a:data(category==music,artist.name==Madonna)');

패턴은 다음과 같습니다.

:data( {namespace} [{operator} {check}]  )

"operator"및 "check"는 선택 사항입니다. 따라서 당신이 가지고있는 것만 있다면 :data(a.b.c)진실성 을 점검 할 것 입니다 a.b.c.

아래 코드에서 사용 가능한 연산자를 확인할 수 있습니다. 그중 ~=정규 표현식 테스트가 가능합니다.

$('a:data(category~=^mus..$,artist.name~=^M.+a$)');

몇 가지 변형으로 테스트했으며 꽤 잘 작동하는 것 같습니다. 아마 이것을 전체 테스트 스위트와 함께 곧 Github 저장소로 추가 할 것이므로 조심하십시오!

코드:

(function(){

    var matcher = /\s*(?:((?:(?:\\\.|[^.,])+\.?)+)\s*([!~><=]=|[><])\s*("|')?((?:\\\3|.)*?)\3|(.+?))\s*(?:,|$)/g;

    function resolve(element, data) {

        data = data.match(/(?:\\\.|[^.])+(?=\.|$)/g);

        var cur = jQuery.data(element)[data.shift()];

        while (cur && data[0]) {
            cur = cur[data.shift()];
        }

        return cur || undefined;

    }

    jQuery.expr[':'].data = function(el, i, match) {

        matcher.lastIndex = 0;

        var expr = match[3],
            m,
            check, val,
            allMatch = null,
            foundMatch = false;

        while (m = matcher.exec(expr)) {

            check = m[4];
            val = resolve(el, m[1] || m[5]);

            switch (m[2]) {
                case '==': foundMatch = val == check; break;
                case '!=': foundMatch = val != check; break;
                case '<=': foundMatch = val <= check; break;
                case '>=': foundMatch = val >= check; break;
                case '~=': foundMatch = RegExp(check).test(val); break;
                case '>': foundMatch = val > check; break;
                case '<': foundMatch = val < check; break;
                default: if (m[5]) foundMatch = !!val;
            }

            allMatch = allMatch === null ? foundMatch : allMatch && foundMatch;

        }

        return allMatch;

    };

}());

@JP : 매우 달콤합니다. 지금 잠자리에 들었지만 내일 시험해 보도록하겠습니다. OR 연산도 가능합니까? 필요하지 않고 그냥 궁금합니다.
Tauren

1
@ JP : 또한 다른 데이터 선택기 솔루션, 장단점에 대한 장단점에 관심이 있습니다. 예를 들어이 플러그인은 plugins.jquery.com/project/dataSelector 입니다.
Tauren

1
OR 연산을 수행하는 것이 가능하지만 단순히 두 개의 선택기를 갖는 것이 가장 좋습니다. $("a:data(condition),a:data(orCondition)")... 동일한 효과가 있습니다. 더 많은 기능을 추가할수록 속도가 느려집니다. 논리가 복잡한 경우을 사용하십시오 $(foo).filter(function(){...}).
James

3
@ JP : 이것을 github 프로젝트로 바 꾸었습니까? html5 속성 data-test = "500"이있는 입력에서 $ ( "input : data (test> 400)") 선택기를 사용하여 jQuery 1.5.1을 사용하여 테스트를 실행하고 있지만 선택기가 아무것도 반환하지 않습니다.
James South

1
@JamesSouth이 답변의 선택기가 low level을 사용하기 때문에 jQuery.dataHTML5 속성에 정의 된 데이터를 얻지 못합니다. 해당 기능을 원하면로 변경할 jQuery.data$('selector').data있지만 속도와 상충됩니다.
Shef

175

현재 다음과 같이 선택하고 있습니다.

$('a[data-attribute=true]')

어느 것이 잘 작동하는 것처럼 보이지만 jQuery가 'data-'접두사없이 해당 속성으로 선택할 수 있다면 좋을 것입니다.

jQuery를 통해 요소에 동적으로 추가 된 데이터로 이것을 테스트하지 않았 으므로이 방법이 실패 할 수 있습니다.


이것이 바로 내가 찾던 것입니다. 달콤함
MikeMurko

109
.data () 함수를 통해 JS를 통해 데이터를 첨부 / 수정하는 경우 실제로 작동하지 않습니다. 속성 선택기는 DOM 만 검사하고 JS는 메모리에 .data ()를 저장합니다.
Clarence Liu

1
.data ()를 통해 첨부하면 속성별로 액세스하는 방법을 알려주시겠습니까?
Maxim V. Pavlov 2016 년

1
이 스레드에서 제공되는 다른 답변은 매우 간단한 사용 사례 이외의 다른 방법에 대한 더 나은 옵션이라고 제안합니다.
Ash

Dmitri의 솔루션은 타사 코드에 의존하지 않으므로 나에게 멋지게 보입니다.
Ash

83

플러그인없이 간단한 필터링 기능을 사용할 수도 있습니다. 이것은 정확히 원하는 것이 아니지만 결과는 같습니다.

$('a').data("user", {name: {first:"Tom",last:"Smith"},username: "tomsmith"});

$('a').filter(function() {
    return $(this).data('user') && $(this).data('user').name.first === "Tom";
});

2
이것은 좋은 생각입니다. filter통과 함수가 테스트 함수를 받아 들일 수 있다는 것을 잊었습니다 =) 감사합니다
Clarence Liu

Tom 대신 "contains"를 어떻게 수행 할 수 있습니까?
Alisso

1
Alisso는 name.first == "Tom"대신 name.first && name.first.indexOF ( "Tom")> -1;
Dmitri

24

$('a[data-attribute=true]')data () 함수를 통해 DOM 요소에 데이터를 첨부하면 Ashley의 답변에 따라 작동하지 않는다는 경고를하고 싶습니다 .

HTML에 실제 데이터 공격자를 추가하면 예상대로 작동하지만 jQuery는 데이터를 메모리에 저장하므로 결과 $('a[data-attribute=true]')가 정확하지 않습니다.

데이터 플러그인 http://code.google.com/p/jquerypluginsblog/ 를 사용 filter하거나 Dmitri의 솔루션을 사용 하거나 모든 요소에 대해 $ .each를 수행하고 .data ()를 반복적으로 확인해야합니다.


필자의 경우 서버 측의 필드를 미리 채우고 있으므로 초기로드 시이 방법으로 만 상담하면되므로 괜찮습니다. 필터는 아마도 빠르지 만 (각각 거의 느리게) 가독성이 향상됩니다.
Don

11

이 작업을 수행하는 :data()필터 플러그인 이 있습니다 :)

귀하의 질문에 근거한 몇 가지 예 :

$('a:data("category=music")')
$('a:data("user.name.first=Tom")');
$('a:data("category=music"):data("artist.name=Madonna")');
//jQuery supports multiple of any selector to restrict further, 
//just chain with no space in-between for this effect

가능한$._cache 요소에 비해 성능이 크게 향상되지는 않습니다 . 해당 요소를 선택 하고 잡는 것이 훨씬 빠르지 만 훨씬 더 많은 정보를 얻을 수 있으며 "jQuery-ey"는 아닙니다. 물건 (일반적으로 요소 측면에서 나옵니다). 내 머리 꼭대기에서 나는 고유 ID에서 요소로 이동하는 프로세스가 성능 측면에서 자체적으로 복잡하기 때문에 어쨌든 이것이 가장 빠르지 않다.

언급 한 비교 선택기는에서 가장 잘 수행 .filter()할 수 있지만 플러그인에는 기본적으로 지원되지 않지만 많은 문제없이 추가 할 수 있습니다.


철저한 답변에 감사드립니다. HTML5 data-*속성을 사용하고 속성을 선택하는 것이 속성을 선택하는 것보다 더 빠른지 알고 .data()있습니까? 또한 $ ._ cache에 대한 자세한 정보는 어디에서 찾을 수 있습니까? 나는 그것을 구글 검색했지만 많이 찾지 못했습니다.
Tauren

@Tauren-내 잘못은 $.cache아닙니다 $._cache.jQuery 코어에서 어떻게 구현되고 사용되는지 확인할 수 있습니다 : github.com/jquery/jquery/blob/master/src/data.js#L4 호출 .data()하면 실제로 객체로 저장됩니다 in $.cache[elementUniqueID], 이것은 1, 2, 3 등과 같이 각 요소에 필요한 방식으로 필요에 따라 할당 된 Id입니다. 그 등반 ID는 jQuery 1.4.3에 노출 될 것입니다. HTML 5 경로가 더 빠르다고 가정하고 사용 가능한 브라우저 최적화에 따라 다릅니다 (더 많은 기능이 제공 될 것입니다).
Nick Craver

7

data-*사용하여 elm에 속성을 설정 한 attr()다음 해당 속성을 사용하여 선택할 수 있습니다 .

var elm = $('a').attr('data-test',123); //assign 123 using attr()
elm = $("a[data-test=123]"); //select elm using attribute

지금 그 느릅 나무를 위해, 모두 attr()data()얻을 것 123 :

console.log(elm.attr('data-test')); //123
console.log(elm.data('test')); //123

당신이 할 값을 수정할 경우, 456을 사용하여 attr(), data() 여전히 것 123 :

elm.attr('data-test',456); //modify to 456
elm = $("a[data-test=456]"); //reselect elm using new 456 attribute

console.log(elm.attr('data-test')); //456
console.log(elm.data('test')); //123

내가 이해 한 것처럼, 필요하지 않으면 코드에서 혼합 attr()data()명령을 피해야 할 것 같습니다 . 있으므로 attr()반면 DOM 직접 대응 같다 data()초기 값이 될 수 DOM에서 불구하고, '메모리'와 상호 작용한다. 그러나 핵심은 두 가지가 반드시 동기화되어 있지는 않다는 것입니다.

그러니 조심하세요

어쨌든 data-*DOM 또는 메모리에서 속성을 변경 하지 않으면 문제가 없습니다. 곧 값을 수정하기 시작하면 잠재적 인 문제가 발생할 수 있습니다.

@Clarence Liu에게 @Ash의 답변 과이 게시물에 감사드립니다 .



5

당신은 또한 jQueryUI를 사용하는 경우, 당신은의 (간단한) 버전을 얻을 :data당신이 뭔가를 할 수 있도록 데이터 항목의 존재를 그것으로 그 검사를 선택을 $("div:data(view)")하거나 $( this ).closest(":data(view)").

http://api.jqueryui.com/data-selector/를 참조하십시오 . 나는 그들이 얼마나 오래했는지 알지 못하지만 지금 거기 있습니다!


이것은 당신이 말한 것처럼 데이터 항목의 존재를 확인합니다. (문서에 따라) 값을 확인하지 않습니다. 그래도
알아서 반가워요

3

다음은 생활을 단순화하는 플러그인입니다 https://github.com/rootical/jQueryDataSelector

다음과 같이 사용하십시오.

data selector           jQuery selector
  $$('name')              $('[data-name]')
  $$('name', 10)          $('[data-name=10]')
  $$('name', false)       $('[data-name=false]')
  $$('name', null)        $('[data-name]')
  $$('name', {})          Syntax error
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.