学习小记1

第一次碰到添加水印的需求在此做个小记录,如有更好的建议还请告知。(采用的是vue3,原生JQ的写法: 区别是将获取元素的方法进行修改)

参考文章:使用JS给页面添加水印效果_tansci的博客-CSDN博客_js 加水印

let watermark_text = ref("大傻蛋子");
let watermarks = ref(null);
onMounted(() => {
  watermark();
});
const Salarys = reactive(salary);
const watermark = (settings) => {
  //默认设置
  let defaultSettings = {
    watermarl_element: "watermark-wrapper",
    watermark_txt: watermark_text.value,
    watermark_x: 10, //水印起始位置x轴坐标
    watermark_y: 10, //水印起始位置Y轴坐标
    watermark_rows: 20, //水印行数
    watermark_cols: 20, //水印列数
    watermark_x_space: 50, //水印x轴间隔
    watermark_y_space: 50, //水印y轴间隔
    watermark_color: "#ccc", //水印字体颜色
    watermark_alpha: 0.5, //水印透明度
    watermark_fontsize: "15px", //水印字体大小
    watermark_font: "微软雅黑", //水印字体
    watermark_width: 100, //水印宽度
    watermark_height: 100, //水印长度
    watermark_angle: 25, //水印倾斜度数
  };
  //采用配置项替换默认值,作用类似jquery.extend
  if (settings && typeof settings === "object") {
    let src = settings[0] || {};
    for (key in src) {
      if (
        src[key] &&
        defaultSettings[key] &&
        src[key] === defaultSettings[key]
      ) {
        continue;
      } else if (src[key]) {
        defaultSettings[key] = src[key];
      }
    }
  }
  let oTemp = document.createDocumentFragment();

  let maskElement = watermarks.value;
  //获取页面最大宽度
  let page_width = maskElement.offsetWidth;
  //获取页面最大高度
  let page_height = maskElement.offsetHeight;
  //水印数量自适应元素区域尺寸
  defaultSettings.watermark_cols = Math.floor(
    page_width /
      (defaultSettings.watermark_x_space + defaultSettings.watermark_width)
  );
  defaultSettings.watermark_rows = Math.ceil(
    page_height /
      (defaultSettings.watermark_y_space + defaultSettings.watermark_height)
  );
  defaultSettings.watermark_x =
    (page_width -
      defaultSettings.watermark_cols * defaultSettings.watermark_width) /
    4;
  defaultSettings.watermark_y =
    (page_width -
      defaultSettings.watermark_cols * defaultSettings.watermark_width) /
    6;
  let x;
  let y;
  for (let i = 0; i < defaultSettings.watermark_rows; i++) {
    y =
      defaultSettings.watermark_y +
      (defaultSettings.watermark_y_space + defaultSettings.watermark_height) *
        i;
    for (let j = 0; j < defaultSettings.watermark_cols; j++) {
      x =
        defaultSettings.watermark_x +
        (defaultSettings.watermark_width + defaultSettings.watermark_x_space) *
          j;
      if (j % 2 == 0) {
        y += 50;
      } else {
        y -= 50;
      }
      let mask_div = document.createElement("div");
      mask_div.id = "mask_div" + i + j;
      mask_div.className = "mask_div";
      //mask_div.appendChild(document.createTextNode(defaultSettings.watermark_txt));
      mask_div.innerHTML = defaultSettings.watermark_txt;
      //设置水印div倾斜显示
      mask_div.style.webkitTransform =
        "rotate(-" + defaultSettings.watermark_angle + "deg)";
      mask_div.style.MozTransform =
        "rotate(-" + defaultSettings.watermark_angle + "deg)";
      mask_div.style.msTransform =
        "rotate(-" + defaultSettings.watermark_angle + "deg)";
      mask_div.style.OTransform =
        "rotate(-" + defaultSettings.watermark_angle + "deg)";
      mask_div.style.transform =
        "rotate(-" + defaultSettings.watermark_angle + "deg)";
      mask_div.style.visibility = "";
      mask_div.style.position = "absolute";
      mask_div.style.left = x + "px";
      mask_div.style.top = y + "px";
      mask_div.style.overflow = "hidden";
      mask_div.style.zIndex = "1029"; // 9999
      // pointer-events:none  让水印不遮挡页面的点击事件
      mask_div.style.pointerEvents = "none";
      // 设置边框
      // 兼容IE9以下的透明度设置
      mask_div.style.filter = "alpha(opacity=50)";
      mask_div.style.opacity = defaultSettings.watermark_alpha;
      mask_div.style.fontSize = defaultSettings.watermark_fontsize;
      mask_div.style.fontFamily = defaultSettings.watermark_font;
      mask_div.style.color = defaultSettings.watermark_color;
      mask_div.style.textAlign = "center";
      mask_div.style.width = defaultSettings.watermark_width + "px";
      mask_div.style.height = defaultSettings.watermark_height + "px";
      mask_div.style.display = "block";
      oTemp.appendChild(mask_div);
    }
  }
  maskElement.appendChild(oTemp);
};

二、迭代器 ES6 (Symbol.iterator)

iteration 被称为迭代,也可以称为遍历。

根据ES6的定义iteration由3个部分组成:Iterable、Iterator、IteratorResult

1. Iterable

interface Iterable {
    [Symbol.iterator]() : Iterator;
}

Iterable表示的是该对象中有可以遍历的数据,且会生成一个Iterator工厂函数

2.Iterator

interface Iterator {
    next() : IteratorResult;
}

可以从Iterable中构建Iterator。Iterator是一个类似游标的概念,可以通过next访问IteratorResult。

3. IteratorResult

interface IteratorResult {
    value: any;
    done: boolean;
}

