vue3实战六、外链跳转404,401等 入口

外链跳转、404、401页面

外链跳转

外链跳转完整代码:其中validate.js代码放入到最后

go 复制代码
<template>
  <div class="link-container layout-padding flex-column-center">
    <img class="link-img" src="@/assets/link.svg" />
    <div class="link-wrap">
      <h3>即将跳转到外部网站[{{ state.title }}]</h3>
      <div>您将要访问的链接不属于 {{ hostname }},请关注您的帐号安全!</div>
      <div>{{ state.link }}</div>
      <el-button @click="handleOpenPage" round class="link-btn">继续前往访问</el-button>
    </div>
  </div>
</template>

<script setup lang="ts" name="wuyouke">
import { useRoute } from "vue-router";
import { watch, reactive } from "vue";
import { validateURL } from "../../utils/validate";

const route = useRoute();

interface State {
  title: string;
  link: string;
}

const state = reactive<State>({
  title: "", // 链接标题
  link: "", // 目标跳转url
});

const hostname = window.location.hostname;
watch(
  () => route.path,
  () => {
    state.title = (route.meta?.title as string) || "外链";
    state.link = (route.meta?.linkTo as string) || "";
  }
);
// 继续前往访问
function handleOpenPage() {
  const { origin } = window.location;
  if (validateURL(state.link)){
    window.open(state.link);
  }else{
    window.open(`${origin}${state.link}`);
  }
}
</script>

<style scoped lang="scss">
.link-container {
  .link-img {
    width: 200px;
  }
  .link-wrap {
    width: 500px;
    border: 1px solid var(--wyk-border-color-light);
    border-radius: 10px;
    padding: 20px;
    line-height: 30px;
    font-size: 15px;
    margin-top: 20px;
    .link-btn {
      float: right;
    }
  }
}
</style>

401页面

401页面完整代码:

go 复制代码
<script setup lang='ts'>
import { useRouter } from "vue-router";
const router = useRouter();
</script>
<template>
  <div class="error-container layout-padding flex-center">
    <img class="error-img" src="@/assets/401.svg" />
    <div class="error-wrap">
      <div class="error-title">您没有操作权限,请联系管理员!</div>
      <div class="error-msg">联系方式:https://www.baidu.com</div>
      <el-button @click="router.push('/login')" round type="primary"
        >重新登录</el-button
      >
    </div>
  </div>
</template>
<style scoped lang="scss">
.error-container {
  .error-img {
    width: 350px;
    margin-bottom: 20px;
  }
  .error-wrap {
    margin-left: 50px;
    .error-title {
      font-size: 22px;
      font-weight: 600;
    }
    .error-msg {
      font-size: 13px;
      margin: 10px 0 30px 0;
      color: var(--el-color-info);
    }
  }
}
</style>

404页面

404页面完整代码:

go 复制代码
<script setup lang='ts'>
import { useRouter } from "vue-router";
const router = useRouter();
</script>
<template>
  <div class="error-container layout-padding flex-center">
    <img class="error-img" src="@/assets/404.svg" />
    <div class="error-wrap">
      <div class="error-title">您所访问的页面不存在!</div>
      <div class="error-msg">
        请检查您输入的网址是否正确,或点击下面的按钮返回首页。
      </div>
      <el-button @click="router.push('/')" round type="primary"
        >返回首页</el-button
      >
    </div>
  </div>
</template>
<style scoped lang="scss">
.error-container {
  flex-direction: row !important;
  .error-img {
    width: 350px;
    margin-bottom: 20px;
  }
  .error-wrap {
    margin-left: 50px;
    .error-title {
      font-size: 22px;
      font-weight: 600;
    }
    .error-msg {
      font-size: 13px;
      margin: 10px 0 30px 0;
      color: var(--el-color-info);
    }
  }
}
</style>

validate.js代码:[常用方法封装]

javascript 复制代码
/**
 * 判断对象属性不为空
 *   object           = null  false
 *   object[property] = null  false
 *   object[property] = ""    false
 * @param object   对象
 * @param property 属性
 * @return boolean
 */
export function isNotEmpty (object:any, property:string) {
  return object != null && object.hasOwnProperty(property) && object[property] != null && object[property] !== "";
}

// 校验用户名是否合法 只允许6-30位数字、字母和下划线,或子帐号:  (中文\u4e00-\u9fa5)
export function isUsername(str:string) {
  const valid_map = /^[a-zA-Z0-9_:]{6,30}$/
  return valid_map.test(str)
}
/**
 * 校验主帐号是否合法
 * @param str 
 * @returns true 合法,false不合法
 */
