DOMTokenList接口的 add() 方法将给定的标记添加到列表中,remove() 方法从 DOMTokenList 中移除指定标记。
添加或者移除class:
document.getElementById('id').classList.add('class');
document.getElementById('id').classList.remove('class');
DOMTokenList 接口的 toggle() 方法从列表中删除一个给定的标记 并返回 false 。
如果标记 不存在,则添加并且函数返回 true。
或者使用toggle切换一个类(如果存在则删除,否则添加它):
document.getElementById('id').classList.toggle('class');
面向对象的编程中,class 是用于创建对象的可扩展的程序代码模版,它为对象提供了状态(成员变量)的初始值和行为(成员函数或方法)的实现。
Wikipedia
在日常开发中,我们经常需要创建许多相同类型的对象,例如用户(users)、商品(goods)或者任何其他东西。
正如我们在 构造器和操作符 "new" 一章中已经学到的,new function 可以帮助我们实现这种需求。
但在现代 JavaScript 中,还有一个更高级的“类(class)”构造方式,它引入许多非常棒的新功能,这些功能对于面向对象编程很有用。
基本语法是:
class MyClass {
// class 方法
constructor() { ... }
method1() { ... }
method2() { ... }
method3() { ... }
...
}
然后使用 new MyClass() 来创建具有上述列出的所有方法的新对象。
new 会自动调用 constructor() 方法,因此我们可以在 constructor() 中初始化对象。
例如:
class User {
constructor(name) {
this.name = name;
}
sayHi() {
alert(this.name);
}
}
// 用法:
let user = new User("John");
user.sayHi();
当 new User("John") 被调用:
……然后我们就可以调用对象方法了,例如 user.sayHi。
类的方法之间没有逗号
对于新手开发人员来说,常见的陷阱是在类的方法之间放置逗号,这会导致语法错误。
不要把这里的符号与对象字面量相混淆。在类中,不需要逗号。
所以,class 到底是什么?正如人们可能认为的那样,这不是一个全新的语言级实体。
让我们揭开其神秘面纱,看看类究竟是什么。这将有助于我们理解许多复杂的方面。
在 JavaScript 中,类是一种函数。
看看下面这段代码:
class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// 佐证:User 是一个函数
alert(typeof User); // function
class User {...} 构造实际上做了如下的事儿:
当 new User 对象被创建后,当我们调用其方法时,它会从原型中获取对应的方法,正如我们在 F.prototype 一章中所讲的那样。因此,对象 new User 可以访问类中的方法。
我们可以将 class User 声明的结果解释为:
下面这些代码很好地解释了它们:
class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// class 是一个函数
alert(typeof User); // function
// ...或者,更确切地说,是 constructor 方法
alert(User === User.prototype.constructor); // true
// 方法在 User.prototype 中,例如:
alert(User.prototype.sayHi); // alert(this.name);
// 在原型中实际上有两个方法
alert(Object.getOwnPropertyNames(User.prototype)); // constructor, sayHi
人们常说 class 是一个语法糖(旨在使内容更易阅读,但不引入任何新内容的语法),因为我们实际上可以在没有 class 的情况下声明相同的内容:
// 用纯函数重写 class User
// 1. 创建构造器函数
function User(name) {
this.name = name;
}
// 函数的原型(prototype)默认具有 "constructor" 属性,
// 所以,我们不需要创建它
// 2. 将方法添加到原型
User.prototype.sayHi = function() {
alert(this.name);
};
// 用法:
let user = new User("John");
user.sayHi();
这个定义的结果与使用类得到的结果基本相同。因此,这确实是将 class 视为一种定义构造器及其原型方法的语法糖的理由。
尽管,它们之间存在着重大差异:
此外,class 语法还带来了许多其他功能,我们稍后将会探索它们。
就像函数一样,类可以在另外一个表达式中被定义,被传递,被返回,被赋值等。
这是一个类表达式的例子:
let User = class {
sayHi() {
alert("Hello");
}
};
类似于命名函数表达式(Named Function Expressions),类表达式可能也应该有一个名字。
如果类表达式有名字,那么该名字仅在类内部可见:
// “命名类表达式(Named Class Expression)”
// (规范中没有这样的术语,但是它和命名函数表达式类似)
let User = class MyClass {
sayHi() {
alert(MyClass); // MyClass 这个名字仅在类内部可见
}
};
new User().sayHi(); // 正常运行,显示 MyClass 中定义的内容
alert(MyClass); // error,MyClass 在外部不可见
我们甚至可以动态地“按需”创建类,就像这样:
function makeClass(phrase) {
// 声明一个类并返回它
return class {
sayHi() {
alert(phrase);
}
};
}
// 创建一个新的类
let User = makeClass("Hello");
new User().sayHi(); // Hello
就像对象字面量,类可能包括 getters/setters,计算属性(computed properties)等。
这是一个使用 get/set 实现 user.name 的示例:
class User {
constructor(name) {
// 调用 setter
this.name = name;
}
get name() {
return this._name;
}
set name(value) {
if (value.length < 4) {
alert("Name is too short.");
return;
}
this._name = value;
}
}
let user = new User("John");
alert(user.name); // John
user = new User(""); // Name is too short.
从技术上来讲,这样的类声明可以通过在 User.prototype 中创建 getters 和 setters 来实现。
这里有一个使用中括号 [...] 的计算方法名称示例:
class User {
['say' + 'Hi']() {
alert("Hello");
}
}
new User().sayHi();
这种特性很容易记住,因为它们和对象字面量类似。
旧的浏览器可能需要 polyfill
类字段(field)是最近才添加到语言中的。
之前,我们的类仅具有方法。
“类字段”是一种允许添加任何属性的语法。
例如,让我们在 class User 中添加一个 name 属性:
class User {
name = "John";
sayHi() {
alert(`Hello, ${this.name}!`);
}
}
new User().sayHi(); // Hello, John!
所以,我们就只需在表达式中写 " = ",就这样。
类字段重要的不同之处在于,它们会在每个独立对象中被设好,而不是设在 User.prototype:
class User {
name = "John";
}
let user = new User();
alert(user.name); // John
alert(User.prototype.name); // undefined
我们也可以在赋值时使用更复杂的表达式和函数调用:
class User {
name = prompt("Name, please?", "John");
}
let user = new User();
alert(user.name); // John
正如 函数绑定 一章中所讲的,JavaScript 中的函数具有动态的 this。它取决于调用上下文。
因此,如果一个对象方法被传递到某处,或者在另一个上下文中被调用,则 this 将不再是对其对象的引用。
例如,此代码将显示 undefined:
class Button {
constructor(value) {
this.value = value;
}
click() {
alert(this.value);
}
}
let button = new Button("hello");
setTimeout(button.click, 1000); // undefined
这个问题被称为“丢失 this”。
我们在 函数绑定 一章中讲过,有两种可以修复它的方式:
类字段提供了另一种非常优雅的语法:
class Button {
constructor(value) {
this.value = value;
}
click = () => {
alert(this.value);
}
}
let button = new Button("hello");
setTimeout(button.click, 1000); // hello
类字段 click = () => {...} 是基于每一个对象被创建的,在这里对于每一个 Button 对象都有一个独立的方法,在内部都有一个指向此对象的 this。我们可以把 button.click 传递到任何地方,而且 this 的值总是正确的。
在浏览器环境中,它对于进行事件监听尤为有用。
基本的类语法看起来像这样:
class MyClass {
prop = value; // 属性
constructor(...) { // 构造器
// ...
}
method(...) {} // method
get something(...) {} // getter 方法
set something(...) {} // setter 方法
[Symbol.iterator]() {} // 有计算名称(computed name)的方法(此处为 symbol)
// ...
}
技术上来说,MyClass 是一个函数(我们提供作为 constructor 的那个),而 methods、getters 和 settors 都被写入了 MyClass.prototype。
在下一章,我们将会进一步学习类的相关知识,包括继承和其他功能。
于class和style我们并不陌生,这个在学习css的时候就是家常便饭了,操作元素的 class 列表和内联样式是数据绑定的一个常见需求。因为它们都是属性,所以我们可以用 v-bind 处理它们,只需要通过表达式计算出字符串结果即可。不过,字符串拼接麻烦且易错。因此,在将 v-bind 用于 class 和 style 时,Vue.js 做了专门的增强。表达式结果的类型除了字符串之外,还可以是对象或数组,所以本章将带你了解vue中如何绑定class和style。
在Vue中,我们可以将DOM元素通过Vue的绑定机制,实现我们想要的样式。接下来看style如何实现绑定。
我们先来看个简单基础的动画案例,大家看案例代码:
例7-1 Demo0701.html
程序的运行结果如下:
图 7- 1 直接在元素中加入style原生态样式
通过例7-1中,我们可以像往常一样直接在元素上添加行内样式。
在Vue中有属性绑定,我们也可以通过属性绑定直接加行内样式,如下代码所示:
<div id="app">
<!-- 直接添加原生态的样式 -->
<h1 style="color:red">原生态的style样式</h1>
<!-- 通过vue属性绑定直接添加 -->
<h1 :style="'color:red;font-size:60px;'">属性绑定添加的style样式</h1>
</div>
程序的运行结果如下:
图 7- 2 通过属性绑定添加样式
通过以上示例代码,我们发现通过属性绑定和直接添加非常像,但是大家认真观察,属性绑定必须加双重引号(双中加单,单中加双),这是因为,如果不对样式规则加引号,则默认会去Vue实例中寻找对应的数据,但是这些并不是Vue实例中的数据而是我们自己顶的规则,所以必须加引号。
刚才使用属性绑定的是一个普通的文本,一般在Vue中,属性绑定的是data中的数据,我们来看如下代码:
<body>
<div id="app">
<!-- 直接添加原生态的样式 -->
<h1 style="color:red">原生态的style样式</h1>
<!-- 通过vue属性绑定直接添加 -->
<h1 :style="'color:red;font-size:60px;background-color:pink;'">属性绑定添加的style样式</h1>
<!-- 通过vue的数据对象添加样式 -->
<h1 :style="styleObj"> 通过vue的数据对象添加样式</h1>
</div>
</body>
<script>
let vm = new Vue({
el: '#app',
data: {
styleObj: "color:green;font-size:80px;background-color:red;",
}
});
</script>
属性绑定的是data中一个数据,该数据写的是样式规则。
也可以绑定一个对象,在该对象中使用js语法控制样式规则:
示例如下:
<body>
<div id="app">
<!-- 直接添加原生态的样式 -->
<h1 style="color:red">原生态的style样式</h1>
<!-- 通过vue属性绑定直接添加 -->
<h1 :style="'color:red;font-size:60px;background-color:pink;'">属性绑定添加的style样式</h1>
<!-- 通过vue的数据对象添加样式 -->
<h1 :style="styleObj"> 通过vue的数据对象添加样式</h1>
<!-- 通过vue的对象添加样式 -->
<h1 :style="testObj"> 通过vue的数据对象添加样式</h1>
</div>
</body>
<script>
let vm = new Vue({
el: '#app',
data: {
styleObj: "color:green;font-size:80px;background-color:red;",
testObj: {
color: 'blue',//注意是对象,对象的各个属性之间使用逗号隔开,而不是分号
fontSize: '90px',
backgroundColor: 'pink'
}
}
});
</script>
注意:在该示例代码中,我们使用的是一个object类型的数据来定义样式,在这必须使用JavaScript操控style的语法规则来定义对象的各个属性,而且属性值必须是字符串,使用引号括起来。
在正常的样式中,一个DOM元素可以同时应用多个样式规则,在Vue中,也可以绑定到一个数组对像,同时应用多个样式规则,示例代码如下:
<body>
<div id="app">
<!-- 直接添加原生态的样式 -->
<h1 style="color:red">原生态的style样式</h1>
<!-- 通过vue属性绑定直接添加 -->
<h1 :style="'color:red;font-size:60px;background-color:pink;'">属性绑定添加的style样式</h1>
<!-- 通过vue的数据对象添加样式 -->
<h1 :style="styleObj"> 通过vue的数据对象添加样式</h1>
<!-- 通过vue的对象添加样式 -->
<h1 :style="testObj"> 通过vue的数据对象添加样式</h1>
<!-- 绑定数组 -->
<h1 :style="[styleObj,testObj]"> 绑定数组</h1>
</div>
</body>
<script>
let vm = new Vue({
el: '#app',
data: {
styleObj: "color:green;font-size:80px;background-color:red;",
testObj: {
color: 'blue',//注意是对象,对象的各个属性之间使用逗号隔开,而不是分号
fontSize: '90px',
backgroundColor: 'pink'
}
}
});
</script>
在绑定数组的时候,数组中的元素来源于data中的数据,所以不需要加引号。
除了进行style行内样式的绑定,也可以进行class样式的绑定。
可以直接在DOM元素上加入class属性,进行定义样式,示例如下:
<style>
.red {
color: red;
}
.bk {
background-color: pink;
}
</style>
</head>
<body>
<div id="app">
<!-- 直接添加原生态的样式 -->
<h1 class="red bk">直接添加class样式</h1>
</div>
</body>
<script>
let vm = new Vue({
el: '#app',
data: {
}
});
</script>
直接在DOM元素上通过class属性添加多个class样式规则,注意此时class没有加冒号。
通过Vue的属性绑定,示例代码如下:
<style>
.red {
color: red;
}
.bk {
background-color: pink;
}
</style>
</head>
<body>
<div id="app">
<!-- 直接添加原生态的样式 -->
<h1 class="red bk">直接添加class样式</h1>
<!-- 属性绑定添加 -->
<h1 :class="'red bk'">属性绑定添加</h1>
</div>
</body>
<script>
let vm = new Vue({
el: '#app',
data: {
}
});
</script>
程序运行结果如下:
图 7- 3 原生态和属性绑定添加
通过属性绑定添加,后面的class类名要加引号,否则会去data中寻找red和bk这样的变量,如果加了,则是直接引用这两个class样式。
现在我们让属性绑定一个data中的数据对象,示例代码如下:
<style>
.red {
color: red;
}
.bk {
background-color: pink;
}
.fs {
font-size: larger;
font-style: italic;
}
</style>
</head>
<body>
<div id="app">
<!-- 直接添加原生态的样式 -->
<h1 class="red bk">直接添加class样式</h1>
<!-- 属性绑定添加 -->
<h1 :class="'red bk'">属性绑定添加</h1>
<!-- 对象绑定 -->
<h1 :class="clsobj">对象绑定</h1>
</div>
</body>
<script>
let vm = new Vue({
el: '#app',
data: {
flag: true,
clsobj: {
'red': true,
'bk': true,
'fs': true
}
}
});
</script>
程序运行结果如下:
图 7- 4 使用Vue对象绑定
使用对象的时候,对象的属性就是class的类名,值是Boolean类型,如果是true则是启用这个类样式,否则则是不使用。
style样式代码:
<style>
.red {
color: red;
}
.thin {
font-weight: 200;
}
.italic {
font-style: italic;
}
.active {
letter-spacing: 0.5em;
}
</style>
示例代码:
<!-- 第一种使用方式,直接传递一个数组,注意: 这里的 class 需要使用 v-bind 做数据绑定 -->
<h2 :class="['red','thin']">这是一个很大很大的H2,大到你无法想象!!!</h2>
数组中的元素必须加引号,否则会去Vue实例中寻找对应的变量数据。
示例代码:
<!-- 第二种使用方式,在数组中使用三元表达式 -->
<h3 :class="['thin', 'italic', flag?'active':'']">这是一个很大很大的H3,大到你无法想象!!!</h3>
这上面使用的data中的数据flag,如果flag为true,则使用active这个class样式,否则是空样式。
示例代码:
<!-- 第三种使用方式,在数组中使用 对象来代替三元表达式,提高代码的可读性 -->
<h4 :class="['thin', 'italic', {active:flag} ]">这是一个很大很大的H4,大到你无法想象!!!</h4>
上述示例数组中第三个元素是个对象,对象的键是style中已知存在的类名,值是boolean类型,如果为true,则采用该类样式,否则则不采用。
总结:设置class样式需要使用v-bind绑定;
1、使用[]设置样式,中括号里的样式必须加引号,否则被识别为变量;
2、可以使用对象表示class样式,键是类名,值是Boolean类型
3、使用对象类名可以不加引号,但是为了区别变量,建议加上;
当在一个自定义组件上使用 class property 时,这些 class 将被添加到该组件的根元素上面。这个元素上已经存在的 class 不会被覆盖。
例如,如果你声明了这个组件:
Vue.component('my-component', {
template: '<p class="foo bar">Hi</p>'
})
然后在使用它的时候添加一些 class:
<my-component class="baz boo"></my-component>
HTML 将被渲染为:
<p class="foo bar baz boo">Hi</p>
对于带数据绑定 class 也同样适用:
<my-component v-bind:class="{ active: isActive }"></my-component>
当 isActive 为 true时,HTML 将被渲染成为:
<p class="foo bar active">Hi</p>
给第六章的综合案例,使用本章的知识添加样式。
*请认真填写需求信息,我们会在24小时内与您取得联系。