Драйвер события, изменив признак этикетки

Драйвер события существует в языке сценариев JavaScript для, когда станет отвечающей совремнным требованиям стоимость признака? И конкретнее для случая src одного img.

Я не отношусь в load (что бросается, когда изображение было загружено), а в раньше, в, когда стоимость src он меняется (он может проводить время пока загружается изображение до того, как он бросился load).

Например, если у меня есть изображение и через код он меняется src, с этого момента до тех пор, пока он не загрузится и покажет изображение, мне хотелось бы показывать сообщение "Грузя".

Это что-то, что существует в языке сценариев JavaScript прямо (и как)?

5
задан 10.01.2017, 19:23
0 ответов

Возможно использовать MutationObserver (проверять совместимость).

Состой в создании объекта:

var miMO = new MutationObserver(callback);

И звонить в observe(nodo, opciones) с узлом, который будет наблюдаться, и выборами, чтобы определять, когда взрывается callback. Выборы - объект MutationObserverInit, который соглашается:

  • childList - Если он true, наблюдай прибавления и уничтожение узлов дети (включая textNodes).
  • attributes - Если он true, наблюдай изменения в признаках узла.
  • characterData - Если он true, наблюдай изменения в дате узла.
  • subtree - Если он true, также наблюдай изменения в потомках узла.
  • attributeOldValue - Если он true (с attributes в true), он взрывается перед изменением в признаке.
  • characterDataOldValue - Если он true (с characterData в true), он взрывается перед изменением в дате.
  • attributeFilter - array признаков, если только хочется наблюдать специфический список.


Благодеяние использования MutationObserver состоит в том, что он взрывается с любым изменением в DOM. Возможно стрелять, когда он изменяется с кода, с рукописным шрифтом пользователя, или даже, когда тот же пользователь издает DOM вручную. В пользу такого мотива, важно, чтобы фильтры, перемещенные за выборы были больше возможных специфических средств, для того, чтобы использование ресурсов не было таким интенсивным.


Например, чтобы наблюдать изменения в src изображения:

var miImg = document.getElementById('idDeImg'),
    miMO  = new MutationObserver(callback);

miMO.observe(miImg, {
    attributes: true,
    attributeFilter: [
        'src'
    ]
});


И потом он назовет callback с коллекцией MutationRecord. В особенности, каждого элемента коллекции, нам будет интересно проверять, что .attributeName == "src". А именно, что изменил себе это специфическое свойство. Эта проверка избыточная с фильтрами, которые мы перемещаем только что, но я это оставляю в случае, если будет хотеться добавлять другое изменение, в которое стреляет callback.


Пример:

var miImg = document.getElementById('idDeImg'),
    miMO  = new MutationObserver(callbackMO);

miMO.observe(miImg, {
    attributes: true,
    attributeOldValue: true,
    attributeFilter: ['src']
});

function callbackMO(mutations) {
    mutations.forEach((mutation) => {
        if (mutation.attributeName == "src") { // <- redundante
            console.log('Se cambió la imagen de', mutation.oldValue, 'a', mutation.target.src);
        }
    });
}


//Prueba cambiando el src
function cambiarSrc() {
    miImg.src = "https://i.stack.imgur.com/f4AWis.jpg";
}
<img id="idDeImg" src="https://i.stack.imgur.com/knEtbs.jpg">
<br>
<input type="button" onclick="cambiarSrc()" value="Probar cambiar el src">
5
ответ дан 03.12.2019, 17:46
  • 1
    Leí в эта листает , что только благосклонно принятые MutationObserver ú nico элемент и не colecció n их ¿ Это верно или только применяет для примера эту страницу? –  10.01.2017, 20:25
  • 2
    @JuankGlezz Докуда прибывает мой imaginació n, só он это применяет к этому примеру (из-за того, что не означает, что está спутанный). Así как tambié n я понимаю, чем с фильтрами, что usé в этом ответе, só podrí чтобы стрелять в ú nico я меняюсь (src só он может менять это однажды из-за mutació n). Но это фальшивый для общего случая. Пример: jsfiddle.net/marianom/zfwytxpg ... Это особенно vá lido с contentEditable, или когда пользователь издает DOM вручную. –  10.01.2017, 21:22