export function isMainAccount(str:string) {
  const valid_map = /^[a-zA-Z0-9_]{6,30}$/
  return valid_map.test(str)
}

// 校验手机号是否合法
export function isMobile(str:string) {
  const valid_map = 11 && /^1(3|4|5|7|8|9)\d{9}$/
  return valid_map.test(str)
}
  
// 校验邮箱是否合法
export function isEmail(str:string) {
  const valid_map = /^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/
  return valid_map.test(str)
}


// 验证码必须为4~6位数字、字母
export function isCheckCode(str:string) {
  const valid_map = /^[0-9a-zA-Z]{4,6}$/
  return valid_map.test(str)
}

/**
 * 密码 (长度在6~30之间,只能包含字母、数字和特殊字符)
 * @param str 当前值字符串
 * @returns 返回 true: 密码正确
 */
export function isPassword(str:string) {
  const valid_map = /^[0-9a-zA-Z_!@#$%^&\.*]{6,30}$/
  return valid_map.test(str)
}

/**
 * 强密码 (字母+数字+特殊字符,长度在6-30之间)
 * @param str 当前值字符串
 * @returns 返回 true: 强密码正确
 */
 export function isPasswordPowerful(str: string) {
  const valid_map = /^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&\.*]+$)(?![a-zA-z\d]+$)(?![a-zA-z!@#$%^&\.*]+$)(?![\d!@#$%^&\.*]+$)[a-zA-Z\d!@#$%^&\.*]{6,30}$/
	return valid_map.test(str)
}

/**
 * 密码强度
 * @param str 当前值字符串
 * @description 弱:纯数字,纯字母,纯特殊字符
 * @description 中:字母+数字,字母+特殊字符,数字+特殊字符
 * @description 强:字母+数字+特殊字符
 * @returns 返回处理后的字符串:弱、中、强
 */
export function isPasswordStrength(str: string) {
	let v = '弱';
	// 弱:纯数字,纯字母,纯特殊字符
	if (/^(?:\d+|[a-zA-Z]+|[!@#$%^&\.*]+){6,30}$/.test(str)) v = '弱';
	// 中:字母+数字,字母+特殊字符,数字+特殊字符
	else if (/^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&\.*]+$)[a-zA-Z\d!@#$%^&\.*]{6,30}$/.test(str)) v = '中';
	// 强:字母+数字+特殊字符
	else if (/^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&\.*]+$)(?![a-zA-z\d]+$)(?![a-zA-z!@#$%^&\.*]+$)(?![\d!@#$%^&\.*]+$)[a-zA-Z\d!@#$%^&\.*]{6,30}$/.test(str))
		v = '强';
	// 返回结果
	return v;
}

// 只允许输入3~30位数字、字母和下划线
export function isCode(str:string) {
  const valid_map = /^[a-zA-Z0-9]{3,30}$/
  return valid_map.test(str)
}

/* 合法uri*/
export function validateURL(textval:string) {
  const urlregex = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
  return urlregex.test(textval)
}

/**
 * @param {string} path
 * @returns {Boolean}
 */
export function isExternal(path:string) {
  return /^(https?:|mailto:|tel:)/.test(path)
}
/**
 * 校验两个对象是否相等(不支持嵌套对象比较)
 * @param obj1 对象1
 * @param obj2 对象2
 * @returns true 相等
 */
export function equals(obj1:any, obj2:any) {
  const _obj1 = JSON.stringify(obj1);
  const _obj2 = JSON.stringify({...obj1, ...obj2});
  return _obj1 === _obj2
}


/**
 * 判断两数组是否相同
 * @param news 新数据
 * @param old 源数据
 * @returns 两数组相同返回 `true`,反之则反
 */
 export function equalsArr(news: unknown[] | string[], old: string[]): boolean {
	let count = 0;
	const leng = old.length;
	for (let i in old) {
		for (let j in news) {
			if (old[i] === news[j]) count++;
		}
	}
	return count === leng ? true : false;
}

/**
 * 判断一个数组(父数组)是否包含另一个数组(子数组)
 *	let parent=[1,2,3,6,5,4]
 *	let child=[1,3,4,6]
 *	let child2=[1,3,4,6,7]
 *	console.log(isContainArr(parent, child))//true
 *	console.log(isContainArr(parent, child2))//false
 * @param parent 父数组
 * @param child 子数组
 * @returns true 包含,false不包含
 */
export function isContainArr(parent: unknown[], child: unknown[]): boolean {
  return child.every(item => {
    return parent.some(v => {
      return item === v
    })
  })
}


/**
 * 验证百分比(不可以小数)
 * @param val 当前值字符串
 * @returns 返回处理后的字符串
 */
 export function verifyNumberPercentage(val: string): string {
	// 匹配空格
	let v = val.replace(/(^\s*)|(\s*$)/g, '');
	// 只能是数字和小数点,不能是其他输入
	v = v.replace(/[^\d]/g, '');
	// 不能以0开始
	v = v.replace(/^0/g, '');
	// 数字超过100,赋值成最大值100
	v = v.replace(/^[1-9]\d\d{1,3}$/, '100');
	// 返回结果
	return v;
}

/**
 * 验证百分比(可以小数)
 * @param val 当前值字符串
 * @returns 返回处理后的字符串
 */
export function verifyNumberPercentageFloat(val: string|number): string {
	let v = verifyNumberIntegerAndFloat(val);
	// 数字超过100,赋值成最大值100
	v = v.replace(/^[1-9]\d\d{1,3}$/, '100');
	// 超过100之后不给再输入值
	v = v.replace(/^100\.$/, '100');
	// 返回结果
	return v;
}

/**
 * 小数或整数(不可以负数)
 * @param val 当前值字符串
 * @returns 返回处理后的字符串
 */
export function verifyNumberIntegerAndFloat(val: string|number) {
	val = String(val);
	// 匹配空格
	let v = val.replace(/(^\s*)|(\s*$)/g, '');
	// 只能是数字和小数点,不能是其他输入
	v = v.replace(/[^\d.]/g, '');
	// 以0开始只能输入一个
	v = v.replace(/^0{2}$/g, '0');
	// 保证第一位只能是数字,不能是点
	v = v.replace(/^\./g, '');
	// 小数只能出现1位
	v = v.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.');
	// 小数点后面保留2位
	v = v.replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3');
	// 返回结果
	return v;
}


/**
 * 小数或整数(可以为负数)
 * @param val 当前值字符串
 * @returns 返回处理后的字符串
 */
export function verifyNumberFloat(val: string|number) {
	val = String(val);
	// 匹配空格
	let v = val.replace(/(^\s*)|(\s*$)/g, '');
	// 只能是数字和小数点,不能是其他输入
	v = v.replace(/[^(\-)*\d.]/g, '');
	// 以0开始只能输入一个
	v = v.replace(/^0{2}$/g, '0');
	// 保证第一位只能是数字,不能是点
	v = v.replace(/^\./g, '');
	// 小数只能出现1位
	v = v.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.');
	// 小数点后面保留2位
	v = v.replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3');
	// 返回结果
	return v;
}

/**
 * 正整数验证
 * @param val 当前值字符串
 * @returns 返回处理后的字符串
 */
export function verifiyNumberInteger(val: string) {
	// 匹配空格
	let v = val.replace(/(^\s*)|(\s*$)/g, '');
	// 去掉 '.' , 防止贴贴的时候出现问题 如 0.1.12.12
	v = v.replace(/[\.]*/g, '');
	// 去掉以 0 开始后面的数, 防止贴贴的时候出现问题 如 00121323
	v = v.replace(/(^0[\d]*)$/g, '0');
	// 首位是0,只能出现一次
	v = v.replace(/^0\d$/g, '0');
	// 只匹配数字
	v = v.replace(/[^\d]/g, '');
	// 返回结果
	return v;
}

/**
 * 去掉中文及空格
 * @param val 当前值字符串
 * @returns 返回处理后的字符串
 */
export function verifyCnAndSpace(val: string) {
	// 匹配中文与空格
	let v = val.replace(/[\u4e00-\u9fa5\s]+/g, '');
	// 匹配空格
	v = v.replace(/(^\s*)|(\s*$)/g, '');
	// 返回结果
	return v;
}

/**
 * 去掉英文及空格
 * @param val 当前值字符串
 * @returns 返回处理后的字符串
 */
export function verifyEnAndSpace(val: string) {
	// 匹配英文与空格
	let v = val.replace(/[a-zA-Z]+/g, '');
	// 匹配空格
	v = v.replace(/(^\s*)|(\s*$)/g, '');
	// 返回结果
	return v;
}

/**
 * 禁止输入空格
 * @param val 当前值字符串
 * @returns 返回处理后的字符串
 */
export function verifyAndSpace(val: string) {
	// 匹配空格
	let v = val.replace(/(^\s*)|(\s*$)/g, '');
	// 返回结果
	return v;
}

/**
 * 金额用 `,` 区分开
 * @param val 当前值字符串
 * @returns 返回处理后的字符串
 */
export function verifyNumberComma(val: string) {
	// 调用小数或整数(不可以负数)方法
	let v: any = verifyNumberIntegerAndFloat(val);
	// 字符串转成数组
	v = v.toString().split('.');
	// \B 匹配非单词边界,两边都是单词字符或者两边都是非单词字符
	v[0] = v[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
	// 数组转字符串
	v = v.join('.');
	// 返回结果
	return v;
}

/**
 * 匹配文字变色(搜索时)
 * @param val 当前值字符串
 * @param text 要处理的字符串值
 * @param color 搜索到时字体高亮颜色
 * @returns 返回处理后的字符串
 */
export function verifyTextColor(val: string, text = '', color = 'red') {
	// 返回内容,添加颜色
	let v = text.replace(new RegExp(val, 'gi'), `<span style='color: ${color}'>${val}</span>`);
	// 返回结果
	return v;
}

/**
 * 数字转中文大写
 * @param val 当前值字符串
 * @param unit 默认:仟佰拾亿仟佰拾万仟佰拾元角分
 * @returns 返回处理后的字符串
 */
export function verifyNumberCnUppercase(val: any, unit = '仟佰拾亿仟佰拾万仟佰拾元角分', v = '') {
	// 当前内容字符串添加 2个0,为什么??
	val += '00';
	// 返回某个指定的字符串值在字符串中首次出现的位置,没有出现,则该方法返回 -1
	let lookup = val.indexOf('.');
	// substring:不包含结束下标内容,substr:包含结束下标内容
	if (lookup >= 0) val = val.substring(0, lookup) + val.substr(lookup + 1, 2);
	// 根据内容 val 的长度,截取返回对应大写
	unit = unit.substr(unit.length - val.length);
	// 循环截取拼接大写
	for (let i = 0; i < val.length; i++) {
		v += '零壹贰叁肆伍陆柒捌玖'.substr(val.substr(i, 1), 1) + unit.substr(i, 1);
	}
	// 正则处理
	v = v
		.replace(/零角零分$/, '整')
		.replace(/零[仟佰拾]/g, '零')
		.replace(/零{2,}/g, '零')
		.replace(/零([亿|万])/g, '$1')
		.replace(/零+元/, '元')
		.replace(/亿零{0,3}万/, '亿')
		.replace(/^元/, '零元');
	// 返回结果
	return v;
}

/**
 * 手机号码
 * @param val 当前值字符串
 * @returns 返回 true: 手机号码正确
 */
export function verifyPhone(val: string) {
	// false: 手机号码不正确
	if (!/^((12[0-9])|(13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\d{8}$/.test(val)) return false;
	// true: 手机号码正确
	else return true;
}

/**
 * 国内电话号码
 * @param val 当前值字符串
 * @returns 返回 true: 国内电话号码正确
 */
export function verifyTelPhone(val: string) {
	// false: 国内电话号码不正确
	if (!/\d{3}-\d{8}|\d{4}-\d{7}/.test(val)) return false;
	// true: 国内电话号码正确
	else return true;
}

/**
 * 登录账号 (字母开头,允许5-16字节,允许字母数字下划线)
 * @param val 当前值字符串
 * @returns 返回 true: 登录账号正确
 */
export function verifyAccount(val: string) {
	// false: 登录账号不正确
	if (!/^[a-zA-Z][a-zA-Z0-9_]{4,15}$/.test(val)) return false;
	// true: 登录账号正确
	else return true;
}

/**
 * 密码 (以字母开头,长度在6~16之间,只能包含字母、数字和下划线)
 * @param val 当前值字符串
 * @returns 返回 true: 密码正确
 */
export function verifyPassword(val: string) {
	// false: 密码不正确
	if (!/^[a-zA-Z]\w{5,15}$/.test(val)) return false;
	// true: 密码正确
	else return true;
}

/**
 * 强密码 (字母+数字+特殊字符,长度在6-16之间)
 * @param val 当前值字符串
 * @returns 返回 true: 强密码正确
 */
export function verifyPasswordPowerful(val: string) {
	// false: 强密码不正确
	if (!/^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&\.*]+$)(?![a-zA-z\d]+$)(?![a-zA-z!@#$%^&\.*]+$)(?![\d!@#$%^&\.*]+$)[a-zA-Z\d!@#$%^&\.*]{6,16}$/.test(val))
		return false;
	// true: 强密码正确
	else return true;
}

/**
 * 密码强度
 * @param val 当前值字符串
 * @description 弱:纯数字,纯字母,纯特殊字符
 * @description 中:字母+数字,字母+特殊字符,数字+特殊字符
 * @description 强:字母+数字+特殊字符
 * @returns 返回处理后的字符串:弱、中、强
 */
export function verifyPasswordStrength(val: string) {
	let v = '';
	// 弱:纯数字,纯字母,纯特殊字符
	if (/^(?:\d+|[a-zA-Z]+|[!@#$%^&\.*]+){6,16}$/.test(val)) v = '弱';
	// 中:字母+数字,字母+特殊字符,数字+特殊字符
	if (/^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&\.*]+$)[a-zA-Z\d!@#$%^&\.*]{6,16}$/.test(val)) v = '中';
	// 强:字母+数字+特殊字符
	if (/^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&\.*]+$)(?![a-zA-z\d]+$)(?![a-zA-z!@#$%^&\.*]+$)(?![\d!@#$%^&\.*]+$)[a-zA-Z\d!@#$%^&\.*]{6,16}$/.test(val))
		v = '强';
	// 返回结果
	return v;
}

/**
 * IP地址
 * @param val 当前值字符串
 * @returns 返回 true: IP地址正确
 */
export function verifyIPAddress(val: string) {
	// false: IP地址不正确
	if (
		!/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/.test(
			val
		)
	)
		return false;
	// true: IP地址正确
	else return true;
}

/**
 * 邮箱
 * @param val 当前值字符串
 * @returns 返回 true: 邮箱正确
 */
export function verifyEmail(val: string) {
	// false: 邮箱不正确
	if (
		!/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(
			val
		)
	)
		return false;
	// true: 邮箱正确
	else return true;
}

/**
 * 身份证
 * @param val 当前值字符串
 * @returns 返回 true: 身份证正确
 */
export function verifyIdCard(val: string) {
	// false: 身份证不正确
	if (!/^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/.test(val)) return false;
	// true: 身份证正确
	else return true;
}

/**
 * 姓名
 * @param val 当前值字符串
 * @returns 返回 true: 姓名正确
 */
export function verifyFullName(val: string) {
	// false: 姓名不正确
	if (!/^[\u4e00-\u9fa5]{1,6}(·[\u4e00-\u9fa5]{1,6}){0,2}$/.test(val)) return false;
	// true: 姓名正确
	else return true;
}

/**
 * 邮政编码
 * @param val 当前值字符串
 * @returns 返回 true: 邮政编码正确
 */
export function verifyPostalCode(val: string) {
	// false: 邮政编码不正确
	if (!/^[1-9][0-9]{5}$/.test(val)) return false;
	// true: 邮政编码正确
	else return true;
}

/**
 * url 处理
 * @param val 当前值字符串
 * @returns 返回 true: url 正确
 */
export function verifyUrl(val: string) {
	// false: url不正确
	if (
		!/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(
			val
		)
	)
		return false;
	// true: url正确
	else return true;
}

/**
 * 车牌号
 * @param val 当前值字符串
 * @returns 返回 true:车牌号正确
 */
export function verifyCarNum(val: string) {
	// false: 车牌号不正确
	if (
		!/^(([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z](([0-9]{5}[DF])|([DF]([A-HJ-NP-Z0-9])[0-9]{4})))|([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳使领]))$/.test(
			val
		)
	)
		return false;
	// true:车牌号正确
	else return true;
}

完结~

相关推荐
天官赐福_9 分钟前
vue2的scale方式适配大屏
前端·vue.js
江城开朗的豌豆9 分钟前
CSS篇:前端经典布局方案:左侧固定右侧自适应的6种实现方式
前端·css·面试
我儿长柏必定高中11 分钟前
Promise及使用场景
前端
无名友11 分钟前
HTML — 浮动
前端·css·html
0xJohnsoy12 分钟前
React中的this详解
前端
the_one12 分钟前
🚀「v-slide-in」+ 瀑布流实战指南:Vue 高级滑入动画一键实现,页面质感瞬间拉满!
前端·javascript·css
ZL不懂前端13 分钟前
微前端介绍
前端
Lear14 分钟前
uniapp&微信小程序markdown&latex
前端
江城开朗的豌豆14 分钟前
CSS篇:CSS选择器详解与权重计算全指南
前端·css·面试
asing14 分钟前
之家中后台前端解决方案 - 支点2.0
前端·javascript