有多种方法可以实现子元素在父元素中垂直居中的方式,以下是其中几种常用的方法:
父元素设置为 flex 容器,并使用 align-items 属性将子元素垂直居中。
.parent {
display: flex;
align-items: center; /* 子元素垂直居中 */
}
将父元素设置为 table,子元素设置为 table-cell,并使用 vertical-align 属性将子元素垂直居中。
.parent {
display: table;
}
.child {
display: table-cell;
vertical-align: middle; /* 子元素垂直居中 */
}
使用绝对定位将子元素相对于父元素居中,结合 transform 属性进行位移变换。
.parent {
position: relative;
}
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%); /* 子元素垂直居中 */
}
父元素设置为 grid 容器,并使用 place-items 属性将子元素垂直居中。
.parent {
display: grid;
place-items: center; /* 子元素垂直居中 */
}
以上是常用的几种方法,选择适合你项目需求和浏览器兼容性的方式来实现子元素在父元素中垂直居中。
1.可以使用 Flexbox 布局。以下是一种基本的方法:
.parent {
display: flex;
justify-content: center; /* 子元素水平居中 */
align-items: center; /* 子元素垂直居中 */
}
以上代码将父元素设置为 flex 容器,使用 `justify-content` 属性将子元素水平居中,使用 `align-items` 属性将子元素垂直居中。
2.使用绝对定位和 transform:
.parent {
position: relative;
}
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%); /* 子元素水平垂直居中 */
}
3.使用表格布局:
将父元素设置为 table,子元素设置为 table-cell,并使用 vertical-align 和 text-align 属性控制对齐方式。
.parent {
display: table;
width: 100%;
height: 100%;
}
.child {
display: table-cell;
vertical-align: middle; /* 子元素垂直居中 */
text-align: center; /* 子元素水平居中 */
}
4.使用 Grid 布局:
.parent {
display: grid;
}
.child {
justify-self: center; /* 子元素水平居中 */
align-self: center; /* 子元素垂直居中 */
}
KeepAlive 组件是 Vue.js 中的一个内置组件,用于缓存和复用组件实例。它可以将动态组件进行缓存,在组件切换时保留其状态,提高应用性能。
作用:
常用的钩子函数:
控制组件级存储:
可以通过
的特殊属性 include
和 exclude
控制具体哪些组件需要被缓存,以及哪些组件不需要被缓存。
include
:指定要缓存的组件名称数组,只有包含在该数组中的组件才会被缓存。exclude
:指定不需要缓存的组件名称数组,这些组件将不会被缓存。示例如下:
<keep-alive :include="['ComponentA', 'ComponentB']" :exclude="['ComponentC']">
<router-view>router-view>
keep-alive>
以上代码中,只有名为 “ComponentA” 和 “ComponentB” 的组件会被缓存,而名为 “ComponentC” 的组件不会被缓存。其他组件则按需创建和销毁。
使用 include
和 exclude
可以灵活地控制组件级别的缓存策略,根据具体需求来决定哪些组件需要保持状态并进行复用。
判断对象是否为数组的三个常用方法如下:
Array.isArray()
方法:if (Array.isArray(obj)) {
// obj 是一个数组
}
instanceof
运算符:if (obj instanceof Array) {
// obj 是一个数组
}
Object.prototype.toString.call()
方法:if (Object.prototype.toString.call(obj) === '[object Array]') {
// obj 是一个数组
}
这些方法都可以判断给定的对象是否为数组。对于这三种方法,推荐使用 Array.isArray()
,因为它是专门用于判断对象是否为数组的方法,且在不支持ES5的环境中也能正常工作。
var myObj1 = {
name: '小王',
myAge: this.age,
sayName: function(add, front) {
console.log(this.name + '今年' + this.age + '在' + add + '做' + front);
}
};
var heros = {
name: '小张',
age: '20'
};
myObj1.sayName.call(heros, '上海', '前端');
myObj1.sayName.apply(heros,['上海','前端']);
myObj1.sayName.bind(heros)('上海','前端');
myObj1.sayName.bind(heros,'上海','前端')();
myObj1.sayName.bind(heros,['上海','前端'])()
小张今年20在上海做前端
小张今年20在上海做前端
小张今年20在上海做前端
小张今年20在上海做前端
小张今年20在上海,前端做undefined
考察的
下面是对每个调用方法的说明:
1、 `myObj1.sayName.call(heros, '上海', '前端')`:使用 `call` 方法调用 `sayName` 方法,并将 `heros` 对象作为方法的上下文(`this`)绑定,同时传递 `'上海'` 和 `'前端'` 作为参数。 立即执行
2 `myObj1.sayName.apply(heros, ['上海', '前端'])`:使用 `apply` 方法调用 `sayName` 方法,并将 `heros` 对象作为方法的上下文(`this`)绑定,同时以** 数组 **形式传递 `['上海', '前端']` 作为参数。 立即执行
3、myObj1.sayName.bind(heros)('上海','前端'); 将 heros 作为参数 传入 bind 方法,然后在后面的调用中又依次传入 上海、前端
4、、 `myObj1.sayName.bind(heros, '上海', '前端')()`:使用 `bind` 方法创建一个新的函数,并将 `heros` 对象作为方法的上下文(`this`)绑定,同时传递 `'上海'` 和 `'前端'` 作为参数。然后立即调用新创建的函数。
5、myObj1.sayName.bind(heros,['上海','前端'])() 将heros 作为改变this 指向的值传入,再把 ['上海','前端'] 这个数组作为第一个替换值传入, 所以 add =‘上海,前端’ ,front =undefined
知识点:
在 JavaScript 中,`call`、`apply` 和 `bind` 都是用于改变函数的执行上下文(即函数内部的 `this` 指向)的方法。它们的主要区别在于参数的传递方式和是否立即执行函数。
1. `call` 方法:
- 语法:`function.call(thisArg, arg1, arg2, ...)`。
- 作用:`call` 方法调用一个函数,并将指定的对象作为函数的执行上下文(`this`)。可以通过 `call` 方法实现继承、借用其他对象的方法或更改函数内部的上下文。
- 参数:
- `thisArg`:被绑定到函数的执行上下文(`this`)的对象。
- `arg1`, `arg2`, ...:函数调用时所需的参数列表。
- 返回值:函数的返回结果。
2. `apply` 方法:
- 语法:`function.apply(thisArg, [argsArray])`。
- 作用:`apply` 方法调用一个函数,并将指定的对象作为函数的执行上下文(`this`)。与 `call` 方法类似,不同之处在于参数的传递方式,`apply` 使用 ·数组·来传递参数。
- 参数:
- `thisArg`:被绑定到函数的执行上下文(`this`)的对象。
- `[argsArray]`:一个包含函数调用时所需参数的数组。
- 返回值:函数的返回结果。
3. `bind` 方法:
- 语法:`function.bind(thisArg, arg1, arg2, ...)`。
- 作用:`bind` 方法.创建. 一个新的函数,该函数和原来的函数具有相同的函数体,但执行上下文(`this`)永久地被绑定到 `bind` 方法的第一个参数指定的对象。
- 参数:
- `thisArg`:被绑定到新函数的执行上下文(`this`)的对象。
- `arg1`, `arg2`, ...:在调用新函数时要传递给原函数的固定参数。
- 返回值:返回一个绑定了执行上下文和固定参数的新函数,并不会立即执行。
在给定的代码示例中,我们使用了 `call`、`apply` 和 `bind` 来改变 `myObj1.sayName` 函数的执行上下文,并传递了额外的参数。
- `myObj1.sayName.call(heros, '上海', '前端')`:调用 `sayName` 函数,使其以 `heros` 对象作为执行上下文(`this`),并传递 `'上海'` 和 `'前端'` 作为参数。结果会打印出类似于 "小张今年20在上海做前端" 的内容。
- `myObj1.sayName.apply(heros, ['上海', '前端'])`:类似于 `call` 方法,但是参数通过数组进行传递。
- `myObj1.sayName.bind(heros, '上海', '前端')()`:创建一个新的函数,并将 `heros` 对象作为执行上下文(`this`),同时传递 `'上海'` 和 `'前端'` 作为参数。由于使用了括号 `()`,新函数会立即执行,并打印出相应的内容。
需要注意的是,在使用 `call`、`apply` 和 `bind` 时,要确保参数和参数列表的正确配对,并根据具体需求选择合适的方法来改变函数的执行上下文。
在 JavaScript 中,你可以使用过滤器(Filter)来对数据进行格式化和处理。过滤器通常用于将原始数据转化为需要的形式,比如在显示数据时对数字进行格式化。
下面是一个示例代码,实现了一个保留两位小数的数字过滤器:
// 定义数字保留两位小数的过滤器
function twoDecimalFilter(value) {
if (typeof value !== 'number') return value; // 非数字类型直接返回
return value.toFixed(2); // 使用toFixed方法保留两位小数
}
// 示例使用
let number1 = 12.3456;
let number2 = 3.7;
let string = 'abc';
console.log(twoDecimalFilter(number1)); // 输出 "12.35"
console.log(twoDecimalFilter(number2)); // 输出 "3.70"
console.log(twoDecimalFilter(string)); // 输出 "abc"
上述代码中,twoDecimalFilter
是一个自定义的过滤器函数。它接受一个参数 value
,判断该值是否为数字类型,如果是,则使用 toFixed
方法将其保留两位小数并返回;如果不是数字,则直接返回原值。
在使用过滤器时,只需调用过滤器函数并传入要格式化的数据即可。在上面的示例中,我们分别对 number1
、number2
和 string
进行过滤,并输出结果。
请注意,在实际开发中,可能会使用框架或库来提供更便捷和灵活的过滤器机制,比如在 Vue.js 中使用过滤器。以上示例仅演示了一个简单的自定义过滤器的实现方式。
使用 Vue 的过滤器可以更方便地对数据进行格式化和处理。下面是一个使用 Vue 过滤器的示例,实现保留两位小数的数字过滤器:
html复制代码
{{ number1 | twoDecimal }}
{{ number2 | twoDecimal }}
{{ string | twoDecimal }}
在上述代码中,我们创建了一个 Vue 实例,并在该实例中定义了一个过滤器 twoDecimal
。在模板中,通过使用管道操作符 |
将要过滤的数据与过滤器名称相连,在输出时会自动应用过滤器。
在这个示例中,number1
、number2
和 string
是 Vue 实例的数据属性,分别代表要过滤的数字和字符串。通过 {{ number | twoDecimal }}
的形式,将数值绑定到对应的模板插值处,同时应用名为 twoDecimal
的过滤器,从而实现保留两位小数的效果。
运行以上代码,你将看到页面上输出的数值已按照过滤器的设定进行了格式化。
在 Vue 中,自定义指令(Custom Directive)是一种扩展 Vue 的能力,用于对 DOM 元素进行低层次的操作和交互。通过自定义指令,我们可以直接操作 DOM、添加事件监听器、进行样式操作等。
要注册一个全局的自定义指令,你可以使用 Vue.directive
方法。下面是一个示例代码,演示如何注册一个名为 my-directive
的全局自定义指令:
<div id="app">
<input v-my-directive />
div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]">script>
<script>
// 注册全局自定义指令
Vue.directive('my-directive', {
bind: function(el, binding, vnode) {
// 指令绑定时的处理逻辑
el.style.backgroundColor = 'yellow';
el.addEventListener('focus', function() {
el.style.color = 'red';
});
},
inserted: function(el, binding, vnode) {
// 指令插入到 DOM 中的处理逻辑
},
update: function(el, binding, vnode, oldVnode) {
// 组件更新时的处理逻辑
},
unbind: function(el, binding, vnode) {
// 指令解绑时的处理逻辑
el.removeEventListener('focus');
}
});
// 创建 Vue 实例
new Vue({
el: '#app',
});
script>
在上述代码中,我们使用 Vue.directive
方法注册了一个名为 my-directive
的全局自定义指令。该指令包含了几个生命周期钩子函数,例如 bind
、inserted
、update
和 unbind
,你可以根据需要实现相应的逻辑。
在示例代码中,bind
钩子函数用来在指令绑定时设置元素的背景颜色为黄色,并添加一个焦点事件监听器,当聚焦到输入框时,将文字颜色设置为红色。
在 Vue 实例的模板中,我们通过 v-my-directive
指令将这个自定义指令应用到了一个 元素上。当 Vue 渲染该模板时,
my-directive
指令就会被触发,执行对应的逻辑。
请注意,以上示例代码是注册一个全局自定义指令的基本用法,你可以根据实际需求进行扩展和修改。
const arr1 =[
{
id:1,
name:'name1
},{
id:2
name:'name2
}
]
const arr2 =[...arr1] // 复制数组,浅拷贝
arr1[0].name='namel-undate' // 会改变复制后的数组
console.log(arr2[0].name) //
const obj ={
a:'aa'
b:bb'
}
const obj2 = {...obj} // 复制对象形成新对象
obj.a='aa-update' // 不会影响新对象
console.log(obj.a)
console.log(obj2.a)
对于更新后的代码如下:
const arr1 = [{
id: 1,
name: 'name1'
}, {
id: 2,
name: 'name2'
}];
const arr2 = [...arr1];
arr1[0].name = 'namel-update';
console.log(arr2[0].name);
与之前相同,arr1
是一个包含两个对象元素的数组。通过扩展运算符[...arr1]
将arr1
数组的元素复制给了新数组arr2
。同样地,这仍然是浅拷贝,意味着修改arr1
中的第一个对象的name
属性会影响到arr2
中的对应元素。因此,console.log(arr2[0].name)
将输出namel-update
。
const obj = {
a: 'aa',
b: 'bb'
};
const obj2 = {...obj};
obj.a = 'aa-update';
console.log(obj.a);
console.log(obj2.a);
在这段代码中,我们使用了对象展开语法{...obj}
来将obj
对象进行复制。这种方式会创建一个新的对象,并将原始对象中的属性复制到新的对象中。因此,obj2
是一个独立的对象,其属性与原始对象obj
相同但值不共享。
由于我们将obj
对象的a
属性值修改为'aa-update'
,所以console.log(obj.a)
将输出'aa-update'
。而console.log(obj2.a)
将输出原始的属性值'aa'
,因为obj2
是在修改之前复制的对象。
综上所述,使用对象展开语法{...obj}
可以实现对象的浅拷贝,并且复制后的对象与原始对象的属性值不共享。
浅拷贝和深拷贝是两种常用的对象或数组复制方法,它们在复制过程中处理引用类型数据的方式不同。
[...arr]
或{...obj}
、Object.assign()
等。在选择使用浅拷贝还是深拷贝时,需要根据具体需求和数据结构来决定。如果对象/数组的属性值不包含引用类型数据、或者对共享值的修改无影响,那么可以使用浅拷贝;如果需要完全独立且不受影响地操作复制后的对象/数组,那么应该使用深拷贝。