Докуда нет родного события, но ты можешь использовать proxy ES6 (или использовать polyfill, если ты нуждаешься ES5), и бросать персонализированное событие, когда изменяется свойство.

В следующий пример верьте proxy для set и get, и брось персонализированное событие, если свойство src она изменена.

// preparacion del proxy
function ImageProxy(element) {
  return new Proxy(element, {
    get(target, propKey, receiver) {
      return element[propKey];
    },
    set(target, propKey, value, receiver) {
      // aqui disparas el evento.
      if (propKey === 'src' && target.onsrcchanged) {
        target.onsrcchanged(target[propKey], value)
      }
      target[propKey] = value;
    }
  });
}

let el = document.createElement('img');
document.body.append(el);

// creas el proxy
let elProxy = ImageProxy(el);

// este es el manejador del evento
elProxy.onsrcchanged = function(oldVal, newVal) {
  console.log('se ha modificadoimg.src =', newVal);
}

// aqui cambias 
elProxy.src = 'http://lorempixel.com/400/200/sports';
console.log(elProxy.src);

setTimeout(function() {
  // vuelves a cambiar
  elProxy.src = 'http://lorempixel.com/400/200/nature';
  console.log(elProxy.src);
}, 5000);

Также возможно делать это с Object.definePropery, он действительно достаточно сходный и совместим с ES5 без необходимости polyfils.

function ImageNonProxy(image) {
  Object.defineProperty(image, 'src', {
    set: function(srcAttr) {
      if (image.onsrcchanged) {
        image.onsrcchanged(image.getAttribute('src'), srcAttr)
      }
      image.setAttribute('src', srcAttr);
    },
    get: function() {
      return image.getAttribute('src');
    }
  });
  return image
}

var el = document.createElement('img');
document.body.append(el);

// creas el proxy
let elProxy = ImageNonProxy(el);

// este es el manejador del evento
elProxy.onsrcchanged = function(oldVal, newVal) {
  console.log('se ha modificadoimg.src =', newVal);
}

// aqui cambias 
elProxy.src = 'http://lorempixel.com/400/200/sports';
console.log(elProxy.src);

setTimeout(function() {
  // vuelves a cambiar
  elProxy.src = 'http://lorempixel.com/400/200/nature';
  console.log(elProxy.src);
}, 5000);
4
ответ дан 03.12.2019, 17:46

Существуй API MutationObserver (IE11+)

Используя счастье API в сочетании с событие onload тебе может удаваться узнать точно момент, в котором наставили ее грузить, и когда он закончился (успешно)

var img = document.getElementById('image');
var loader = document.getElementById('loader');
var btn = document.getElementById('button');

// Creamos un observador y pasamos la función que sera invocada 
// cada vez que se realice alguna mutación
var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    // Si la mutacion fue sobre un atributo y especificamente sobre el "src"
    if (mutation.type === 'attributes' && mutation.attributeName === 'src') {
      console.log('Load Started!');
      loader.style.display = 'block';
    }
  });    
});
var config = {attributes: true};

// Suscribimos el observer a la img con la config deseada
observer.observe(img, config);

btn.addEventListener('click', function() {
  img.src = 'https://i.imgur.com/xkKw5r8.jpg';
});
img.addEventListener('load', function() {
  console.log('Load Finished!');
  loader.style.display = 'none';
});
#image {
  width: 300px;
}

#loader {
  display: none;
}
<button id="button">Cargar imagen</button>
<br/><br/>
<img id="image" />
<div id="loader">Cargando...</div>
4
ответ дан 03.12.2019, 17:46

Теги

Похожие вопросы