JS 获取URL中的参数
使用URLSearchParams方法
此方法使用 URLSearchParams 类来解析 search 中的参数,然后使用 get 方法获取对应的参数
const urlParams = new URLSearchParams(window.location.search);
const showFrom = urlParams.get('show_from');
const time = urlParams.get('time');
console.log(' == show_from == ', showFrom);
console.log(' == time == ', time); // null
直接解析 window.location.search
const search = window.location.search;
if (search !== '') {
const obj = search.split('?')[1].split('&')
let obj1 = []
obj.forEach(key => {
const [key1, value] = key.split('=')
obj1[key1] = value
});
console.error(' -- show_from -- ', obj1.show_from);
console.error(' -- time -- ', obj1.time); // undefined
}
JS 中对象深拷贝的方式
JSON.parse(JSON.stringify(obj))
这种方式通过将对象转换为 JSON 字符串,然后再将 JSON 字符串转换回对象,实现深拷贝
function deepCopy(value) {
if (typeof value !== object || value === null) return value
return JSON.parse(JSON.stringify(value))
}
Object.assign()
这种方式通过将原对象的属性复制到一个新对象中,实现深拷贝 但是,如果原对象中有嵌套对象,不适用。需要递归调用,否则嵌套的对象会变成浅拷贝
function deepCopy(obj) {
return Object.assign({}, obj)
}
const obj = { a: 1, b: { c: 2 } }
let newObj = deepCopy1(obj)
console.log(' == obj == ', obj); // { a: 1, b: { c: 2 } }
console.log(' == newObj == ', newObj); // { a: 1, b: { c: 2 } }
obj.a = 3
console.log(' == obj == ', obj); // { a: 3, b: { c: 2 } }
console.log(' == newObj == ', newObj); // { a: 1, b: { c: 2 } }
obj.b.c = 4
console.log(' == obj == ', obj); // { a: 3, b: { c: 4 } }
console.log(' == newObj == ', newObj); // { a: 1, b: { c: 4 } }
递归函数
通过递归函数来实现深拷贝,可以处理任意深度的嵌套对象
function deepCopy(value) {
if (typeof value !== object || value === null) return value
const result = Array.isArray(value) ? [] : {}
for (key in value) {
result[key] = deepCopy(value[key])
}
}
Lodash 的 cloneDeep()
Lodash 是一个流行的 JavaScript 库,它提供了一个名为 cloneDeep() 的函数,可以实现深拷贝
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
const _ = window._;
const obj = { a: 1, b: { c: 2 } }
const newObj = _.cloneDeep(obj)
定时更新日期
需求描述
若页面展示一个页面更新日期为:2024.09.05,为了避免在之后需要更新这个日期时进行项目的发版,或者项目中很多页面都展示了这个日期。弄一个定时更新日期的函数去更新这个页面的时间
实现思路
-
周三早上八点之后访问,则更新成当前的日期(也就是本周三日期)
-
其他时间访问,更新成周三的日期
2.1. 比如周一、二访问,日期更新成上周周三的
2.2. 周四、五访问,日期是本周周三的
-
一周更新一次时间(周三八点之后访问时更新)
编码实现
function updateDate() {
const date = new Date(); // Thu Sep 05 2024 20:43:21 GMT+0800 (中国标准时间)
const dayOfWeek = date.getDay(); // 获取日期(是周几)
const hour = date.getHours(); // 获取当前小时
const isWednesday = dayOfWeek == 3 && hour >= 8; // 是否周三早上八点后访问
const wednesdayDate = isWednesday ? date : getPreviousWednesday(date);
const year = wednesdayDate.getFullYear();
const month = String(wednesdayDate.getMonth() + 1).padStart(2, '0');
const day = String(wednesdayDate.getDate()).padStart(2, '0');
$('.update-date').text(year + '.' + month + '.' + day);
}
function getPreviousWednesday(date) {
const wednesdayDate = new Date(date);
/**
* wedensday.getDate():获取当前日期 - 多少号。例如:27号
* wedensday.getDay():获取当前日期 - 周几。例如 27号是周二 => 2
*/
if (wednesdayDate.getDay() < 3) {
wednesdayDate.setDate(wednesdayDate.getDate() - (wednesdayDate.getDay() + 4));
} else {
wednesdayDate.setDate(wednesdayDate.getDate() - (wednesdayDate.getDay() - 3));
}
return wednesdayDate;
}
new Date().setDate()的作用
new Date().setDate() 的作用是,设置对应日期的日期
比如如果要获取本月(写这篇文章时是24年9月)27号的日期是什么
const date = new Date();
date.setDate(27); // 1727441498872
return date; // Fri Sep 27 2024 20:51:38 GMT+0800 (中国标准时间)
localStorage设置过期时间
需求描述
localStorage 是浏览器的一种持久化存储机制。其存储的数据除非手动删除,或者浏览器的存储空间被清除,否则永远会存在。其本身不支持设置过期时间,那么如何通过编码为其设置一个过期时间,让数据到期后自动删除呢?
实现思路
-
在设置数据存储时,存储一个对象,对象属性设置一个过期时间
-
在获取数据时,先将当前时间与缓存数据的过期时间进行对比
2.1 如果当前时间大于过期时间,说明数据已过期,则删除
2.2 如果当前时间小于过期时间,说明在有效期内,则直接返回
编码实现
// 存储值的方法
const setLocalStorageWithExpires = (key, value, expiresTime) => {
const expireDate = new Date().getTime() + expiresTime * 1000;
localStorage.setItem(key, JSON.stringify({ value, expireDate }));
};
// 获取值的方法
const getLocalStorageWithExpires = (key) => {
const storedValue = localStorage.getItem(key);
if (!storedValue) {
return null;
}
const { value, expireDate } = JSON.parse(storedValue);
// 判断是否过期了
if (new Date().getTime() > expireDate) {
// 过期,则移除
localStorage.removeItem(key);
return null;
}
return value;
};
// 调用
setLocalStorageWithExpire('myKey', 'myValue', 3600); // 1小时
const value = getLocalStorageWithExpire('myKey');
if (value) {
console.log(value);
} else {
console.log('值已过期');
}
注意
这种方法虽然可以实现过期时间的功能,但是需要注意的是,localStorage 的存储空间是有限的,所以不建议存储大量数据。
另外,可以使用 sessionStorage,它本身支持会话级别的存储,并且会在会话结束时自动清除数据。
Vue 以插件的形式注册组件
在Vue中组件最常用的调用方式,是内部引用,如下形式
<template>
<div>
<CompLoading />
</div>
<template>
<script>
import CompLoading from './CompLoading.vue'
export default {
......
components {
CompLoading
}
......
}
</script>
这样做有不少劣势
- 局部注册:普通组件创建方式需要手动注册组件,意味着组件只能在注册的作用域内使用
- 管理不便:普通组件需要手动导入、注册后才能使用
- 不适合大型项目
针对上述问题,这边介绍一种vue中通过插件创建组件的方式
插件创建组件
优点
- 全局注册:通过插件创建的组件可以全局注册,意味着可以在项目中任何地方使用该组件,而不需要手动导入和注册
- 方便管理:插件方式创建的组件可以集中管理,一个插件文件可以管理多个组件
- 可扩展性强:可通过插件的选项来扩展其功能
- 自动注册:当 使用
Vue.use方法安装插件时,插件会自动调用install方法来注册组件和方法
代码示例
目录结构
- plugins
- compLoading
- CompLoading.vue
- index.js
index.js
/**
* 这里面包含两个组件
* 1. CompLoading - 全局注册的组件,提供了一个基础的模版
* 2. LocalLoading - 局部创建的组件,扩展了AppleLoading组件的功能
*/
import CompLoading from './CompLoading.vue'
export default {
vm: null,
// 安装插件到vue实例
install (Vue) {
// 全局注册CompLoading组件
Vue.component('CompLoading', CompLoading)
// 初始化一个标识,来跟踪loading组件是否显示
Vue.prototype.$loadingShow = null
// 定义一个方法(用来显示loading组件)
Vue.prototype.$compLoading = function (text, options = {}) {
// 如果loading组件没有显示,那么就显示它
if (!Vue.prototype.$loadingShow) {
// 创建一个新的Vue局部组件-LocalLoading(是CompLoading组件的一个子类或者扩展)
const loadingTpl = Vue.extend({
name: 'LocalLoading',
data () {
return {
isShow: false
}
},
render (h) {
// CompLoading组件的属性
const props = {
text,
isShow: this.isShow,
}
// 渲染CompLoading组件(使用CompLoading组件作为模版进行渲染)
return h(CompLoading, { props })
}
})
// 创建一个新的loadingTpl组件实例
const loadingVM = new loadingTpl()
// 将组件挂载到DOM
this.vm = loadingVM.$mount()
// 获取组件的DOM元素
const el = this.vm.$el
// 显示组件
this.vm.isShow = true
// 这是$loadingShow标识为true
Vue.prototype.$loadingShow = true
// 把生成的提示的dom插入body中
document.body.appendChild(el)
}
}
// 定义一个方法(用来隐藏loading组件)
Vue.prototype.$loadingHide = function () {
// 如果loading组件已经显示,那么就隐藏它
if (Vue.prototype.$loadingShow) {
// 从DOM中移除loading组件
document.body.removeChild(this.vm.$el)
// 销毁组件实例
this.vm.$destroy()
// 更新标识为null
Vue.prototype.$loadingShow = null
}
}
}
}
CompLoading.vue
<template>
<div>
<div v-if="isShow">
<p>{{ text }}</p>
</div>
</div>
</template>
<script>
export default {
name: 'CompLoading',
props: {
text: {
type: String,
default: ''
},
isShow: {
type: Boolean,
default: false
}
},
}
</script>
main.ts
import Vue from 'vue'
import compLoading from '@/plugins/compLoading/'
Vue.use(compLoading, {}) // 此时,已经调用了install方法。组件已经挂载了,但是props值都是默认的
使用场景
// vue2
this.$compLoading('加载中...')
// vue3
context.root.$compLoading('加载中...')