Понимание Vue.js Порядок привязки классов CSS

#javascript #css #vue.js

#javascript #css #vue.js

Вопрос:

Кто-нибудь может помочь мне понять, как управлять порядком css-класса корневого элемента компонента и любого css-класса, который может быть привязан к родительскому элементу, вызывающему компонент?

Вот скрипт, который отображает то, что я замечаю (пример фрагмента ниже): https://jsfiddle.net/cicsolutions/b6rnaw25 /

Вы заметите, что если у вас есть компонент с классом в его корневом элементе, если этот класс является строкой, привязка класса Vue помещает класс в начало результирующего списка связанных классов. Это то, чего я ожидал, потому что, поскольку компонент задает базовый класс css, а затем вы можете настраивать стили при использовании компонента, добавляя классы к элементу html компонента. Затем Vue связывает / объединяет классы вместе.

В следующих примерах в скрипте я показываю использование динамического класса css (т. Е. не статической строки). В этих случаях Vue помещает класс корневого элемента компонента в конец списка связанных классов.

Я работаю над компонентом, который, я надеюсь, будут использовать другие, поэтому я хотел бы установить свой класс component в корневом элементе, а затем, если кто-то захочет переопределить эти стили, они могут просто добавить свой собственный класс в тег component.

Мне также нужно, чтобы класс корневого элемента был динамическим, поэтому я должен использовать массив или объект для обработки привязки класса.

Кто-нибудь знает, почему Vue помещает корневой css-класс компонента в начало для статических классов и в конец для динамических классов? Мне это кажется странным, но, возможно, это сделано намеренно по причине, которая от меня ускользает.

Тем не менее, как мне добиться того, чтобы класс корневого элемента моего компонента всегда был первым в результирующем списке связанных классов, когда мне нужно, чтобы это был динамический класс?

 Vue.directive('bound-class', (el) => {
	const boundClass = el.attributes.class.nodeValue
  const boundClassPrintout = document.createElement('div')
  boundClassPrintout.innerHTML = 'Resulting Bound Class: '   boundClass
  el.appendChild(boundClassPrintout)
});

// STATIC CSS CLASS -> becomes 1st class in bound class list (expected)
Vue.component('string-test', {
	template: `<div class="string-class" v-bound-class><slot></slot></div>`
});

// DYNAMIC CSS CLASS -> becomes last class in bound class list (unexpected)
Vue.component('array-test', {
	template: `<div :class="['array-class']" v-bound-class><slot></slot></div>`
});

// DYNAMIC CSS CLASS -> becomes last class in bound class list (unexpected)
Vue.component('object-test', {
	template: `<div :class="{ 'object-class': true }" v-bound-class><slot></slot></div>`
});

new Vue({
  el: "#app",
  computed: {
  	vueVersion() {
    	return Vue.version
    }
  }
})  
 body {
  background: #20262E;
  padding: 20px;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
}

h2 {
  margin-bottom: 0.75rem;
}  
 <link href="https://cdn.jsdelivr.net/npm/tailwindcss/dist/tailwind.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <h2>Vue version: {{ vueVersion }}</h2>
  <string-test class="p-2 mb-2 border">Root class (string-class) at beginning (expected)</string-test>
  <array-test class="p-2 mb-2 border">Root class (array-class) at end (unexpected)</array-test>
   <object-test class="p-2 mb-2 border">Root class (object-class) at end (unexpected)</object-test>
</div>  

Комментарии:

1. 1. Ваша ссылка на скрипку не работает. 2. Если я правильно понял вопрос, вы пытаетесь контролировать порядок добавления классов CSS к элементу. Это верно? Если да, то почему? Порядок классов не имеет значения.

2. исправлена ссылка на скрипку, спасибо, что отметили! Да, вы правильно поняли вопрос. Мне также просто любопытно в целом, почему Vue обрабатывает классы по-разному в зависимости от того, как вы их устанавливаете. Vue настолько умен, так что, вероятно, на то есть веская причина. Классы CSS каскадируются, поэтому порядок действительно имеет значение.

3. Боюсь, ваше понимание каскада CSS ошибочно. Смотрите codepen.io/sathomas/pen/WmoaGw

Ответ №1:

Я подозреваю, что нет особой причины, по которой Vue сначала вставляет статические классы; возможно, это просто зеркальное отображение порядка входных параметров в renderClass функции.

Также порядок наборов правил в файлах CSS имеет значение; порядок имен классов в class атрибуте elements — нет. И ни один из этих порядков не имеет ничего общего с каскадом, который ссылается на дочерние элементы, наследующие стили от своих родителей. Возможно, вы перепутали это с порядком объявлений внутри блока или внутри встроенного стиля. В этом случае порядок имеет значение:

 <p class="red blue">
    Order doesn't matter in the class attribute above. If
    the class styles contradict, whichever is defined last
    will win regardless of how they're ordered in the attribute.
</p>

<p class="blue red">
    This paragraph will be styled identically to the previous
    one, despite the change in class order.
</p>

<p style="color: red; color: blue">
    Order does matter here. The text color will be blue.
</p>
  

Комментарии:

1. Спасибо! Я ценю ваше подробное и полезное объяснение!

2. Как, черт возьми, вы узнали, где ссылаться на renderClass подобным образом?! Есть ли чтение / документация помимо документов Vue и форумов, которая объясняет архитектуру более подробно? Или вы просто изучаете исходные файлы?

3. Просто читаю исходный код. Хотя в Vue Mastery есть довольно хорошая серия статей о внутренностях и архитектуре Vue, если вы ищете дополнительную информацию

4. Большое вам спасибо! Признателен за ваше подробное объяснение 🙂