IteratorResult是通过调用next()获取到的数据,value是值,done是判断是否遍历完成

示例:
var arr = [1,2,3,4]
var a = arr[Symbol.iterator]()
a.next()  // value:1,done:false
a.next()  // value:2,done:false
a.next()  // value:3,done:false
a.next()  // value:4,done:false
a.next()  // value:undefined,done:true

Iterable对象包含:Arrays、Strings、Maps、Sets、DOMs

1.Arrays

示例:
var arr = [1,2,3,4]
var a = arr[Symbol.iterator]()
a.next()  // value:1,done:false
a.next()  // value:2,done:false
a.next()  // value:3,done:false
a.next()  // value:4,done:false
a.next()  // value:undefined,done:true

更简单的方法使用for...of

for (const x of ['a', 'b']) {
    console.log(x);
}
// Output:
// 'a'
// 'b'

2.Strings(基础类型的String在遍历的时候,会自动转换成为String对象)

var a = 'avcbfa'[Symbol.iterator]()
undefined
a.next()
{value: 'a', done: false}
a.next()
{value: 'v', done: false}
a.next()
{value: 'c', done: false}
a.next()
{value: 'b', done: false}
a.next()
{value: 'f', done: false}
a.next()
{value: 'a', done: false}
a.next()
{value: undefined, done: true}
a.next()
{value: undefined, done: true}

3.Maps

Maps是通过遍历entries来实现的

const map = new Map().set('a', 1).set('b', 2);
for (const pair of map) {
    console.log(pair);
}
// Output:
// ['a', 1]
// ['b', 2]

JS中对于Map通常需要维护两个数组, 第一个数组存储着key,另一个数组存储着value,每次添加和删除item时,需要同时操作两个数组,导致其存在2个缺点。

(1)每次查找Map中的元素时,都需要先去遍历key数组中拿到index,再去第二个数组中通过index来查找到对应的value

(2)Map中key和value是强绑定的,即使不在使用也不会被垃圾回收机制回收。

根据以上两个缺陷引入了weakMap的概念。

weakMap中key和value并不是强绑定关系,key不在使用时就会被垃圾回收机制回收。但是weakMap并不支持key的遍历仅有增删改的功能

4.Sets

const set = new Set().add('a').add('b');
for (const x of set) {
    console.log(x);
}
// Output:
// 'a'
// 'b'

也可以遍历arguments对象,也可以遍历大部分DOM对象

function printArgs() {
    for (const x of arguments) {
        console.log(x);
    }
}
printArgs('a', 'b');

// Output:
// 'a'
// 'b'
for (const node of document.querySelectorAll('div')) {
    ···
}

5. 普通对象是不可遍历的

在JS中,Array、Map、Set是普通对象中的一种特例(可遍历对象),在普通对象中是不存在Symbol.iterator这个属性所以是不可以遍历的

for (const x of {}) { // TypeError
    console.log(x);
}

虽然不能直接遍历普通对象,但是我们可以通过使用objectEntries方法来遍历普通对象。

// objectEntries的实现方法
function objectEntries(obj) {
    let iter = Reflect.ownKeys(obj)[Symbol.iterator]()
    
    return {
        [Symbol.iterator]() {
            return this
        },
        next() {
            let {done, value:key} = iter.next();
            if (done) {
                return { done: true };
            }
            return { value: [key, obj[key]] };
        }
    }
}

以下是具体的使用,也可以通过类似方法获取key,value

const obj = { first: 'Jane', last: 'Doe' };

for (const [key,value] of objectEntries(obj)) {
    console.log(`{key}:{value}`);
}

// Output:
// first: Jane
// last: Doe

6.自定义iterables

function iterateOver(...args) {
    let index = 0;
    const iterable = {
        [Symbol.iterator]() {
            const iterator = {
                next() {
                    if (index < args.length) {
                        return { value: args[index++] };
                    } else {
                        return { done: true };
                    }
                }
            };
            return iterator;
        }
    }
    return iterable;
}
iterateOver方法会返回一个iterable对象。在这个对象中,我们实现了Symbol.iterator为key的方法。这个方法返回一个iterator,在iterator中,我们实现了next方法。
// Using `iterateOver()`:
for (const x of iterateOver('fee', 'fi', 'fo', 'fum')) {
    console.log(x);
}

// Output:
// fee
// fi
// fo
// fum
如果Symbol.iterator返回的对象是iterable本身,那么iterable也是一个iterator。
function iterateOver(...args) {
    let index = 0;
    const iterable = {
        [Symbol.iterator]() {
            return this;
        },
        next() {
            if (index < args.length) {
                return { value: args[index++] };
            } else {
                return { done: true };
            }
        },
    };
    return iterable;
}
这样做的好处就是,我们可以使用for-of同时遍历iterables和iterators,如下所示:
const arr = ['a', 'b'];
const iterator = arr[Symbol.iterator]();

for (const x of iterator) {
    console.log(x); // a
    break;
}

// Continue with same iterator:
for (const x of iterator) {
    console.log(x); // b
}

8.关闭iterators

通过实现return方法,我们可以在程序中断的时候(break,return,throw)调用iterators的return。
function createIterable() {
    let done = false;
    const iterable = {
        [Symbol.iterator]() {
            return this;
        },
        next() {
            if (!done) {
                done = true;
                return { done: false, value: 'a' };
            } else {
                return { done: true, value: undefined };
            }
        },
        return() {
            console.log('return() was called!');
        },
    };
    return iterable;
}
for (const x of createIterable()) {
    console.log(x);
    break;
}
// Output:
// a
// return() was called!
、通过break来中断遍历,最终导致return方法的调用

你可能感兴趣的:(前端集合,学习,javascript,前端)