学习周报 -2022/10/03
项目总结
Vue3商城
使用<script setup>
标签与组合式API
重构已经编写的相关页面,改为使用<script setup>
标签与组合式API,不需要专门使用export暴露组件,所有的顶层变量都会默认暴露。
使用组合式API则不需要专门设置data
、computed
、methods
等对象,而是可以直接声明对应变量,Vue即可直接识别为对应的变量、函数等,可以将相关联的变量、函数写在一起,维护和开发上更加方便。
使用defineProps
定义props参数,即可正常接收和使用props参数。
<script setup>
const props = defineProps(['foo'])
console.log(props.foo)
</script>
从Vuex迁移至Pinia
使用$patch
方法修改state,在方法中使用this
可以获取当前store对象。
Pinia的组合式API
ref()
s becomestate
propertiescomputed()
s becomegetters
function()
s becomeactions
知识总结
el-button的disabled属性搭配v-if无法正常生效
问题描述
以下代码中,原本使用:disable
禁用的按钮会出现无法正常禁用的情况:
<el-button v-if="show" :disabled="true">禁用的按钮</el-button> <!-- show是一个变量,值会发生变化 -->
<el-button v-if="!show">隐藏的按钮</el-button> <!-- 这里的v-if="!show"替换为v-else也是一样的 -->
<script>
...
data(){
return {
show: false
}
},
mounted(){
this.show = true // 挂载时将show设置为true,让按钮显示。其他切换两个按钮显示的方法都会出现一样的问题
}
...
</script>
解决方法
添加属性key,值可以是任意值:
<el-button v-if="show" :disabled="true" key="test">禁用的按钮</el-button> <!-- show是一个变量,值为true -->
<el-button v-if="!show">隐藏的按钮</el-button> <!-- 这里的v-if="!show"替换为v-else也是一样的 -->
问题原因
Vim是共用虚拟DOM节点的,而且el-button
内部使用的button
设置了一个计算属性,会判断是否el-button
是否有disabled
属性且为真,如果满足条件则会调用一个方法将按钮禁用。
第一次渲染(show:false
)的隐藏的按钮生成时没有disabled
属性,理所应当不会禁用,但是当第二次渲染(show
被修改为true
)时,disabled
被设置为true
。但是,这时Vue判断disabled实际调用的计算属性没有发生变化,没有重新执行,所以没有调用按钮禁用的方法。
简单来说,就是第一次生成无disabled
属性的el-button
实例时,控制禁用的计算属性绑定的依赖中没有disabled
属性,所以当后续disabled
属性变化时也不会重新执行该计算属性,而是直接返回之前缓存的结果。
TypeScript基本用法
直接在声明变量时赋值即声明类型
例如:
let a: string = '123'
//也可以使用es6的字符串模板
let str: string = `dddd${a}`
let notANumber: number = NaN;//Nan
let num: number = 123;//普通数字
void、undefined和null的区别
这三个类型虽然看起来相似,但是有区别,即void类型的数据不能赋值给其他类型的,三者和其他类型的关系如下:
即undefined
和null
是其他类型的子集。
而且如果开启了严格模式,null
也不能赋值给void
。
unknow和any
unknow
比any
严格,any
会放弃所有的类型检查,建议需要使用any
时优先使用unkonw
。unknow
类型不能赋值给除了unknow
和any
的其他类型
let names:unknown = '123'
let names2:string = names // 会提示错误
接口和对象类型
使用interface关键字定义对象类型,后续定义对象时如果指定该对象类型,则需要和对象类型保持一致:
//必须与接口保持一致
interface Person {
b:string,
a:string
}
const person:Person = {
a:"213"
} // 会报错,因为少了值为string类型的b
函数变量和返回值类型声明
数组、元组中的属性类型声明
数组:
即相同类型数据的集合
var numlist:number[] = [2,4,6,8]
元组:
即长度、元素类型都固定(且每个元素类型可以不同)的数组,声明方法类似(这里还添加了readonly标记来让该元组只读)
let arr: readonly [number,boolean,string,undefined] = [1,true,'sring',undefined]
编译设置
在项目根目录下新建tsconfig.json,在其中使用以下参数设置编译文件:
include
:设置编译文件和文件夹范围;exclude
:设置不编译的文件和文件夹;extends
:设置被继承的配置文件;files
:指定编译特定文件;compilerOptions
:编译器配置项,不设置时有默认值(完整编译选项);部分选项:
removeComments
:移除注释;noEmit
:不生成编译后文件,仅执行;alwaysStrict
:使用严格模式;noImplicitAny
:不对隐式Any类型报错;noImplicitThis
:当this
表达式的值为any
类型时,不报错;strictNullChecks
:严格检查空白值;
**
compileOnSave:
**让IDE在保存文件的时候根据tsconfig.json
重新生成文件;
Less和Sass
这两个是css预处理器,即使用专门的语言进行样式的设计,再通过编译器转换成正常的css。
相比CSS的不同
- 可以使用变量
编译方式
- 工具编译
Vite中配置CSS额外数据
在vite.config.ts
文件中可以使用css.preprocessorOptions
配置CSS预处理器的额外数据:
export default defineConfig({
css: {
preprocessorOptions: {
scss: {
additionalData: `$injectedColor: orange;`}
}
}
})
Vite比Webpack快的原因
- Vite对于ES的模块语法会直接保持原状,浏览器也是支持这样在html中引入js模块的,而Webpack会对所有js文件进行编译合并后再引入;
- Vite实行按需编译,如果当前页面还没用到修改的内容,则不会立即编译打包;
Git工作流(以Github为例)
自己有一个本地个人分支,当远端仓库主分支有更新时:
- 切换本地分支到主分支:
git checkout main
- 拉取远端主分支到本地主分支:
git pull origin master
- 切换到个人分支:
git checkout my-feature(个人分支名)
- 将个人分支基底替换为主分支,然后再覆盖commit的修改(如果有冲突会提示):
git rebase main(主分支名)
- 个人分支修改结束后push到远端:
git push -f origin my-feature(个人分支名)
- 在Github上提交Pull request,申请合并到主分支
- 审查代码后,管理员使用Squash and merge通过并合并改动,这样合并出来的主分支上commit history只有一个,而不会把所有个人分支中的commit都提交
- 管理员删除远端个人分支;
- 本地切换到主分支上:
git checkout main
- 本地也删除个人分支:
git branch -D my-feature
- 拉取最新的更新内容到本地:
git pull origin master
CSS中的clamp()方法
和min()
、max()
方法类似,都是输入多个参数,然后根据要求输出一个参数。
但是clamp()
相对复杂一些:
.clamp{
width: clamp(minVal, preferredVal, maxVal)
}
minVal
:最小值,当preferredVal
小于该值时返回该值;
preferredVal
:首选值,默认返回该值;
maxVal
:最大值,当preferredVal
大于该值时返回该值;