小田'blog

前端小菜鸡(〃∀〃)

0%

这里使用vue(其他道理应该也是一样的), 因为微信的sdk只能在他的域名下才能正常使用, 我们又不能去服务端开发然后build, 所有在本地调试微信sdk就很有必要了,(微信分享在另一篇会写)

Read more »

教程

教程写的很好, 我按照教程跑了一部分

真实的示例:为级联动画使用一个自定义滚动指令

这部分没有跑, 看了看directive里面的代码, 通过v-scroll里面的参数来进行判断的, 然后把toPath里面的参数传入进来,

我根据教程学习, 然后顺便添加了一个lodash throttle 来’节流’

创建一个vue demo

1
... ... 省略

新建一个directive.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import Vue from 'vue'
import throttle from "lodash/throttle";
Vue.directive('scroll', {
inserted: (el, binding) => {
let f = evt => {
if (binding.value(evt, el)) {
// eslint-disable-next-line no-console
// console.log(8, binding.value(evt, el))
// remove event
window.removeEventListener('scroll', f)
}
}
// listen event
// use lodash/throttle call methods
window.addEventListener('scroll', throttle(f, 300))
// eslint-disable-next-line no-console
console.log(el, binding)
}
})

import "./directive"; // main.js 里面 import

在组件里面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<HelloWorld v-scroll="handleScroll" class="box" msg="Welcome to Your Vue.js App"/>
````

可以是任何元素 使用 v-scroll="xxx"

```js
// ....
handleScroll (evt, el) {
// eslint-disable-next-line no-console
console.log(19, evt, el, window.scrollY)
// judeg window.scroll, execution TweenMax function
if (window.scrollY > 50) {
TweenMax.to(el, .3, {
y: -10,
opacity: 1,
// eslint-disable-next-line no-undef
ease: Sine.easeOut
})
}
// to meet the conditions return true else return false
return window.scrollY > 100
}
// ...
1
2
3
4
5
.box {
opacity: 0;
transition: 1.5s all cubic-bezier(0.39, 0.575, 0.565, 1);
/* transform: translate3d(0, 10px, 0); */
}

在线工具

匹配A字符与B字符之间的字符(包含AB)

A.*?B

匹配A字符与B字符之间的字符(包含A不包含B)

A.*?(?=B)

匹配A字符与B字符之间的字符(不包含AB)

(?<=A).*?(?=B)


资料

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
### 正则中的 ?= 、?<= 、?!、 ?<!=

以前看正则的时候遇到?= 、?<=,在网上搜索出来名字有称之为正向预查、负向预查的,有称之为前瞻、后顾的,看用法的话大概知道是怎么回事,但就是记不住啊,对于我来说,这名称太抽象(鬼扯)了。

今天看书看到作者讲到正则,感觉自己又有所领悟,翻出来重新理解了一下。

如今我的理解是这样的,我将<记为方向,包含这个箭头说明是放在目标内容左边的:

1. ```?=``` : 询问后面跟着的东西是否等于这个    /b(?=a)/.test('bab')

2. ```?<=``` : 询问是否以这个东西开头  /(?<=a)b/.test('ab')

3. ```?!``` : 询问后面跟着的东西是否不是这个  /b(?!a)/.test('bb')

4. ```?<!=``` :询问是否不是以这个东西开头  /(?<!=a)b/.test('bb')

其实按照我这样理解的话,```?!``` 后面要是加上```=```就更加符合我的心理预期了,最后还有一点,匹配得到的结果并不包含 ?=、?<=、?!和?<!=里面的内容

### 顺便记录一下

javascript的replace方法的第二个参数,如果是传入的字符串的话,有几个特殊的东西。

1. ```$&`` : 表示匹配到的结果。'javascript'.replace(/script/, '$&$&') ->  ‘javascriptscript’

2. ```$\```` : 表示匹配到的结果的左边或者说前面的那一堆字符串。 'javascript'.replace(/script/, '$& 不是 $`')  ->  "javascript 不是 java"

3. ```$'``` : 表示匹配到的结果的右边或者说后面的那一堆字符串。 '我是猪'.replace(/我是/, "$&$'")  ->   "我是猪猪"

