Git Product home page Git Product logo

js-learn's People

Contributors

fncheng avatar

Watchers

 avatar

js-learn's Issues

JS实现回到页面顶部

scrollTop

scrollTop属性表示被隐藏在内容区域上方的像素数。元素未滚动时,scrollTop的值为0,如果元素被垂直滚动了,scrollTop的值大于0,且表示元素上方不可见内容的像素宽度
由于scrollTop是可写的,可以利用scrollTop来实现回到顶部的功能

function scrollToTop() {
  document.body.scrollTop = document.documentElement.scrollTop = 0;
}

scrollTo

function scrollToTop() {
  scrollTo(0, 0);
}

scrollTo(x,y)方法滚动当前window中显示的文档,让文档中由坐标x和y指定的点位于显示区域的左上角

设置scrollTo(0,0)可以实现回到顶部的效果

scrollIntoView()

Element.scrollIntoView方法滚动当前元素,进入浏览器的可见区域 

function scrollToTop() {
  const app = document.querySelector("#app");
  app.scrollIntoView();
}

优化

控制按钮的显示与隐藏

要注意,display: none;的属性是无法被hover的

new操作符以及es6转成es5

new操作符

new操作符的作用

es6 通过babel转成es5

objFactory就类似于new操作符的作用

function Person(name) {
  this.name = name;
}

Person.prototype.getName = function () {
  return this.name;
};

var objFactory = function () {
  let obj = new Object();
  // 获取实参的第一个值
  // 等效于 arguments.shift()
  Constructor = [].shift.call(arguments); // arguments  实参 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/arguments
  // arguments对象不是一个 Array 。它类似于Array,但除了length属性和索引元素之外没有任何Array属性。例如,它没有 pop 方法。但是它可以被转换为一个真正的Array
  obj.__proto__ = Constructor.prototype;
  // 修改Constructor(这里是指Person)里的this指向obj
  // 所以obj.name = 'seven'
  // 这里argiments第一个值已经被shift() 了
  var ret = Constructor.apply(obj, arguments);
  console.log(ret);
  // var ret = Person.apply(obj, arguments);
  return typeof ret === 'object' ? ret : obj;
};
// let a = new Person('seven');
var a = objFactory(Person, 'seven');
console.log(a.name);
console.log(a.getName());
console.log(Object.getPrototypeOf(a) === Person.prototype);

Mockjs使用

使用

import mockjs from 'mockjs'

mockjs.mock('/api/getdata', 'get', {
  code: 200,
  body: {
    name: 'zs',
    age: 20
  }
})

然后在需要使用的页面引入即可

如果使用fetch请求的话,则需要额外安装fetchMock

import fetchMock from 'fetch-mock'
// 初始化 fetch-mock
fetchMock.config.overwriteRoutes = true

fetchMock.mock('/api/getdata1', {
      code: 200,
      data: {
        username: 'mock',
        age: 18
      }
    })

规则

http://mockjs.com/examples.html

@id // 随机身份证
@guid // 随机id
@ip // 随机ip地址

// 数字
"number|1-100": 100   // 随机数字1-100内
"number|+1": 202  // 202开始自增1
// 布尔值
'boolean': '@boolean'
// 或者用0/1代替
'numnber|0-1': 0

// 时间
@date
Random.date('yyyy-MM-dd')
@time

// 姓名
@name
Random.name()
@name(true) // 有middle name

图片懒加载

图片懒加载

先看几个API

// 获取屏幕可视区域的高度 (不包括滚动条)
document.documentElement.clientHeight

mdn上的解释:

// 获取元素相对于文档顶部的高度
element.offsetTop
// 获取浏览器窗口顶部与文档顶部之间的距离,也就是滚动条滚动的距离
document.documentElement.scrollTop

通过判断

element.offsetTop - document.documentElement.scrollTop < document.documentElement.clientHeight

来确定元素是否进入到了可视区域

<img data-src="./images/1.jpeg" alt="" />
<img data-src="./images/2.png" alt="" />
<img data-src="./images/3.png" alt="" />
<img data-src="./images/4.png" alt="" />
<img data-src="./images/5.png" alt="" />
<img data-src="./images/6.jpeg" alt="" />
<img data-src="./images/7.png" alt="" />

<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>
<script>
  let imgs = document.querySelectorAll('img');
  function getTop(e) {
    let T = e.offsetTop;
    while ((e = e.offsetParent)) {
      T += e.offsetTop;
    }
    return T;
  }
  function lazyLoad(imgs) {
    let H = document.documentElement.clientHeight; // 获取可视区域高度
    let S = document.documentElement.scrollTop || document.body.scrollTop;
    imgs.forEach((item) => {
      if (H + S > getTop(item)) {
        item.src = item.getAttribute('data-src');
      }
    });
  }
  window.onload = window.onscroll = () => {
    lazyLoad(imgs);
  };
  _.throttle(window.onscroll, 1000);
</script>

这里用到了一个知识:

img标签在没有src属性的时候是不会去请求的。

Element.getBoundingClientRect()

返回元素的大小及其相对于视口的位置(相对于可视区域左上角)

const bound = el.getBoundingClientRect();

当bound == clientHeight 时,说明元素即将进入可视区域了 。

所以bound <= clientHeight ,图片是在可视区域内的

bound<0 图片离开了可视区域

Intersection Observer API

mdn的解释:

Intersection Observer API提供了一种异步检测目标元素与祖先元素或 viewport 相交情况变化的方法。

<img data-src="./images/1.jpeg" alt="" />
<img data-src="./images/2.png" alt="" />
<img data-src="./images/3.png" alt="" />
<img data-src="./images/4.png" alt="" />
<img data-src="./images/5.png" alt="" />
<img data-src="./images/6.jpeg" alt="" />

