最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to handle or minimize tight coupling in jquery - Stack Overflow

programmeradmin2浏览0评论

Description

By design most jquery code leads to a lot of tight coupling, e.g. selectors assume a specific structure of html

var mySubnav = $("#navigation a.sub-menu");

If the corresponding html changes, for whatever reasons,

<a class="subMenu" .... </a>

functionality is broken.

Question

  • What's the best way to handle tight coupling?
  • What approaches exist to loosen it up?

Answers, Approaches

  • use the html custom data attribute to separate css from js logic. e.g. add data-submenu="true" on the html and use var mySubnav = $("[data-submenu]"); on the js side.
  • implement a solid testing environment
  • couple as loose as possible, by using the least specific selectors, e.g. $("a.sub-menu'). See also
  • Eliminate the actual string literals that represent CSS selectors from the body of your jQuery code by (1) retrieving references to static DOM elements beforehand, and (2) storing selector strings in one place (at the top of your code).
  • use javascript frameworks, like Backbone, which decouple javascript from the DOM via views
  • use delegate and live regarding coupling due to event management

Description

By design most jquery code leads to a lot of tight coupling, e.g. selectors assume a specific structure of html

var mySubnav = $("#navigation a.sub-menu");

If the corresponding html changes, for whatever reasons,

<a class="subMenu" .... </a>

functionality is broken.

Question

  • What's the best way to handle tight coupling?
  • What approaches exist to loosen it up?

Answers, Approaches

  • use the html custom data attribute to separate css from js logic. e.g. add data-submenu="true" on the html and use var mySubnav = $("[data-submenu]"); on the js side.
  • implement a solid testing environment
  • couple as loose as possible, by using the least specific selectors, e.g. $("a.sub-menu'). See also
  • Eliminate the actual string literals that represent CSS selectors from the body of your jQuery code by (1) retrieving references to static DOM elements beforehand, and (2) storing selector strings in one place (at the top of your code).
  • use javascript frameworks, like Backbone, which decouple javascript from the DOM via views
  • use delegate and live regarding coupling due to event management
Share Improve this question edited May 23, 2017 at 11:53 CommunityBot 11 silver badge asked Jul 25, 2011 at 18:22 SunnyRedSunnyRed 3,5454 gold badges37 silver badges57 bronze badges 2
  • Related question: stackoverflow.com/questions/5682748/… – Chetan Commented Jul 25, 2011 at 18:32
  • Related: jondavidjohn.com/blog/2012/04/… – jondavidjohn Commented Apr 19, 2012 at 19:20
Add a comment  | 

7 Answers 7

Reset to default 6

This may not be a popular answer, but... testing, testing, testing. JQuery and Javascript in general are typically tightly coupled, and for good reason; they're code running in the browser, and so you want to keep the performance relatively snappy. So injecting an indirection layer that allows for looser coupling can decrease performance; as well, it can be a bit of overkill, since there's typically a close pairing between the JQuery / Javascript code that's written and the pages they're written for; this is as much an artifact of the historical development of Javascript, but that's the way that it is. As such, the tight coupling is pretty "normal".

The way to deal with this tight coupling, like any tight coupling, is to make sure that you've got good testing in place to cover any coupling failures. Testing can provide assurance that the coupling is proper, and it's really the best way to assure the functionality you expect anyway.

One option is to use a Javascript framework, like Backbone. It gives you the concept of views which help decouple your Javascript from the DOM structure. For example, you can create the Comment view, which you assign to the following div:

<div class="comment">
    <span class="title"></span>
    <p class="body"></p>
</div>

And then you can access elements in the view relative to the comment div:

var title = this.$(".title");

This makes it easy to change the DOM structure outside of the comment div as long as the internals of the comment div remain the same.

Use Custom prefixed classes for UI hooks ui-specificGuy

Provided HTML

<div class="container grid8">
    <ul class="ul1 horizontal">
        <li>List Item 1</li>
        <li>List Item 2</li>
    </ul>
</div>

Bad - using style purposed classes/hooks

$('.container.grid8').stuff();
$('.ul1.horizontal').moreStuff();

Adjusting the HTML

<div class="container grid8 ui-specificContainer">
    <ul class="ul1 horizontal ui-specificList">
        <li>List Item 1</li>
        <li>List Item 2</li>
    </ul>
</div>

Good - using your own purposed classes/hooks

$('.ui-specificContainer').stuff();
$('.ui-specificList').moreStuff();

Only be as specific as neccessary

If this will accomplish your goal.

$('.ui-targetedElement')

Then why have a selector that looks like this?

$('ul > li a.ui-targetedElement')

This simply introduces unnecessary DOM structure dependencies into the functionality you are building, and you should be able to be proactive in this regard because you should be providing your own hooks (prefixed classes) at this point right?

Ultimately though I would say that tight coupling between the DOM and the script are sometimes unavoidable because of the nature of how they work together.

Full Article

If you are talking in respect to event management then make as much use of delegates and live which are not tightly coupled to the dom structure. Take a look at the below urls

Live - http://api.jquery.com/live/

Delegate - http://api.jquery.com/delegate/

My suggestion would be to:

  1. retrieve the references of static DOM elements on DOM ready and put them in variables or properties of an object or whatever.

  2. store class names inside an object (or several objects or whatever, as long as those names (strings) are in one place)

Then you can do this:

var mySubnav = $('a.' + C.submenu, navigation);

where navigation is a reference to the #navigation element and C is the class-names object which submenu property is the string "sub-menu".

Now, when you change class-names in your HTML code, you only have to update the C object.

The idea is to get rid of the actual string literals that represent CSS selectors from the body of your jQuery code by (1) retrieving references to static DOM elements beforehand, and (2) storing selector strings in one place (at the top of your code).

If your html changes, the all bets are off.

And what you have is not tight coupling. It is essential for your code to function.

E.g., this is what I would consider tight coupling:

<a class="subMenu" onclick="doSomething()"> .... </a>

The loose version would be:

$("#navigation a.sub-menu').click(function(){
   //do something
});

What about using html5 data attributes to do javascript selectors?

<a data-submenu="true" .... </a>

var mySubnav = $("[data-submenu]");

Makes it really clear that javascript is operating on the html.

发布评论

评论列表(0)

  1. 暂无评论