整理文章后提交

This commit is contained in:
jimmy committed 2025-01-06 10:57:12 +08:00
1 parent 441dd0e18e
commit 473a07eba4
105 files changed
+1053 -678

No files matched your search

@@ -0,0 +1,73 @@
---
date: '2022-06-27T19:33:58+08:00'
draft: false
title: '如何在Vue3的Store中使用i18n'
keywords: [ 'vue','vue3','i18n' ]
tags: [ 'vue3','i18n' ]
categories: [ 'skill' ]
---
## 使用环境
> `Vue`的版本为:`3.2.36`,
>
> `vue-router`的版本为:`4.0.16`
>
> `vue-i18n`的版本为:`9.2.0-beta.40`
几乎都最新版本了
![在这里插入图片描述](/blog/2022/06/img-1.png)
## 问题复现
使用的`element-plus`框架进行项目的搭建,在登陆的时候在全局路由中进行密码的校验,如果密码错误或正确使用`element-plus`中的提示组件登录的提示,但是提示的内容要根据选择的语言进行分别的提示
这个似乎很正常的需求,但是因为使用的`vue3`中的`setup`,并且在路由中是使用的`ts`,所以不能使用this,并且像`vue`文件中使用的引入方式:
```js
const { t, d, n, locale } = useI18n()
```
这种方式也是不行的,因为执行顺序的前后问题,在路由加载时`useI18n()`还没有引入执行,所以这种方式的引入会直接报错的
## 问题解决
因为在`.vue`文件中会使用对应的方法将对应的内容引入,但是当执行路由时这个内容并没有加载,但是这个代码一定是存在并且可以直接运行的,所以可以通过其他方式直接手动将对应需要的代码引入,而不使用提供的方法
当在创建对应的i18n时,会先将对应的内容进行创建和导出:
![在这里插入图片描述](/blog/2022/06/img-2.png)
在这个文件中创建了i18n,并且对特定的配置项进行了指定,但是导出的这个i18n中有什么?
![在这里插入图片描述](/blog/2022/06/img-3.png)
在配置的文件中已经存在了要使用的方法,也就是导出的:`t`,`d`,`n`等,要使用的方法也在这里面
![在这里插入图片描述](/blog/2022/06/img-4.png)
在这个`global`中存在了对应的全局的方法,不需要通过i18n指定的方法进行引入执行,可以直接使用,所以这个就是要手动引入的内容
## 解决
![在这里插入图片描述](/blog/2022/06/img-5.png)
使用这种方法问题得到解决,不过在尝试过程中,这种两种方式使用的i18n也是有区别的
在引入的过程中,因为方式不同,所以引入的方法其实也不是同一个
![在这里插入图片描述](/blog/2022/06/img-6.png)
不过在对应的注释中也能略微看出二者的区别
![在这里插入图片描述](/blog/2022/06/img-7.png)
使用方法引入的‘t’应当也有特有的内容,这里只进行列举,不继续深入探讨。
@@ -0,0 +1,511 @@
---
date: '2022-08-26T12:33:58+08:00'
draft: false
title: 'JavaScript和Vue中实现表格(table)固定表头和首列【提供Vue和原生代码】'
keywords: [ 'vue','vue3','JavaScript' ]
tags: [ 'vue3','JavaScript' ]
categories: [ 'skill' ]
---
## 写在前面
本文主要介绍关于`JS`或`Vue`中如何进行表头,列固定,可以根据实际应用场景应用于`原生`,`Vue`,`移动端`,`小程序`中
实际效果展示:
![在这里插入图片描述](/blog/2022/08/img-1.gif)
对于列的固定,`table`中有对应的方法,但是如果列和表头都要固定,只能通过其他方式实现,<span style="color:red;">如果您找到了更好的自身方法,还请斧正</span>
## 思路概述
`表头,列头,表格本身,这三个内容被分为了三块元素,将这三个内容进行抽离,并且通过定位和大盒子的包裹进行样式管理。`
【当要进行滚动时,只要对滚动事件进行绑定,让`表头和列头显示对应的内容就完成了滚动的操作`】
下面有`Vue`组件的和`JavaScript`原生的代码,可以直接运行查看逻辑和效果
## 具体实现
整体代码,`可以直接创建组件,将代码复制到组件中使用`,在`App`中引用运行【基于`vue3+ts+less`实现,其他版本会在后面给出修改思路】`【最下面也提供了原生写法】`
```html
<!--
~ Time:2022/8/9 13:06 29
~ Name:fixmeTable.vue
~ Path:src/components/table
~ ProjectName:element-plus
~ Author:charlatan
~
~ Il n'ya qu'un héroïsme au monde :
~ c'est de voir le monde tel qu'il est et de l'aimer.
-->
<script lang="ts" setup>
import { ref } from 'vue'
const row = 20
const column = 30
let top = ref('0px')
let left = ref('0px')
const Scroll = (event: Event) => {
top.value = -event.target.scrollTop + 'px'
left.value = -event.target.scrollLeft + 'px'
}
</script>
<template>
<h3>
列头表头固定table
</h3>
<hr>
<!-- 表格-->
<div class="table">
<!-- 表头-->
<div class="rowHeader">
<table class="rowHeader-table">
<tr>
<td class="td" v-for="(item,index) in row" :key="index">
{{ item }}
</td>
</tr>
</table>
</div>
<!-- 列头-->
<div class="columnHeader">
<table class="columnHeader-table">
<tr v-for="(RootItem,index) in column" :key="index">
<td class="td">
{{ String.fromCharCode(RootItem + 64) }}
</td>
</tr>
</table>
</div>
<!-- 表格-->
<div class="tableBody" @scroll="Scroll($event)">
<table class="tableBody-table">
<tr v-for="(RootItem,index) in column" :key="index">
<td
class="td" v-for="(item,index) in row" :key="index">
{{ item + String.fromCharCode(RootItem + 64) }}
</td>
</tr>
</table>
</div>
</div>
</template>
<style scoped lang="less">
.table {
border: 1px solid red;
padding: 1rem;
border-radius: 1rem;
position: absolute;
left: 200px;
top: 100px;
width: 300px;
height: 300px;
// 表头
.rowHeader {
position: relative;
width: 260px;
max-width: 300px;
overflow: hidden;
left: 30px;
.rowHeader-table {
position: relative;
left: v-bind(left);
width: fit-content;
}
}
// 列头
.columnHeader {
position: relative;
max-height: 300px;
overflow: hidden;
width: 30px;
top: 3px;
.columnHeader-table {
position: relative;
top: v-bind(top)
}
}
// 表格本体
.tableBody {
width: 265px;
height: 300px;
position: absolute;
top: 55px;
left: 50px;
overflow: auto;
}
// 表格元素
tr {
width: fit-content;
white-space: normal;
display: flex;
.td {
display: block;
width: 30px;
height: 30px;
text-align: center;
line-height: 30px;
}
}
}
</style>
```
1. `html`部分:主要进行框架的设计,这里表头,列头,表格本体分为三份
```html
<template>
<h3>
列头表头固定table
</h3>
<hr>
<!-- 表格-->
<div class="table">
<!-- 表头-->
<div class="rowHeader">
<table class="rowHeader-table">
<tr>
<td class="td" v-for="(item,index) in row" :key="index">
{{ item }}
</td>
</tr>
</table>
</div>
<!-- 列头-->
<div class="columnHeader">
<table class="columnHeader-table">
<tr v-for="(RootItem,index) in column" :key="index">
<td class="td">
{{ String.fromCharCode(RootItem + 64) }}
</td>
</tr>
</table>
</div>
<!-- 表格-->
<div class="tableBody" @scroll="Scroll($event)">
<table class="tableBody-table">
<tr v-for="(RootItem,index) in column" :key="index">
<td
class="td" v-for="(item,index) in row" :key="index">
{{ item + String.fromCharCode(RootItem + 64) }}
</td>
</tr>
</table>
</div>
</div>
</template>
```
内容分为了三部分,这三部分将相互独立,通过样式的调节将三部分内容进行统一的管理。
这里使用的是`table`进行了内容的填充,因为表头和列头是单独的元素,所以可以使用其他内容如`div`等,通过样式上的和交互上的进行协调统一,这里不在赘述
2. 样式上的内容,因为主要是功能,这里样式使用`less`进行简单绘制
```css
<style scoped lang="less">
.table {
border: 1px solid red;
padding: 1rem;
border-radius: 1rem;
position: absolute;
left: 200px;
top: 100px;
width: 300px;
height: 300px;
// 表头
.rowHeader {
position: relative;
width: 260px;
max-width: 300px;
overflow: hidden;
left: 30px;
.rowHeader-table {
position: relative;
left: v-bind(left);
width: fit-content;
}
}
// 列头
.columnHeader {
position: relative;
max-height: 300px;
overflow: hidden;
width: 30px;
top: 3px;
.columnHeader-table {
position: relative;
top: v-bind(top)
}
}
// 表格本体
.tableBody {
width: 265px;
height: 300px;
position: absolute;
top: 55px;
left: 50px;
overflow: auto;
}
// 表格元素
tr {
width: fit-content;
white-space: normal;
display: flex;
.td {
display: block;
width: 30px;
height: 30px;
text-align: center;
line-height: 30px;
}
}
}
</style>
```
内容上和定义的结构进行统一调节,这里需要主要的是:<span style='color:red;font-weight:900;'>因为表格的宽度和表头的宽度对应,表格的高度和列头的高度固定,所以建议在定义时考虑好对应的宽高对应关系,方便调节</span>
在定义好表头和列头时,对与展示的部分通过外部的`div`进行定位的调节进行展示,内部的表格部分通过宽度的固定来达到样式统一,使用相对定位来完成展示内容的切换
内部使用了Vue3提供的`v-bind`,如果你使用的时vue2或其他内容请更换为内联样式或其他方式
`v-bind`为Vue3中提供,主要是将绑定的内容转换为自定义标签使用,具体介绍可以看我的另一篇文章:[Vue3新属性 — v-bind in css](https://blog.csdn.net/weixin_52235488/article/details/126290046?spm=1001.2014.3001.5502),里面有用法和原理的详细介绍
3. 逻辑部分:主要为内部的真正的表格绑定了滚动的监听,
```html
<script lang="ts" setup>
import { ref } from 'vue'
// 定义行和列
const row = 20
const column = 30
// 将内容进行响应式定义
let top = ref('0px')
let left = ref('0px')
// 绑定对应的监听事件
const Scroll = (event: Event) => {
top.value = -event.target.scrollTop + 'px'
left.value = -event.target.scrollLeft + 'px'
}
</script>
```
这里使用的动态数据在`v-bind`中进行,这里直接修改即可
## 其他环境中要修改的内容
这里对常见问题进行解决,如果没有匹配,请评论或找其他方式解决
1. `原生JavaScript中使用`:如果你完全没有使用过`Vue`,上面的代码我也改成了原生的版本,逻辑一样,这里就只放代码不做介绍了`直接创建文件复制使用`
```html
<!--
~ Time:2022/8/12 9:02 36
~ Name:test1.html
~ Path:
~ ProjectName:element-plus
~ Author:charlatan
~
~ Il n'ya qu'un héroïsme au monde :
~ c'est de voir le monde tel qu'il est et de l'aimer.
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta content="IE=edge" http-equiv="X-UA-Compatible">
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<title>Title</title>
<style>
* {
margin: 0;
padding: 0;
list-style: none;
font: 500 15px YouYuan;
text-decoration: none;
}
li {
cursor: pointer;
position: relative;
}
/*-------以上为默认设置(The above is the default setting)--------*/
.table {
border: 1px solid red;
padding: 1rem;
border-radius: 1rem;
position: absolute;
left: 200px;
top: 100px;
width: 300px;
height: 300px;
}
.rowHeader {
position: relative;
width: 260px;
max-width: 300px;
overflow: hidden;
left: 30px;
}
.rowHeader-table {
position: relative;
left: 0;
width: fit-content;
}
.columnHeader {
position: relative;
max-height: 270px;
overflow: hidden;
width: 30px;
top: 3px;
}
.columnHeader-table {
position: relative;
top: 0;
}
.tableBody {
width: 265px;
height: 270px;
position: absolute;
top: 55px;
left: 50px;
overflow: auto;
}
tr {
width: fit-content;
white-space: normal;
display: flex;
}
.td {
display: block;
width: 30px;
height: 30px;
text-align: center;
line-height: 30px;
}
</style>
</head>
<body>
<div class="table">
<!-- 表头-->
<div class="rowHeader">
<table class="rowHeader-table">
<tr id="rowHeader-table-tr"></tr>
</table>
</div>
<!-- 列头-->
<div class="columnHeader">
<table class="columnHeader-table" id="columnHeader-table-tr"></table>
</div>
<!-- 表格-->
<div class="tableBody" id="scroll">
<table class="tableBody-table" id="tableBody-table-tr"></table>
</div>
</div>
</body>
<script>
// 定义行和列
const row = 30
const column = 30
// 获取表头
let rowHeard = document.getElementById('rowHeader-table-tr')
// 创建表头元素
for (let i = 0, len = row; i < len; i++) {
// 获取元素
let td = document.createElement('td')
// 添加样式
td.classList.add('td')
// 添加内容
let testNode = document.createTextNode(i)
td.appendChild(testNode)
// 将表头放置到指定位置
rowHeard.appendChild(td)
}
// 创建表头元素
let columnHeard = document.getElementById('columnHeader-table-tr')
// 创建元素
for (let i = 0, len = column; i < len; i++) {
let tr = document.createElement('tr')
let td = document.createElement('td')
td.classList.add('td')
td.appendChild(document.createTextNode(String.fromCharCode(i + 64)))
tr.appendChild(td)
columnHeard.appendChild(tr)
}
// 创建表格元素
let table = document.getElementById('tableBody-table-tr')
for (let i = 0, len = column; i < len; i++) {
let tr = document.createElement('tr')
for (let j = 0, len = row; j < len; j++) {
let td = document.createElement('td')
td.classList.add('td')
td.appendChild(document.createTextNode(i + String.fromCharCode(j + 64)))
tr.appendChild(td)
}
table.appendChild(tr)
}
// 获取表头和列头滚动元素
let row_heard = document.getElementsByClassName('rowHeader-table')[0]
let column_heard = document.getElementsByClassName('columnHeader-table')[0]
// 绑定滚动时间
let scroll = document.getElementById('scroll')
scroll.onscroll = function (event) {
row_heard.style.left = -event.target.scrollLeft + 'px'
column_heard.style.top = -event.target.scrollTop + 'px'
}
</script>
</html>
```
主要通过的是JS的元素创建然后将元素添加至对应的内容中,然后进行事件的绑定,从而完成整体逻辑
2. `React`和`小程序中`,二者都是可以进行数据的绑定,元素的循环处理更加方法,小程序中没有鼠标,可能要更换为手指滑动操作,对于这个逻辑相同,`绑定元素的移动距离`,从而让表头和列头跟随移动从而达到同步的效果和目的
@@ -0,0 +1,91 @@
---
date: '2022-08-25T10:33:58+08:00'
draft: false
title: 'Vue3中的ref为何要用.value进行值的调用?'
keywords: [ 'vue','vue3' ]
tags: [ 'vue3' ]
categories: [ 'skill' ]
---
在`Vue2`中,所有的数据都通过一个Data进行统一的返回,并且在data中对某个组件要用的数据进行统一的管理,常见的使用形式是这样的:
```html
<template>
<div class="div">
<todos :Obj="tos" :removeObj="removeObj"></todos>
</div>
</template>
<script>
import search from '@/components/search'
import todos from '@/components/todos'
import all from '@/components/all'
export default {
name: 'App',
data () {
return {
tos: [
{ id: '001', value: '第一个', done: true },
{ id: '002', value: '第二个', done: true },
{ id: '003', value: '第三个', done: false },
{ id: '004', value: '第四个', done: true },
],
}
},
computed: { },
components: {
search, todos, all,
},
methods: {
removeObj (obj) {
console.log(obj.id)
this.tos = this.tos.filter(item => item.id !== obj.id)
console.log(this.tos)
},
},
}
</script>
<style scoped>
// 样式
</style>
```
可以看出来这里定义的内容都在一个数组中进行,或者是一个函数,将要使用的数据返回出来,这里无论怎么进行操作处理,最终进行数据代理的时候得到的都是一个对象,Vue2中直接通过`defineProperty`进行处理,并绑定对应的监听事件进行响应式的处理。
而Vue3中,数据的定义可以是单独的,Vue可以让我们随时需要随时定义,这也就带来了另一个问题,我需要的一个数据可能不是对象
```js
<script lang="ts" setup>
let str = ref('响应式字符串')
let obj = reactive({
name: '张三',
age: 10,
})
</script>
```
如果要定义的数据不是对象,还需要代理会怎么样?
在Vue2中数据的定义都在对象中统一进行,也就不会出现这种情况,如果一定要代理一个单独的数据呢?
Vue2中的数据代理通过`defineProperty`进行实现,也就是说我们要让`defineProperty`代理一个普通的数据,而不是一个对象,在`defineProperty`的MDN的文档中是这样定义的:
> **`Object.defineProperty()`** 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
通过这个可以明确看出,只能进行对象的代理,不能进行普通数据的代理,如果使用普通数据类型会直接报以下错误[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p1Lm0OSJ-1661407967498)(Vue3中的ref为何要用.value进行值的调用?.assets/image-20220825094409254.png)]
在Vue3中数据代理可以使用单一数据了,并且也改进了数据代理的方式,使用的是`Peoxy`完成了数据代理,而MDN中对`Proxy`也进行了定义:
> **Proxy** 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。
可以看出,`Proxy`依然是为对象服务,而不是普通的内容,这样问题似乎就解决了
本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。
可以看出,`Proxy`依然是为对象服务,而不是普通的内容,这样问题似乎就解决了
> 即使是Vue3中使用的`Proxy`的代理方式也不能进行普通数据的代理,所以当调用`Ref`的时候其实仍然创建了一个`Proxy`对象,并且Vue帮你给这个对象了一个`value`属性,属性值就是你定义的内容,改变的时候监视的改变依然是通过`Proxy`的数据劫持来进行响应式的处理,而模板中使用的时候`Vue`会默认调用对应的`value`属性,从而完成模板中的内容的直接调用
@@ -0,0 +1,377 @@
---
date: '2022-08-11T16:44:29+08:00'
draft: false
title: 'Vue3新属性 — css中使用v-bind(v-bind in css)'
keywords: [ 'vue','vue3' ]
tags: [ 'vue3' ]
categories: [ 'skill' ]
---
# Vue3新属性:CSS 中的 `v-bind()`
## 写在前面:
本文主要介绍Vue3中的新增的`v-bind()`的常用使用方式,主要包括在`css`,`less`,`scss`中的使用,可以参考官方文档查看:[Vue3官方文档](https://cn.vuejs.org/api/sfc-css-features.html#v-bind-in-css),本文将主要通过一个demo中的使用来展示
## 实际使用:
先创建一个通过的页面结构,因为是结构是通用内容,所以这里在直接进行简单的定义
```html
<div class="div">
<div class="span">
<div class="span_title">
这是测试文字
</div>
</div>
</div>
```
- 在`css`中:
在`css`中主要通过直接进行绑定,主要包括几种使用方式(我自己编的名词):`直接使用`、`拼接使用`、`对象调用`、`组合使用`【这是我想到的几种常见方式,如果有特殊需求,可以评论区沟通】
在JS中先对需要用的数据进行定义:
```js
// 进行拼接调用测试的数据
let width = 400
// 直接调用的数据
let div_height = '400px'
let div_color = '#e89393'
// 对象调用的数据
let span = {
width: '200px',
height: '200px',
color: 'green',
}
// 组合调用的数据
let transition = 'cubic-bezier(0, 1.5, .6, 1)'
```
然后这些数据直接在`css`中进行使用,使用`v-bind()`进行绑定
```css
<style scoped lang="css">
.div {
/* 拼接使用 */
width: v-bind(width + 'px');
/* 直接使用 */
height: v-bind(div_height);
background: v-bind(div_color);
}
.span {
/* 对象调用 */
width: v-bind('span.width');
height: v-bind('span.height');
background: v-bind('span.color');
display: flex;
justify-content: center;
align-items: center;
}
.span_title {
width: 100px;
height: 100px;
background: #000;
color: white;
/* 组合使用 */
transition: all .9s v-bind(transition);
}
.span:hover .span_title {
border-radius: 50%;
background: #a5f5b8;
color: #ff0000;
}
</style>
```
在对应的四个方式的调用中:
`直接使用`:完全没有问题
`拼接使用`:这个在`css`中没有问题,不过在`scss`中会出现错误,这个在下面的`scss`中会有详细介绍
`对象调用`:对象的调用和直接使用类似,不过不同的是,需要使用引号的包裹才能正常使用,如果直接书写会报错
`组合使用`:完全没问题
- 在`less`中:
使用的数据同样是上面给出的数据,这里直接改样式的内容了
```css
<style scoped lang="less">
// 使用变量承接
@height: v-bind(div_height);
.div {
width: 400px;
/* 直接使用 */
height: @height;
background: v-bind(div_color);
.span {
@width: v-bind('span.width');
/* 对象调用 */
width: @width;
height: v-bind('span.height');
background: v-bind('span.color');
display: flex;
justify-content: center;
align-items: center;
.span_title {
@transition: v-bind(transition);
width: 100px;
height: 100px;
background: #000;
color: white;
/* 组合使用 */
transition: all .9s @transition;
}
&:hover .span_title {
border-radius: 50%;
background: #a5f5b8;
color: #ff0000;
}
}
}
</style>
```
`直接使用`:没有问题
`拼接使用`:**存在问题**,在下面尝试进行了解决
`对象调用`:没问题
`组合使用`:没问题
<h3>问题:</h3>
> 在拼接使用有几种方式:
>
> ```js
> // 定义使用的数据
> let width = 400
> ```
>
> ```css
> // 直接拼接
> @width: v-bind( width + 'px');
> width: @width;
>
> // 拿到内容后拼接
> @width: v-bind(width) + 'px';
> width: @width;
>
> // 使用时拼接
> @width: v-bind(width);
> width: @width + 'px';
>
> ```
>
> 常用的拼接方法一般为这几种(如果有欠缺还请补充),这几种方式都进行了尝试,其中第二种第三种会没有效果,第一种会直接报错
<h3>问题分析(尝试解决):【这部分会很长,如果不想看,可以直接跳到解决方法】</h3>
首先是第一种,如果使用的话会直接报错,报错内容为:
![在这里插入图片描述](/blog/2022/08/img-1.png)
因为`less`的直接报错,导致定义的变量压根就没有被编译出来,从而报错
第二种和第三种错误一样:
![在这里插入图片描述](/blog/2022/08/img-2.png)
在这种使用方式中,变量可以正确承接,但是不能完成拼接的操作,导致只有变量而没有单位,并且可以看出最终都被翻译为`var(--变量名)`来执行,所以顺便也对`var()`进行了拼接测试
![在这里插入图片描述](/blog/2022/08/img-3.png)
这里进行调用内容的定义,并且模仿编译后的内容,进行使用,在这种情况下尝试使用拼接
> 尝试的拼接方式:
>
> `直接拼接`:
>
> ```css
> :root{
> --test:400 + 'px';
> }
> /* 使用 */
> width: var(--test);
> ```
>
> `接受变量后拼接`:
>
> ```css
> :root{
> --test:400 + 'px';
> }
> /* 使用 */
> width: var(--test+ 'px');
> ```
>
> `继承后拼接`:
>
> ```css
> :root{
> --test:400 + 'px';
> }
> /* 使用 */
> width: var(--test) + 'px';
> ```
结果也非常让不出意外的都不行,并且在第二种方式也是直接报错的,在寻找问题的过程中,发现了更加`amazing`的事情:
![在这里插入图片描述](/blog/2022/08/img-4.png)
这个变量压根就没定义,或者说没被识别到,所以重新模仿`Vue`直接定义行内样式,并且使用拼接尝试:
![在这里插入图片描述](/blog/2022/08/img-5.png)
这种直接的拼接方式直接将所有内容都进行了拼接,再换一种思路:使用`V-bind`这个V-bind指的是数据的而不是样式:
![在这里插入图片描述](/blog/2022/08/img-6.png)
这次问题得到了解决,并且样式数据也是响应式的单个数据,并且也是在`less`中正确使用,应该也算解决问题吧
<h3>解决方式(思路):</h3>
将变量的内容在`行内样式`使用拼接的方式进行定义,然后在定义的`less或scss`中进行使用,因为定义的样式是行内样式,所以优先级和变量出现的位置,都是在使用之前,所以可以正常使用
<h3>完整代码:</h3>
> 使用数据的定义:
>
> ```js
> // 大部分数据和预先提供的数据一样(这里只写了新增数据)
> let test = 400
> ```
>
> 页面结构:
>
> ```html
> <!-- 改变的内容为下面这行(其他内容和原来内容保持一致)-->
> <!-- 【在这里对要使用的数据进行单位的绑定】-->
> <div class="div" :style="{'--test' :test + 'px'}">
> <div class="span">
> <div class="span_title">
> 这是测试文字
> </div>
> </div>
> </div>
> ```
>
> 样式的使用:
>
> ```css
> <style scoped lang="less">
> // 承接使用
> @width: var(--test);
>
> .div {
> /* 使用 */
> width: @width;
> /* 或者直接使用 */
> width: var(--test);
> height: 400px;
> background: red;
> }
> </style>
> ```
>
在`css`的测试中几种方式也都能完美运行,并且在`less`的特有的数据绑定中也都没有问题,对于`拼接使用`是可以正常使用的。
我用的工具是`webstorm`less也是唯一一个没有报错的提示的(工具内的报错提示,可能不认识新内容把)
- 在`scss`中:
```css
<style scoped lang="scss">
// 使用变量承接
$width: v-bind(width + 'px');
$height: v-bind(div_height);
.div {
/* 拼接使用 */
width: $width;
/* 直接使用 */
height: $height;
background: v-bind(div_color);
.span {
$width: v-bind('span.width');
/* 对象调用 */
width: $width;
height: v-bind('span.height');
background: v-bind('span.color');
display: flex;
justify-content: center;
align-items: center;
.span_title {
$transition: v-bind(transition);
width: 100px;
height: 100px;
background: #000;
color: white;
/* 组合使用 */
transition: all .9s $transition;
}
&:hover .span_title {
border-radius: 50%;
background: #a5f5b8;
color: #ff0000;
}
}
}
</style>
```
`scss`相对`less`一些方法更加灵活,在`v-bind()`的使用中,拼接使用会出现错误,这个暂时按下不表,在原理中会详细阐述
- 执行原理:
`v-bind() in css`并没有进行劫持或者其他操作,他主要完成的任务是将`v-bind()`中的内容通过自定义属性的方式进行了重新定义,在编译后代码中可以看到
![在这里插入图片描述](/blog/2022/08/img-7.png)
所有的数据直接在自定义属性中进行,并且直接对应引用,自定义属性的内容的改变影响视图的效果,从而达到数据影响视图的效果,这个在使用中`less`,`css`中完全没有问题
但是,在`scss`中,因为编译之后`名字无法进行匹配`从而造成样式的丢失
![在这里插入图片描述](/blog/2022/08/img-8.png)
可以看到,使用的名字和编译的名字并不匹配,从而出错,这个使用时需要注意
@@ -0,0 +1,99 @@
---
date: '2022-08-09T10:33:58+08:00'
draft: false
title: '在JavaScript获取Promise的状态'
keywords: [ 'JavaScript','Promise' ]
tags: [ 'JavaScript' ]
categories: [ 'skill' ]
---
# 写在前面
本文属于对`stackoverflow`中写法的解析,原文链接:[**Stack Overflow** ](https://stackoverflow.com/questions/30564053/how-can-i-synchronously-determine-a-javascript-promises-state)
如果你在其他环境下遇到同样问题,这个[文章](https://blog.csdn.net/Lee_01/article/details/124892590)可能也会有帮助
# 问题复现
如何在代码执行过程中获取到`promise`的状态?
如果你想寻找或尝试通过原生的属性,或者指定API进行访问,基本可以放弃了,我也是看了很多博客的确没找到,如果您找了其他方式,还望指教
# 解决方式
本文中提到的解决方式主要是继续`stackoverflow`中提供的解决方式【完整代码】
```js
/**
* 传入需要测试的 Promise 对象,将对应结果返回
* @param promise 需要测试的 Promise 对象
* @return {Promise<string>}
*/
const promiseState = promise => {
const target = {}
return Promise.race([promise, target]).then(
value => (value === target) ? 'pending' : 'fulfilled',
() => 'rejected',
)
}
// 测试代码
let a = Promise.resolve();
let b = Promise.reject();
let c = new Promise(() => {});
promiseState(a).then(state => console.log(state)); // fulfilled
promiseState(b).then(state => console.log(state)); // rejected
promiseState(c).then(state => console.log(state)); // pending
```
这种方式通过`promise`中的`race()`方法来进行了状态的判断,非常奇妙的一种方式
# 代码分析
1. 在方法中会接收一个`promise`对象,开始了整个方法
2. 进入方法后会先创建一个`target`对象,这个对象只用于后续的匹配,没有其他含义
```js
const target = {}
```
3. 然后开始最核心的部分,因为`stackoverflow`中对代码进行简写,可以先进行代码的还原
```js
return Promise.race([promise, target]).then(
// 成功回调
value => {
return (value === target) ? 'pending' : 'fulfilled'
},
// 失败回调
() => {
return 'rejected'
},
)
```
可以复现出这种结构,`promise`的`race`开始后,接收两个对象,一个为刚刚创建的`target`对象,还有一个是接收到的`promise`对象,当两个其中一个状态结束时,整个`Promise.race()`结束,这时分为三种情况
1. 当传入的`promise`为`pending`状态时,`Promise.race`会找到最先有确定状态的元素,并将其返回,因为`promise`没有结束,那么返回值对象会接收到定义的`target`,因为`target`的状态是确定的,这时`value`接收到的值就是已经确定状态的`target`,如果进行对比,那么他们两个一定是相等的,这时也就是返回`pending`
2. 当传入的`promise`为`fulfilled`状态时,相当于`promise`已经有确定的值了,`Promise.race`匹配到第一个直接结束,并将匹配到的内容返回,返回的内容因为是一个全新的对象,对象的内存地址不可能相等,所以判断结果是`false`,也就返回`fulfilled`
3. 当传入的`promise`为`rejected`状态时,`promise`状态确定,那么因为状态报错,直接进入`catch`中,走失败回调,这个回调一旦执行,就可以判定`promsie`结束,并且内容出现报错,直接返回`rejected`即可
4. 在调用的时候,因为返回的时会将对应的状态通过`promise`返回,所以直接通过调用方法之后的`then`中指定回调来完成状态的获取
- **值得注意的是**:`Promise.race()`在匹配的过程中,一定保证要判断的`promise`在前,因为只有当`promise`状态不确定时才会判断第二个内容的状态,如果将状态已经确定的`target`放在第一个,那么将不会再进行`promise`的判断,返回结果永远为`fulfilled`
- 并且因为`catch`有两种形式,可以进行变形,这种形式可能更常见(根据个人习惯了)
```js
const promiseState = promise => {
const target = {}
return Promise.race([promise, target]).then(
value => {
return (value === target) ? 'pending' : 'fulfilled'
},
).catch(() => {
return 'rejected'
})
}
```