<script>
  let imgs = document.querySelectorAll('img');
  let callback = (e) => {
    // console.log(e);
    let el = e[0].target;
    // set src attribute to load img
    el.src = el.dataset.src;
  };
  let observer = new IntersectionObserver(callback);
  imgs.forEach((img, i) => {
    observer.observe(img);
  });
</script>

参考文档:

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

Intersection Observer API

FormData上传二进制文件

multipart/form-data

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

一个简单的例子:

Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryNcxNYP2Llirw6P9C

Content-Type 文件类型

boundary 分隔符 分隔符的作用?多文件多字段时用于划分

看Request body

Request Payload:
------WebKitFormBoundary3BCUw6TpNMWxyC8B
Content-Disposition: form-data; name="myfile"; filename="5g.png"
Content-Type: image/png


------WebKitFormBoundary3BCUw6TpNMWxyC8B--

其中有文件名,formdata.append() 的name字段 以及Content-Type 具体的文件类型

后端接收的文件格式

------WebKitFormBoundaryOjAKFnxCzqgLffEj
Content-Disposition: form-data; name="name"

zs
------WebKitFormBoundaryOjAKFnxCzqgLffEj--

遇到的问题❓

1.Ajax formdata 为空的问题?

在使用ajax上传图片时打印formdata 显示FormData {}

解决办法:

meteor/meteor#8125

FormData 不能被console.log

使用原生ajax发送formdata,后台接受不到数据;而使用axios来发送请求却可以收到。

1.这是因为使用ajax处理二进制数据时,需要使用XMLHttpRequest 对象的 overrideMimeType()方法。

var oReq = new XMLHttpRequest();
oReq.open("GET", url);
// 以二进制字符串形式检索未处理的数据
oReq.overrideMimeType("text/plain; charset=x-user-defined");
/* ... */

2.也可以修改XMLHttpRequest的responseType属性

xhr.open('POST', 'http://127.0.0.1:3000', true);
// xhr.setRequestHeader(
//   'Content-Type',
//   'multipart/form-data;boundary=----WebKitFormBoundaryVFmi5Doq4aeH0RQ1'
// );//无效

// xhr.overrideMimeType('multipart/form-data'); //有效

xhr.responseType = 'blob'; //有效
xhr.send(formdata);

Boolean运算

Boolean('')  // false
Boolean(0)  // false

!!符号与Boolean() 功能一样

TypeScript-元组

const arr = [['1', 1], ['2', 2]]

想给上面的二维数组定义一个类型,发现无从下手。
经人提醒想起来元组这个概念

元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。

于是

type T1 = Array<[string,number]>

这样就可以

sort排序

MDN

sort排序是升序排序

const List = [
  { name: 'zs', age: 20 },
  { name: 'zs', age: 30 },
  { name: 'zs', age: 50 },
  { name: 'zs', age: 80 },
  { name: 'zs', age: 17 },
  { name: 'zs', age: 33 }
]

const List2 = List.sort((a, b) => {
  return a.age - b.age
})
  • 如果 compareFn(a, b) 大于 0,b 会被排列到 a 之前。小的排在大的前面,即升序
  • 如果 compareFn(a, b) 小于 0,那么 a 会被排列到 b 之前;

onevent和addEventListener的区别?

http://if-true.com/2018/09/20/onclick-vs-addEventListener.html
onevent vs addEventListener ?

  1. Listener(s)
    onclick只能绑定一个事件处理函数,并且可以通过设为 null 进行移除;
    而addEventListener 可以绑定多个事件处理函数,并且可以进行更精细的控制(通过第三个参数,包括 capture、once、passive)等,可以通过 removeEventListener 移除。
<div id="app">Button</div>

const app = document.getElementById('app');
app.onclick = () => {
  console.log(123);
};
app.onclick = () => {
  console.log(456);
};
app.addEventListener('click', () => {
  console.log(789);
});
app.addEventListener('click', () => {
  console.log(890);
});

上面的代码中,123会被456覆盖,而789就不会被890覆盖。

  1. 事件流阶段
    事件流有3个阶段:捕获、到达目标、冒泡。可以通过 event.eventPhase 来判断当前。捕获(1)、到达目标(2)、冒泡(3),还有个 None(0)状态,表示该事件已经被处理。
    addEventListener 可以根据第三个参数来决定事件处理发生在哪个阶段。而 onclick 往往在冒泡阶段触发。(这个说法并不准确,根据 DOM 结构不同,可能在冒泡也有可能在到达目标阶段)。
    当 addEventListener 和 onclick 同时绑定且前者指定冒泡阶段时,按照绑定先后顺序依次触发。

什么是纯函数

纯函数 Pure Function

纯函数符合一下两个条件:

  1. 返回结果只依赖于它的参数
  2. 执行过程无任何副作用

纯函数的好处

纯函数非常“靠谱”,执行一个纯函数你不用担心它会干什么坏事,它不会产生不可预料的行为,也不会对外部产生影响。
不管何时何地,你给它什么它就会乖乖地吐出什么。如果你的应用程序大多数函数都是由纯函数组成,那么你的程序测试、调试起来会非常方便。

鼠标拖拽事件mousemove

鼠标按下触发mousedown事件,拖拽触发mousemove事件,但是松开不触发mouseup

需要e.preventDefault 阻止mousemove的默认事件

组件拖拽过程中drop事件 (当元素或选中的文本在可释放目标上被释放时触发),为了获取到触发元素冒泡过程中的所有元素,使用event.path属性,但是这个属性在Firefox下并不存在

百度后的解决方案

e.path || (e.composedPath && e.composedPath())

e.path是Chrome单独支持的属性,不属于MDN的标准,所以在MDN上搜不到event.path,但是composedPath是标准的属性。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.