文档
Echarts官网文档:Handbook - Apache ECharts
Elementui官网:elementui官网地址 (基于Vue2)
Element Plus官网:Element Plus (基于Vue3)
Vue2和Vue3的区别写法
vue
1、vue中watch的详细用法
watch的用法大致有三种,参考下方链接
2、Vue中的watch与computed
Vue中的watch与computed的区别:
Vue中的watch与computed
3、vue 路由
可能比文档还详细--VueRouter完全指北 (重点,非常详细)
vue 中 this.$router.push() 路由跳转传参 及 参数接收的方法_
常使用 编程式导航 方式进行跳转
什么是编程式导航,编程式导航就是在vue组件内部通过
this.$router
访问路由实例,并通过this.$router.push导航到不同的url,进行路由映射,前提是你已经在routes里配置了对应的路由对象
编程式导航一般都是用到router.push方法.该方法的参数可以是一个字符串路径,或者一个描述地址的对象.例如:
home已经在路由表中配置了,它是一个对象名称,对象内部有自己的指向地址
路由表的配置参考:https://www.jiangweishan.com/article/vuejs20211117a1.html
//字符串
this.$router.push('home')
//对象
this.$ruter.push({path:'home'})
//命名路由
this.$router.push({name:'user',params:{userId:2333}})
//带查询参数,变成/register?plan=private
this.$router.push({path:'register',query:{plan:'private'}})
// 或使用下面项目常用的格式
this.$router.push({
name:'user',
query:{
userId: 2333,
age: 18
}
})
通过路由传输的数据,使用$this.route或$router.currentRoute 接收,也可以使用props接收参数
console.log($this.route.query.age)
router.currentRoute 相当于 $route
使用props接收参数只需要在路由中配置props: true,参考下面链接
注意:==原谅色警告==:path
和params
是不能同时生效的!,否则params会被忽略掉.所以使用对象写法进行params传参时,要么就是path
加冒号:
,要么就是像上例中的'命名路由'.通过name和params进行传参.然而query却并不受影响,有没有path都可以进行传参.,当然也可以使用name和query的格式进行传参
同时:还可以使用props接收参数 :vue 路由传参--props - 简书
4、vue proxy代理
参考:vue:详解vue中的代理proxy (重点)
5、vue父子组件之间的传值
简单来说:components 里面的就是子组件
调用子组件常用步骤:
1:引入组件
import headTop from ‘…/…/components/headTop’
2:申明组件
components:{ headTop }
3.1:使用组件<head-top></head-top>
3.2: 或使用组件元素或属性
使用props传值 或 使用this.$refs调用属性或方法
父子组件的关系可以总结为
prop
向下传递,事件
向上传递。父组件通过prop
给子组件下发数据,子组件通过事件
给父组件发送信息。参考:vue组件中数据传递 components props_ (重点例子)
当然,也可以使用Vuex来管理数据,它相当于一个公共仓库,保存着所有组件都能共用的数据。参考:vue中使用vuex(超详细)
注意:为什么父传子值时,在组件的属性中,有的需要加冒号“:”,有的不用:
加冒号的,说明后面的是一个变量或者表达式;没加冒号的后面就是对应的字符串字面量!
为什么vue组件的属性,有的需要加冒号“:”,有的不用?_黑子Kuroko的博客-CSDN博客_vue 中的冒号
所以只有传递字符串常量时,不采用v-bind形式,其余情况均采用v-bind形式传递。为什么vue组件的属性,有的需要加冒号“:”,有的不用?_黑子Kuroko的博客-CSDN博客_vue 中的冒号
父传子:
使用 prop 传递,两个步骤:
1、定义子组件,并通过prop 声明引用数据的变量名
2、在代码中引入子组件,并通过属性绑定(v-bind:)的形式,把父组件的数据传入子组件使用,也可以不使用冒号,这时候传的就是纯粹的字符串(参考上面的注意里的链接)
- 参考:
- 关于Vue中props的详解
子传父
在子组件中,利用 $emit 触发 父组件传递过来的方法的时候,可以将子组件的数据当做参数传递给父组件
5.2、父子组件各生命周期执行顺序
先看一下父子组件的 mounted created 等一些钩子函数的先后顺序
1 父组件:beforeCreate
2 父组件:created
3 父组件:beforeMount
4 子组件:beforeCreate
5 子组件:createc
6 子组件:beforeMount
7 子组件:mounted
8 父组件:mounted
核心就是:按照钩子顺序来先赋值后传即可
更新和删除等顺序参考:Vue 子组件mounted拿到父组件mounted后的数据
6、VSCode创建Vue项目
参考:使用VSCode创建第一个VUE项目 (完整点)
零到一 vscode创建vue项目完整过程 (细节点)
7、vue关于watch和methods值执行顺序问题
(1)页面初始化时: 会执行一次computed,watch初始化时不会执行,methods只有调用的时候才会执行
(2)渲染完成后:
如果不是由点击事件造成的数据变化,执行顺序为:watch——beforeUpdate——computed——updated
如果是由点击事件造成的数据变化,执行顺序为:methods——watch——beforeUpdate——computed——update
参考:vue关于watch和methods值执行顺序问题,以及解决方案
vue执行顺序图
8、mixins可复用功能使用
混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。
什么时候使用Mixins?
当我们存在多个组件中的数据或者功能很相近时,我们就可以利用mixins将公共部分提取出来,通过 mixins封装的函数,组件调用他们是不会改变函数作用域外部的。
作用: 减少data、methods、钩子的重复
具体使用参考:
9、禁止粘贴,复制,剪切
<input name=”txtPwd” type=”password” maxlength=”20″ id=”txtPwd” class=”lg_input”
οnpaste=”return false;” οncοntextmenu=”return false;” οncοpy=”return false;” oncut=”return false;”>
οnpaste=”return false;” 禁止向控件粘贴内容
οncοpy=”return false;” 禁止复制
oncut=”return false;” 禁止剪贴
οncοntextmenu=”return false;” 禁止使用右键
10.对话点赞(和chatGPT那样的)
点赞调用接口存储信息,同时切换图片变黑。反对同理
关键代码
// html关键代码
<div class="left-header" style="float: left; margin-right: 10px; cursor: pointer">
<img id="img-like" class="like-logo" v-on:click="clickLike(item.message)" src="../../assets/images/like.png" alt="" />
</div>
<div class="right-header" style="cursor: pointer">
<img id="img-not-like" class="like-logo" v-on:click="clickNotLike(item.message)" src="../../assets/images/not-like.png" alt="" />
</div>
// js 关键代码
const clickLike = (message) => {
var like = document.getElementById("img-like").getAttribute("src");
if (like.indexOf( 'like.png' ) !== -1) {
document.getElementById("img-like").setAttribute("src", "/src/assets/images/liked.png");
document.getElementById("img-not-like").setAttribute("src", "/src/assets/images/not-like.png");
saveMessage(message, 1);
} else {
document.getElementById("img-like").setAttribute("src", "/src/assets/images/like.png");
}
}
const clickNotLike = (message) => {
var notLike = document.getElementById("img-not-like").getAttribute("src");
if (notLike.indexOf( 'not-like.png' ) !== -1) {
document.getElementById("img-not-like").setAttribute("src", "/src/assets/images/not-liked.png");
document.getElementById("img-like").setAttribute("src", "/src/assets/images/like.png");
saveMessage(message, 0);
} else {
document.getElementById("img-not-like").setAttribute("src", "/src/assets/images/not-like.png");
}
}
const saveMessage = (message, rate) => {
const params = {
context: message,
rate: rate
}
console.log(params)
// 调用接口存储点赞信息
// 代码略.......
}
11.vue中控制v-for循环出来的某一个列表项的显示隐藏切换或对其下属数据进行更详细的展示
node
1.nodejs安装
nodejs下载指定版本:Index of /dist/
nodejs安装:nodejs安装和环境配置 - 今晚打老虎! - 博客园
查看npm配置:npm config list
修改下载地址为淘宝镜像
npm config set registry https://registry.npm.taobao.org/
设置node-sass地址的变量
npm config set sass_binary_site https://npm.taobao.org/mirrors/node-sass/
2.如何安装并管理多版本node?方法介绍
先下载两个不同版本的node,通过配置环境变量(切换node时只需更改文件夹名称)
3.node node-sass sass-loader版本对应问题
一般报错:Syntax Error: Error: Node Sass version 6.0.1 is incompatible with ^4.0.0. 这种就是Node Sass版本6.0.1与^4.0.0不兼容,需要我们根据需要选择sass需要的版本
参考:node node-sass sass-loader版本对应问题,对于npm编译大家经常遇到这个问题_sass-loader 版本-CSDN博客
JS
1、JS中的let,var, const的区别
var 声明一个变量
let 声明的变量只在 let 命令所在的代码块内有效。
const 声明一个只读的常量,一旦声明,常量的值就不能改变。
const 的本质: const 定义的变量并非常量,并非不可变,它定义了一个常量引用一个值。使用 const 定义的对象或者数组,其实是可变的。
参考:JS中的let和var的区别 (重点)
2、变量提升
var scope = "全局变量";
function test()
{
document.writeln(scope + "<br >");
var scope = "局部变量";
document.writeln(scope + "<br >");
}
test();
/*第一个输出是undefined*/
该代码等价于下面的代码
var scope = "全局变量";
function test()
{
var scope;
document.writeln(scope + "<br >");
var scope = "局部变量";
document.writeln(scope + "<br >");
}
test();
参考:JavaScript总结: javascript中使用var定义变量的变量提升问题
H5
CSS
elementui知识点
ElmentUI表单验证规则
一般在<el-form>表单的 rules中添加规则,如下代码
<el-form
ref="dataForm"
:model="dataForm"
:rules="rules"
label-width="100px"
autocomplete="off"
hide-required-asterisk="true"
size="medium"
>
<el-form-item label="名称" prop="name">
<el-input v-model="dataForm.name" style="width:300px;" />
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input v-model="dataForm.password" type="password" style="width:300px;" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">添加/更新/查询</el-button>
</el-form-item>
</el-form>
<script>
...
// 定义验证规则常量, 组件中的 prop 定义使用的那个规则(如 使用 name或者其他的)
const rules = {
name: [
{ trigger: 'blur', pattern: '^(?!-)', message: '不能以中划线开头'},
{ trigger: 'blur', pattern: '.*[^-]$', message: '不能以中划线结尾'},
{ trigger: 'blur', pattern: '^([0-a9-z\u4e00-\u9fa5]+-?[0-a9-z\u4e00-\u9fa5]?)+$', message: '由小写英文字母,数字,汉字和不连续的中划线组成'},
// { trigger: 'blur', pattern: '^([\u4E00-\u9FA5A-Za-z0-9]+-?[\u4E00-\u9FA5A-Za-z0-9]?)+$', message: '由中文、英文、数字和不连续中划线组成'}
],
password: [
{ required: true, message: '密码必填~', trigger: 'blur' },
{ min: 8, max: 16, message: '密码长度在8-16字符', trigger: 'blur' }
]
}
exprot default {
data() {
return {
...,
// 在把常量放到data中,让组件使用
rules
}
},
methods:{
onSubmit() {
// 如果表单内所有都通过校验就弹框提醒
this.$refs.dataForm.validate((valid) => {
if (valid) {
alert('通过校验了~')
}
})
}
}
}
</script>
ElementUI表单的自定义校验规则
用法:在提交表单的时候,我们可以套用几成规则,如身份证:
第一层规则为身份证必须填写
第二层为验证身份证是否已经在数据库中存储了
大概就是这样的,即先触发第一个基础校验,基础校验通过后才能触发自定义的校验规则。
参考
ElementUI表单的自定义校验规则_<a href="#">leo</a>的博客-CSDN博客_elementui自定义表单验证规则
自定义element-ui表单验证的样式
参考:自定义element-ui表单验证的样式_智慧zhuhuix的博客-CSDN博客_element表单样式
element-ui 表格中带有按钮的loading详细解决方案
<el-button
:loading="scope.row.remindLoading"
icon="el-icon-message-solid"
size="mini"
type="primary"
@click="remind(scope.row)"
/>
remind(row) {
this.$set(row, 'remindLoading', true)
console.log('remind....')
setTimeout(() => {
this.$message.success('提醒成功')
this.$set(row, 'remindLoading', false)
}, 2000)
}
参考:element-ui 表格中带有按钮的loading详细解决方案_Missy Peng的博客-CSDN博客
el-select中每个option加删除按钮并且可点击
核心是在el-option元素下添加@click.stop属性;
细节
深拷贝与浅拷贝的区别
和java对象地址思想相似
常用的深拷贝:
JSON.stringify与JSON.parse 实现深拷贝
【JS】深拷贝与浅拷贝的区别,实现深拷贝的几种方法
https://www.cnblogs.com/echolun/p/7889848.html
es6之 Object.assign和 扩展运算符(...)
扩展运算符:
let bar = { a: 1, b: 2 };
let baz = { ...bar }; // { a: 1, b: 2 }
let ber = { c: 3, d: 4 };
ber = {...bar}; // {a: 1, b: 2}
Object.assign:
let bar = { a: 1, b: 2 };
let ber = { c: 3, d: 4 };
let bfr = { e: 5, f: 6 };
let baz = Object.assign({}, bar); // { a: 1, b: 2 }
let ber = Object.assign({}, bar); // { a: 1, b: 2 } 目标对象为空相当于重新赋值
let bfr = Object.assign({bfr}, bar);
/*
a: 1
b: 2
bfr: {e: 5, f: 6}
*/
- Object.assign()方法接收的第一个参数作为目标对象,后面的所有参数作为源对象。然后把所有的源对象合并到目标对象中。它会修改了一个对象,因此会触发 ES6 setter。
- 扩展操作符(…)使用它时,数组或对象中的每一个值都会被拷贝到一个新的数组或对象中。它不复制继承的属性或类的属性,但是它会复制ES6的 symbols 属性。不会触发setter
- 注意:Object.assign()是将源对象合并到目标对象哦(即目标对象的属性会增加),而扩展操作符则是完全的拷贝所有的可遍历属性(是拷贝,目标对象重新赋值)
-
如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。
同样,如果用户自定义的属性,放在扩展运算符后面,则扩展运算符内部的同名属性会被覆盖掉。顺序决定了是谁覆盖谁。