4. ```$$``` : 表示$字符。

作者:不过从心而已
链接:https://www.jianshu.com/p/661af704198c
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

vue-i18n国际化在data中切换不起作用

https://www.bbsmax.com/A/qVdep96p5P/

配置会写在另一篇文章里面!!

1
2
3
4
5
6
7
8
将this.$t() 写到了data属性里,切换语言不起作用

data是一次性生产的,你这么写只能是在 data 初始化的时候拿到这些被国际化的值,并不能响应变化。

官方的解决办法是,建议我们将表达式写到computed属性里,不要写到data里

copy⬆️

因为在 js 中的this.options只会在初始化的时候执行一次,它的数据并不会随着你本地 lang的变化而变化,所以需要你在lang变化的时候手动重设this.options。 – copy

https://panjiachen.github.io/vue-element-admin-site/zh/guide/advanced/i18n.html

有些数据又不想写在computed里面怎么办???

解决方案

  1. 刷新页面 (体验不太好
  2. 写入computed
  3. 通过监听locale重新赋值
1
2
3
4
5
6
watch: {
'$i18n.locale'() {
console.log(this.$i18n.locale)
this.setContent() // 重新设置一下值
}
},

https://developers.google.com/web/fundamentals/web-components/shadowdom#slots

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
<!-- custom dom -->
<custom-tabs>
<!-- 定义slot -->
<button slot="tab">button</button>
<button slot="tab">button</button>
<button slot="tab">button</button>
<!-- 默认slot -->
<section>section1</section>
<section>section2</section>
<section>section3</section>
</custom-tabs>

<script>
let selected_ = null
class customTab extends HTMLElement {
constructor() {
super()

let shadowRoot = this.attachShadow({mode: 'open'})
// 样式 内容
shadowRoot.innerHTML = `
<style>
:host {
border: 1px solid #ececec;
display: inline-block;
}

#tabs ::slotted(*) {
border: none;
outline: none;
padding: 20px 40px;
background: #f1f1f1;
}

#tabs ::slotted([aria-selected="true"]) {
background: #fff;
}

#panels {
padding: 20px;
font-size: 18px;
}

#panels ::slotted([aria-hidden="true"]) {
display: none;
}

</style>

<div id="tabs">
<slot id="tabSlot" name="tab"></slot>
</div>
<div id="panels">
<slot id="panelsSlot"></slot>
</div>
`
}

// get set
get selected() {
return selected_
}

set selected(idx) {
selected_ = idx
this._selected(idx)
}

connectedCallback() {

// set role
this.setAttribute('role', 'tab-list')

// get Element
let tabsSlot = this.shadowRoot.querySelector('#tabSlot')
let panelsSlot = this.shadowRoot.querySelector('#panelsSlot')

// filter Element
this.tabs = tabsSlot.assignedNodes({flatten: true})
this.panels = panelsSlot.assignedNodes({flatten: true}).filter(el => el.nodeType === Node.ELEMENT_NODE)


// set role
for (const [i, panel] of this.panels.entries()) {
panel.setAttribute('role', 'tab-panel')
}

// set click keydown event
this._boundOnTitleClick = this._onTitleClick.bind(this)
this._boundOnKeydown = this._onKeydown.bind(this)

tabsSlot.addEventListener('click', this._boundOnTitleClick)
tabsSlot.addEventListener('keydown', this._boundOnKeydown)

// set default selected, by tab html selected attribute
this.selected = this._findFirstSelectedTab() || 0
}

// tab click event
_onTitleClick(e) {
if (e.target.slot === 'tab') {
// now click Element index
this.selected = this.tabs.indexOf(e.target)
}
}

// tab keydown event
_onKeydown(e) {
switch(e.code) {
// up left
case 'ArrowUp':
case 'ArrowLeft':
e.preventDefault()
// --, if it's 0 idx = length - 1 else idx
var idx = this.selected - 1
idx = idx < 0 ? this.tabs.length - 1 : idx
// click event
this.tabs[idx].click()
break;
// down right
case 'ArrowDown':
case 'ArrowRight':
e.preventDefault()
// ++ by & tab click event
var idx = this.selected + 1
this.tabs[idx % this.tabs.length].click()
break;
default:
break;
}
}

// find tab html attribute selected set now Tab
_findFirstSelectedTab() {
let selectedIdx
// for
for (const [i, tab] of this.tabs.entries()) {
// set role
tab.setAttribute('role', 'tab')
// if tab has selected, nowTab is i
if (tab.hasAttribute('selected')) {
selectedIdx = i
}
}
return selectedIdx
}

// set tab toggle function
_selected(idx = null) {
// for
for(let i = 0, tab; tab = this.tabs[i]; ++i) {
// if idx === i equal true
let selected = idx === i
// set attribute
tab.setAttribute('aria-selected', selected)
this.panels[i].setAttribute('aria-hidden', !selected)
}
}
}


if (customElements) customElements.define('custom-tabs', customTab)
else console.log('不支持 custom')
</script>

开始自己想找个地方存放自己的文章demo,开了一个仓库感觉懒得维护,直接放进文件价里面又会被build编译

然后搜了一个好像没有什么好的方案,自己想了一个’野路子’(gulp)

使用简单的gulp命令就能解决这个需求!!!💗

https://www.gulpjs.com.cn/

安装

1
npm install --save-dev gulp

写 gulpfile.js

1
2
3
4
5
6
7
const { src, dest } = require('gulp');

exports.default = function() {
console.log('copy blog_source')
return src('blog_source/**/*')
.pipe(dest('.deploy_git/blog_source'));
}

我只需要吧存放demo的文件夹全部copy过去不就好了吗!!!(机智)

修改原来的推送

1
2
3
4
5
6
7
8
9
# old
hexo g -d

# now
"scripts": {
"gd": "hexo g -d && gulp"
},

yarn gd

先执行原来的命令,然后执行gulp(完事) 这样大家需要demo也可以直接去仓库里面查看或者下载😄

首先来写一个示例吧

Web Components 标准非常重要的一个特性是,它使开发者能够将HTML页面的功能封装为 custom elements(自定义标签),而往常,开发者不得不写一大堆冗长、深层嵌套的标签来实现同样的页面功能。这篇文章将会介绍如何使用HTML的custom elements。 - MDN

https://developer.mozilla.org/zh-CN/docs/Web/Web_Components/Using_custom_elements

具体看MDN文档,(复制完应该就差不多了 然后去这里玩)

https://developers.google.com/web/fundamentals/web-components/

Read more »

资料

https://zhuanlan.zhihu.com/p/20486738

GO

  • 首先去twitter打开控制台下载png的素材
  • 放入一个div
  • 设置css 完事

Js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
export default class Render {
append(parent, dom){
parent.append(dom)
}
}


let render = new Render()

let likeButton = document.createElement('div')
likeButton.classList.add('like-button')


render.append(document.querySelector('body'), likeButton)

Css

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
.like-button {
width: 50px;
height: 50px;
background-position: left;
background-image: url(https://abs.twimg.com/a/1446542199/img/t1/web_heart_animation.png);
background-repeat:no-repeat;
background-size:2900%;
cursor: pointer;
&:hover {
background-position: right;
}
}

.is-animating {
animation: heart-burst .8s steps(28) 1 forwards;
}

@keyframes heart-burst { // 从左到右
0%{
background-position: left;
}
100%{
background-position: right;
}
}


鼠标经过png从 background-position: left;background-position: right; 变色处理

通过单击添加 class 达到目的

animation: heart-burst .8s steps(28) 1 forwards; 分为steps 28 执行动画

js

1
2
3
4
5
6
7
8
9
likeButton.onclick = function() {
let hasClass = likeButton.classList.contains('is-animating')
if (!hasClass) likeButton.classList.add('is-animating')
}

likeButton.addEventListener('animationend', function() {
let hasClass = likeButton.classList.contains('is-animating')
if (hasClass) likeButton.classList.remove('is-animating')
}) // 根据情况处理

– end —