JS 如何创建对象?

thbcm阅读(390)

一、new Object();

 var x="age"

        var obj=new Object();
        obj.name="wang";
        obj.x=20; //.字符串
        obj[x]=25; //[变量]
        console.log(obj);//{name: "wang", x: 20, age: 25}

二、字面量

 var a="hobby"
        var obj={"name":"wang","age":"18"};

            obj.sex="男";
            obj[a]="唱歌";
            obj.say=function(){
            }
            console.log(obj);//{name: "wang", age: "18", sex: "男", hobby: "唱歌", say: ƒ}
            var obj2={"aa bb":"hellow",".x":"world"};
            console.log(obj2["aa bb"]);//hellow
            console.log( obj2[".x"] );//world

三、工厂模式;

 //1.创建函数
        function a(name, age) {
            var obj = {
                "name": "wang",
                "age": 19,
                "say": function () {
                }
            }
            return obj
        }
        //2.依次调用
        var obj1 = a("wang", 20);
        console.log(obj1);//{name: "wang", age: 19, say: ƒ}
        console.log(obj1 instanceof Object);//true

            //优点:返回新对象,互不影响
            //缺点:代码重复(方法相同)。
            //  没有从属关系,

四、构造函数

 //四、构造函数;
        //优点:有从属
        //缺点:代码重复(相同方法);
         //   1.创建函数
         //2.传入参数
        function A(name,age){
            //3.this。属性名=值
            this.name=name;
            this.age=age;
            this.say=function(){
            }
        }
        //调用 : var obj=new 构造函数(参数)
        
        var obj= new A("wang",19);
        console.log(obj);
        console.log( obj instanceof Object );//true
        console.log( obj instanceof A );//true

五、原型模式

 //原型优点:共同/相同的属性、方法不重复 有从属关系
        //缺点:原型上的属性不可单独改变
        function Fn(){
            
        }
        Fn.prototype.name="王";
        Fn.prototype.age=19;

        var obj=new Fn();
        console.log(obj);
        /*
        修改obj.__proto__.name
        obj.__proto__.name 发生变化
        obj2.__proto__.name 也发生变化
        obj和obj1 共用__proto__对象
        公共/相同的属性、方法放在构造函数.prototype上 实现代码不重复
        */
            obj.__proto__.name="李"
            console.log( obj.__proto__.name  );

            var obj2=new Fn();
            console.log(obj2);
            console.log(obj.__proto__.name);

推荐好课:

小白学前端:JavaScript零基础入门到进阶(2020版)

JavaScript实战:动态网站开发

JavaScript交互式网站实战开发

软件测试–mocha入门

thbcm阅读(379)

什么是TDD:

TDD:Test driven devlement,测试驱动开发,是敏捷开发中的一项核心实践和技术,也是一种设计方法论。TDD的原理是在开发功能代码之前,先编写单元测试用例代码,测试代码确定需要编写什么产品代码。

什么是mocha:

mocha是JavaScript的一种单元测试框架,既可以在浏览器环境下运行,也可以在Node.js环境下运行。

安装mocha:

1.创建一个工程。

2.运行:

#初始化
npm init
#安装mocha
npm i mocha chai -D

此时目录结构为:

编写业务代码:

编写math.js用于模拟业务代码

function add(x,y){
    return x+y;
}

function multiply (x,y){
    return x*y;
}

module.exports={
    add,multiply 
}

编写测试代码:

//导入刚刚写的math.js
var math=require("../math");
//导入断言
var assert= require("assert");
// 描述测试文件
describe('测试math.js',function(){
    // 描述测试的方法
    describe('测试方法add',function(){
        // mocha提供了it方法,称为测试用例,表示一个单独的测试
        // 我们可以写某个方法的多个测试用例来测试不同情况下的状况
        // 测试10+1;
        it('10+1',function(){
            // 断言10+1=11
            assert.equal(math.add(10,1),11);
        });
        // 测试不通过
        // 测试10+2;断言10+2=9
        it("10+2",function(){
            assert.equal(math.add(10,2),9)
        })
    });
    describe("测试方法multiply",function(){
        // 测试5*2
        it('5-2',function(){
            // 断言5*2=10
            assert.equal(math.multiply(5,2),10);
        })
    });
})

配置package.json:

直接使用mocha测试显示在终端

"scripts": {
    "test": "mocha"
  }

运行测试:

npm test

结果:

推荐好课:

Vue.js三天学习实战教程

JavaScript实战:动态网站开发

Javascript移动端App实战开发

Node.js微课

软件测试教程

Java main方法中的String[] args详解

thbcm阅读(380)

在每一个学习Java的同学,都应该写过下面的这一段代码。

public class Hello{
	public static void main(String[] args) {
		System.out.println("Hello,World!");
	}
}

在Java语言中,规定了入口函数是一个main()方法,该方法有一个String[]类型的参数,但是在很多时候,很多人都使用不上这个参数,也不关心为什么要写这个参数。

那么这个字符串数组类型的参数究竟是什么东西呢?

其实很简单,main()方法中的字符串数组类型的参数就是java命令的参数,使用java命令的方式运行main()方法,会将java命令的参数入参到Java main()方法的字符串数组参数中。

我们可以通过以下方式来进行验证:

  • 1、先编写一个Hello.java文件,文件内容如下:
public class Hello{
	public static void main(String[] args) {
		System.out.println("==============args start============");
		for(int i = 0; i < args.length; i++) {
			System.out.println(args[i]);
		}
		System.out.println("==============args end============");
	}
}
  • 2、在Hello.java文件的路径下打开cmd命令提示符,运行javac Hello.java命令编译该文件,这将会在对应的文件路径下,得到一个Hello.class字节码文件。
  • 3、使用java Hello命令运行Hello.class文件,我们将会得到如下的运行结果:
  • 4、我们这次在java命令后面添加一些参数,这些参数我们可以自己定义。例如:java Hello a b c d ,我们将会得到如下的运行结果:

正是因为Java main()方法的这个扩展性,使得每一个开发者,可以通过自己定义一些Java命令的参数,实现一些不同的功能。

其中SpringBoot的启动类,其实也使用了这个特性,SpringApplication.run()方法有一个重载方法,其中第一个入参的是注解了@SpringBootApplication注解的类的字节码对象,而第二个参数,即为main()方法的字符串数组参数。

SpringBoot可以通过这个字符串数组参数,通过java命令参数的方式,在不同的环境下实现不同的应用配置。

@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

推荐好课:

Java:23天零基础完全入门

Java开发实例:坦克大战游戏

Java基本数据类型,看这一篇就够了!

thbcm阅读(394)

相信学过Java的小伙伴们都知道,Java是强类型语言,所以Java对于数据类型的规范会相对严格。

它提供了八种基本类型(这里不讲解Void)。其中六种数字类型(四个整数型(默认是int 型),两个浮点型(默认是double 型)),一种字符类型,还有一种布尔型。

基础

我们先来一点干货!!

基本数据类型 大小 值域 默认值 包装器类型
boolean – true,false false Boolean
char 16 bit [0,216-1] ‘\u0000’ Character
byte 8 bit [-128,127] 0 Byte
short 16 bit [-215,215-1] 0 Short
int 32 bit [-231,231-1] 0 Integer
long 64 bit [-263,263-1] 0L Long
float 32 bit [-3.4E38,3.4E38] 0.0F Float
double 64 bit [-1.8E308,1.8E308] 0.0D Double

如果掌握了这些要点,那说明基础是不错的,有兴趣的话可以随小编再深入了解一下!!

深入

数据类型在计算机语言里面,是对程序所处理数据的抽象,它存在的意义是为了方便虚拟机为不同的数据分配更合适的空间。所以,对数据类型的理解自然与虚拟机分不开。

在 Java 虚拟机规范中,boolean 类型则被映射成 int 类型。具体来说,“true”被映射为整数 1,而“false”被映射为整数 0。这个编码规则约束了 Java 字节码的具体实现。

Java 虚拟机规范同时也要求 Java 编译器遵守这个编码规则,并且用整数相关的字节码来实现逻辑运算,以及基于 boolean 类型的条件跳转。这样一来,在编译而成的 class 文件中,除了字段和传入参数外,基本看不出 boolean 类型的痕迹了。

Java 的基本类型都有对应的值域和默认值。

可以看到,byte、short、int、long、float 以及 double 的值域依次扩大,而且前面的值域被后面的值域所包含。因此,从前面的基本类型转换至后面的基本类型,无需强制转换。另外一点值得注意的是,尽管他们的默认值看起来不一样,但在内存中都是 0。

在这些基本类型中,boolean 和 char 是唯二的无符号类型。boolean 类型的取值范围是 0 或者 1,char 类型的取值范围则是 [0, 65535]。通常我们可以认定 char 类型的值为非负数,这种特性十分有用,比如说作为数组索引等。

数据存储

Java 虚拟机每调用一个 Java 方法,便会创建一个栈帧。这种栈帧有两个主要的组成部分,分别是局部变量区,以及字节码的操作数栈。

在 Java 虚拟机规范中,局部变量区等价于一个数组,并且可以用正整数作为索引。除了 long、double 值需要用两个数组单元来存储之外,其他基本类型以及引用类型的值均占用一个数组单元。也就是说,boolean、byte、char、short 这四种类型,在栈上占用的空间和 int 是一样的,和引用类型也是一样的。

因此,当我们将一个 int 类型的值,存储到这些类型的字段或数组时,相当于做了一次隐式的掩码操作。举例来说,当我们把 0xFFFFFFFF(-1)存储到一个声明为 char 类型的字段里时,由于该字段仅占两字节,所以高两位的字节便会被截取掉,最终存入“\uFFFF”。

数据加载

Java 虚拟机的算数运算几乎全部依赖于操作数栈。也就是说,我们需要将堆中的 boolean、byte、char 以及 short 加载到操作数栈上,而后将栈上的值当成 int 类型来运算。

对于 boolean、char 这两个无符号类型来说,加载伴随着零扩展。举例来说,char 的大小为两个字节,在加载时 char 的值会被复制到 int 类型的低二字节,而高二字节则会用 0 来填充。

对于 byte、short 这两个类型来说,加载伴随着符号扩展。举个例子,short 的大小为两个字节。在加载时 short 的值同样会被复制到 int 类型的低二字节。如果该 short 值为非负数,即最高位为 0,那么该 int 类型的值的高二字节会用 0 来填充,否则用 1 来填充。

小结

基础知识要掌握好,底层实现也需要有一定的认识。了解虚拟机,有助于理解Java语言的一些性质,也有助于使用Java语言。

推荐阅读:

Java:23天零基础完全入门

深入解析Java面向对象

Java8编程开发入门

python 五种常见的测试框架

thbcm阅读(382)

一. unittest

unittest 和 JUnit类似,可以说是python的标准单元测试框架,所以有时也被人称为 PyUnit。它使用起来和xUnit 家族其他成员类似。 用的人也比较多。兼容 python2 以及python3 。

个人比较喜欢用这个,主要之前用过JUnit,用这个上手就很快。而且属于python自动集成,不用额外的安装包,感觉是该有的都有了,用着方便。

官网示例:

按 Ctrl+C 复制代码

import unittest

class TestStringMethods(unittest.TestCase):

def test_upper(self): self.assertEqual(‘foo’.upper(), ‘FOO’)

def test_isupper(self): self.assertTrue(‘FOO’.isupper()) self.assertFalse(‘Foo’.isupper())

def test_split(self): s = ‘hello world’ self.assertEqual(s.split(), [‘hello’, ‘world’]) # check that s.split fails when the separator is not a string with self.assertRaises(TypeError): s.split(2)

if name == ‘main’: unittest.main()

二. unittest2

unittest2 可以说是一个针对 unittest 测试框架新特性的补丁。它很大程度上和 unittest 都类似。然后还添加了一些 unittest 没有的方法。

三. pytest

看了一下,pytest 文档还是蛮详细的。比较关注的一点是,pytest 直接可以通过 @pytest.mark.parametrize 进行参数化,而 unittest 则需要借助 DDT。

官网示例:

# content of test_sample.py
def inc(x):
  return x + 1
​
def test_answer():
  assert inc(3) == 5

执行如下:

$ pytest
======= test session starts ========
platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
rootdir: $REGENDOC_TMPDIR, inifile:
collected 1 item
​
test_sample.py F
​
======= FAILURES ========
_______ test_answer ________
​
  def test_answer():
>       assert inc(3) == 5
E       assert 4 == 5
E       + where 4 = inc(3)
​
test_sample.py:5: AssertionError
======= 1 failed in 0.12 seconds ========

四. nose

nose 扩展了 unittest,从而使得测试更容易。

一般可以用 unittest 方式写用例,写完之后用 nose 来执行。nose 的测试收集方式还是很方便的。

还有一个特定就是,nose 可以采用 @with_setup() 来定义方法的 setup 和 teardown。

官方示例:

def setup_func():
  "set up test fixtures"
​
def teardown_func():
  "tear down test fixtures"
​
@with_setup(setup_func, teardown_func)
def test():
  "test ..."

五. doctest

doctest 模块会搜索那些看起来像交互式会话的 Python 代码片段,然后尝试执行并验证结果。

doctest 中,如果要写测试用例,只需要在写在以 ”’ ”’包围的文档注释即可,也就是可以被 doc 这个属性引用到的地方。这点比较特别,跟其他单元测试框架都不一样。但是我觉得这样的话就注定了 doctest 不适合大型测试,因为做不到代码和测试的分离。

import doctest
​
"""
This is the "example" module.
​
The example module supplies one function, factorial(). For example,
​
>>> factorial(5)
120
"""
​
def factorial(n):
  """Return the factorial of n, an exact integer >= 0.
​
  >>> [factorial(n) for n in range(6)]
  [1, 1, 2, 6, 24, 120]
  >>> factorial(30)
  265252859812191058636308480000000
  >>> factorial(-1)
  Traceback (most recent call last):
      ...
  ValueError: n must be >= 0
​
  Factorials of floats are OK, but the float must be an exact integer:
  >>> factorial(30.1)
  Traceback (most recent call last):
      ...
  ValueError: n must be exact integer
  >>> factorial(30.0)
  265252859812191058636308480000000
​
  It must also not be ridiculously large:
  >>> factorial(1e100)
  Traceback (most recent call last):
      ...
  OverflowError: n too large
  """
​
  import math
  if not n >= 0:
      raise ValueError("n must be >= 0")
  if math.floor(n) != n:
      raise ValueError("n must be exact integer")
  if n+1 == n: # catch a value like 1e300
      raise OverflowError("n too large")
  result = 1
  factor = 2
  while factor <= n:
      result *= factor
      factor += 1
  return result
​
​
if __name__ == "__main__":
  doctest.testmod(verbose=True)

verbose 参数用于控制是否输出详细信息,默认为 False ,如果不写,那么运行时不会输出任何东西,除非测试 fail。

输出如下:

Trying:
  [factorial(n) for n in range(6)]
Expecting:
  [1, 1, 2, 6, 24, 120]
ok
Trying:
  factorial(30)
Expecting:
  265252859812191058636308480000000
ok
Trying:
  factorial(-1)
Expecting:
  Traceback (most recent call last):
      ...
  ValueError: n must be >= 0
ok
Trying:
  factorial(30.1)
Expecting:
  Traceback (most recent call last):
      ...
  ValueError: n must be exact integer
ok
Trying:
  factorial(30.0)
Expecting:
  265252859812191058636308480000000
ok
Trying:
  factorial(1e100)
Expecting:
  Traceback (most recent call last):
      ...
  OverflowError: n too large
ok
1 items had no tests:
  __main__
1 items passed all tests:
  6 tests in __main__.factorial
6 tests in 2 items.
6 passed and 0 failed.
Test passed.

推荐好课:python3入门、python3进阶

JQuery的增加元素,删除元素

thbcm阅读(387)

JQuery的增加元素,删除元素

1. jQuery创建元素方法

let div = $('<div>elm</div>');

$(‘<div>elm</div>’)可以创建一个div元素,并内容为elm

2.添加元素

2.1.内部添加 append(),prepend()方法

<ul>
   <li>原有的</li>
</ul>
<script>
   $(function() {
       let li = $('<li>后加的</li>');
       $('ul').append(li);
  });
</script>

append()方法会把元素添加到匹配元素最后面,类似原生JS里的appendChild()

<ul>
  <li>原有的</li>
</ul>
<script>
  $(function() {
      let li = $('<li>后加的</li>');
      $('ul').prepend(li);
  });
</script>

prepend()方法会把元素添加到匹配元素最前面,类似原生JS里的insertBefore()

内部添加元素后,生成的是父子关系

2.2.外部添加 before(),after()方法

原来的    $(function() {        let div = $(‘ 添加的 ‘);        $(‘div’).before(div);   })

before()方法会把元素添加在匹配元素前面

<div>原来的</div>
<script>
   $(function() {
       let div = $('<div>添加的</div>');
       $('div').after(div);
  })
</script>

after()方法会把元素添加在匹配元素后面

外部添加元素,生成的是兄弟关系

2.删除元素

1.remove()

<ul>
   <li></li>
</ul>
<script>
   $(function() {
       $('ul').remove();
  })
</script>

remove()会删除ul元素,包括子节点

2.empty()

<ul>
   <li></li>
</ul>
<script>
   $(function() {
       $('ul').empty();
  })
</script>

empty()清空ul节点内的所有子节点,但会保留ul自身节点

3.html(“”)

html(“”)方法作用于empty()基本一致

推荐好课:jquery微课、jquery入门

DOM操作_获取元素

thbcm阅读(379)

概述

DOM (Document objectModal) :文档对象模型。

DOM:是浏览器提供的(浏览器特有),专门用来操作网页内容的一些JS对象。

目的:让我们可以使用 Js/TS 代码来操作页面(HTML) 内容,让页面“动”起来,从而实现 Web 开发。

HTML:超文本标记语言,用来创建网页结构。

两者的关系:浏览器根据 HTML 内容创建相应的 DOM 对象,也就是:每个 HTML 标签都有对应的 DOM 对象

获取元素

常用方法有两个:

querySelector (selector)作用:获取某一个DOM元素。

queryseletor (selectocu)作用:同时获取多个D0M元素。

获取一个DOM元素:

document. querySelector (selector) document 对象:文档对象(整个页面),是操作页面内容的入口对象。 selector 参数:是一个 css 选择器(标签、类、id 选择器等)。 作用:查询(获取)与选择器参数匹配的 DOM 元素,但是,只能获取到第一个 推荐使用id选择器,例如

获取html中id为title的标签内容并在控制台输出:
let title = document.querySelector('#title')
console.log(title)

结果如下

调用 querySelector ()通过id选择器获取 DOM 元素时,拿到的元素类型都是 Element. 因为无法根据id来确定元素的类型,所以,该方法就返回了一个宽泛的类型:元素(Element) 类型。 不管是 h1 还是 img 都是元素。 导致新问题:无法访问 img 元素的 src 属性了。 因为: Element 类型只包含所有元素共有的属性和方法(比如: id 属性)。

解决方式:使用类型断言,来手动指定更加具体的类型(比如,此处应该比 Element 类型更加具体)。 比如: 解释:我们确定 id=” image”的元素是图片元素,所以,我们将类型指定为 HTML ImageElement。

let img1 = document.querySelector('#img1') as HTMLImageElement
​
img1.src = './img/4.jpg'
如何知道元素的属性?

技巧:通过 console.dir()打印 DOM 元素,在属性的最后面,即可看到该元素的类型。

let img1 = document.querySelector('#img1') as HTMLImageElement
​
img1.src = './img/4.jpg'
​
console.dir(img1)

获取多个 DOM元素:

document . querySelectorAll (selector) 作用:获取所有与选择器参数匹配的 DOM 元素,返回值是一个列表。 推荐:使用 class 选择器。 示例: let、list = document . querySelectorAll(’.a’) 解释:获取页面中所有 class 属性包含 a 的元素。

html中的内容如下
<p id='title'>欢迎来到海南大学</p>
   <p class = ' a'>2020年时多灾多难的一年</p>
   <p class="b a">2021年将牛气冲天</p>
   <img id = 'img1'src="./img/1.jpg" alt="">
   <script src = './index.js'></script>
ts 中的内容如下
let list = document.querySelectorAll('.a')
​
console.log(list)
运行结果如下

操作文本内容

读取: dom. innerText 设置: dom. innerText = ’ 等你下课’ 注意:需要通过类型断言来指定 DOM 元素的具体类型,才可以使用innerText 属性。 例如

let title = document.querySelector('#title') as HTMLParagraphElement
console.log(title.innerHTML)

追加内容如下操作

let title = document.querySelector('#title') as HTMLParagraphElement
title.innerHTML = title.innerHTML + ' 阳光沙滩美女'
console.log(title.innerHTML)
给所有p标签的内容加上索引
let list = document.querySelectorAll('.a') 
​
list.forEach(function (item,index) {
   let p = item as HTMLParagraphElement
   p.innerHTML = '['+index+']'+p.innerHTML
})

输出结果如下:

如何进行数据埋点?

thbcm阅读(391)

埋点一种良好的私有化部署数据采集方式, 当然,本文主要是针对代码埋点的方式进行讲解。

1.明确埋点目的

通俗点讲,就是说到底我们需要去看哪些数据,比如是要看某篇文章分享的是不是够多,或者点了付款单付款成功人数的比例有多少,一般可以大致分为三类:用户基本数据、功能使用数据、综合数据。

2. 梳理业务流程

梳理业务流程,其实并不是必须的,只是针对一些比较复杂的用户操作流程而言,是需要特别注意,因为有一些是需要通过多个步骤计算得到一个百分比,比如用户的下单流程,大致需要经过注册->登录->浏览列表->访问详情->立即购买->确认订单->付款,那这就涉及到在每个环节上用户的流失情况,从而可以推断出最终的付款转化情况。

而有一些埋点目的相对比较单纯简单,就是想对比下多个入口的受欢迎程度,那么就直接在各个入口埋点即可,因为不涉及到什么流程,只是需要统计它们的点击次数即可。

3.定义埋点事件

作为产品来说,我们需要定义事件的id、事件名称,事件id是需要开发工程师写到代码里面的英文字段,事件名称则是为了自己能明白埋的到底是啥的,还需要跟英文字段对应的一个名称,而对于有的平台比如友盟还需要去定义事件类型,它可以定义成多参数类型事件或者计算事件。

那除了上面这些在埋点的第三方平台上必须要去提交的参数外,为了让产品自己能够在过了很久以后,或者其他同事能够知道之前某个埋点到底是代表什么意思,一般我们还会去整理某个埋点对应的是哪个功能模块,以及简单的描述某个埋点的说明,可以用Excel表格进行整理,大概可以如下:

4.进行数据采集

在产出了上面的埋点需求表格以后,就把这个表格给开发工程师就可以了,当然在这之前,还需要把对应的事件录入到数据统计的平台上,以确保我们能够正常的看到数据,比如友盟平台就是在事件管理里去进行事件的添加,然后去填写事件 id、事件名称并选择事件的类型,当然也可以用批量添加的方式,具体模板不同平台略有差异,需要添加的时候去各个平台上查看即可。

另外一个目的就是想要监控用户开通会员的入口来源,所以我们在有开通会员的入口位置加上了相应的埋点,命名为clickOpen,同时给这个事件加上了参数也就是上图的属性fromPage,并指定了来源一个是Banner,一个是首页弹出的Dialog。

5. 添加埋点

所以整理完上面的埋点需求以后,我们就把对应的事件添加到了友盟的后台(可以选择批量添加多个或者手动单个去添加,下图是单个添加的截图),同时把上面的需求交给了开发工程师去进行埋点。

原生js中用DOM操作table以及表格搜索功能

thbcm阅读(348)

DOM中table的便捷操作

tBobies(数组) tHead tFoot rows(行) cells(单元格)

<body>
  <table border="1" id="table1" width="500">
      <thead>
           <tr>
              <td>ID</td>
               <td>姓名</td>
               <td>年龄</td>
           </tr>
       </thead>
       <tbody>
           <tr>
               <td>1</td>
               <td>张三</td>
              <td>23</td>
           </tr>
       </tbody>
  </table>
   <script>
       window.onload = function () {
           var oTable = document.getElementById('table1')
   alert(oTable.getElementsByTagName('tbody')[0].getElementsByTagName('tr')[0].getElementsByTagName('td')[1].innerHTML)
           alert(oTable.tBodies[0].rows[0].cells[1].innerHTML)
      }
   </script>
</body>

隔行变色、高亮

<body>
   <table border="1" id="table1" width="500">
       <thead>
           <tr>
              <td>ID</td>
              <td>姓名</td>
               <td>年龄</td>
          </tr>
      </thead>
      <tbody>
           <tr>
              <td>1</td>
              <td>张三</td>
               <td>23</td>
           </tr>
           <tr>
               <td>2</td>
               <td>里斯</td>
               <td>24</td>
           </tr>
           <tr>
              <td>3</td>
               <td>王武</td>
               <td>25</td>
           </tr>
       </tbody>
   </table>
   <script>
       window.onload = function () {
           var oTable = document.getElementById('table1');
           var oldColor = '' //原来的背景颜色
           alert(oTable.tBodies[0].rows.length)
           for(var i = 0; i < oTable.tBodies[0].rows.length; i++){
               oTable.tBodies[0].rows[i].onmouseover = function(){
                   oldColor = this.style.background; //将原来的背景颜色保存起来
                   this.style.background = 'yellow'
              }
               oTable.tBodies[0].rows[i].onmouseout = function(){
                   this.style.background = oldColor
              }
               if(i % 2){ // i%2为0时,条件为假
                   oTable.tBodies[0].rows[i].style.background = "#999"
              }else{
                   oTable.tBodies[0].rows[i].style.background = ""
              }
          }
      }
   </script>
</body>

添加行、删除行

<body>
   <input type="text" id="name">
   <input type="text" id="age">
   <input type="button" id="btn" value="添加">
   <table border="1" id="table1" width="500">
       <thead>
           <tr>
               <td>ID</td>
               <td>姓名</td>
               <td>年龄</td>
               <td>操作</td>
           </tr>
       </thead>
       <tbody></tbody>
   </table>
   <script>
       window.onload = function () {
           var oTable = document.getElementById('table1'); //获取table
           var oName = document.getElementById('name') //获取姓名文本框
           var oAge = document.getElementById('age') //获取年龄文本框
           var oBtn = document.getElementById('btn') //获取添加按钮
           var id = oTable.tBodies[0].rows.length + 1; //将 id 的值作为全局变量保存,避免 id 重复
           oBtn.onclick = function () {  
               var oTr = document.createElement('tr') //创建 tr 元素
              oTr.innerHTML = '<td>' + (id++) + '</td><td>' + oName.value + //给 tr 赋值
                  '</td><td>' +
                   oAge.value + '</td><td><a href="javascript:;">删除</a></td>'
               oTr.getElementsByTagName('a')[0].onclick = function () {  // 给删除按钮设置点击时间
                   oTable.tBodies[0].removeChild(this.parentNode.parentNode)
              }
               oTable.tBodies[0].appendChild(oTr)
          }
      }
   </script>
</body>

表格搜索、忽略大小写、模糊查询

DOM中table的便捷操作

tBobies(数组) tHead tFoot rows(行) cells(单元格)

<body>
  <table border="1" id="table1" width="500">
      <thead>
           <tr>
              <td>ID</td>
               <td>姓名</td>
               <td>年龄</td>
           </tr>
       </thead>
       <tbody>
           <tr>
               <td>1</td>
               <td>张三</td>
              <td>23</td>
           </tr>
       </tbody>
  </table>
   <script>
       window.onload = function () {
           var oTable = document.getElementById('table1')
   alert(oTable.getElementsByTagName('tbody')[0].getElementsByTagName('tr')[0].getElementsByTagName('td')[1].innerHTML)
           alert(oTable.tBodies[0].rows[0].cells[1].innerHTML)
      }
   </script>
</body>

隔行变色、高亮

<body>
   <table border="1" id="table1" width="500">
       <thead>
           <tr>
              <td>ID</td>
              <td>姓名</td>
               <td>年龄</td>
          </tr>
      </thead>
      <tbody>
           <tr>
              <td>1</td>
              <td>张三</td>
               <td>23</td>
           </tr>
           <tr>
               <td>2</td>
               <td>里斯</td>
               <td>24</td>
           </tr>
           <tr>
              <td>3</td>
               <td>王武</td>
               <td>25</td>
           </tr>
       </tbody>
   </table>
   <script>
       window.onload = function () {
           var oTable = document.getElementById('table1');
           var oldColor = '' //原来的背景颜色
           alert(oTable.tBodies[0].rows.length)
           for(var i = 0; i < oTable.tBodies[0].rows.length; i++){
               oTable.tBodies[0].rows[i].onmouseover = function(){
                   oldColor = this.style.background; //将原来的背景颜色保存起来
                   this.style.background = 'yellow'
              }
               oTable.tBodies[0].rows[i].onmouseout = function(){
                   this.style.background = oldColor
              }
               if(i % 2){ // i%2为0时,条件为假
                   oTable.tBodies[0].rows[i].style.background = "#999"
              }else{
                   oTable.tBodies[0].rows[i].style.background = ""
              }
          }
      }
   </script>
</body>

添加行、删除行

<body>
   <input type="text" id="name">
   <input type="text" id="age">
   <input type="button" id="btn" value="添加">
   <table border="1" id="table1" width="500">
       <thead>
           <tr>
               <td>ID</td>
               <td>姓名</td>
               <td>年龄</td>
               <td>操作</td>
           </tr>
       </thead>
       <tbody></tbody>
   </table>
   <script>
       window.onload = function () {
           var oTable = document.getElementById('table1'); //获取table
           var oName = document.getElementById('name') //获取姓名文本框
           var oAge = document.getElementById('age') //获取年龄文本框
           var oBtn = document.getElementById('btn') //获取添加按钮
           var id = oTable.tBodies[0].rows.length + 1; //将 id 的值作为全局变量保存,避免 id 重复
           oBtn.onclick = function () {  
               var oTr = document.createElement('tr') //创建 tr 元素
              oTr.innerHTML = '<td>' + (id++) + '</td><td>' + oName.value + //给 tr 赋值
                  '</td><td>' +
                   oAge.value + '</td><td><a href="javascript:;">删除</a></td>'
               oTr.getElementsByTagName('a')[0].onclick = function () {  // 给删除按钮设置点击时间
                   oTable.tBodies[0].removeChild(this.parentNode.parentNode)
              }
               oTable.tBodies[0].appendChild(oTr)
          }
      }
   </script>
</body>

表格搜索、忽略大小写、模糊查询

<body>
  姓名:<input type="text" id="name"><input type="button" value="搜索" id="btn">
   <table border="1" id="table1" width="500">
       <thead>
           <tr>
               <td>ID</td>
               <td>姓名</td>
               <td>年龄</td>
           </tr>
       </thead>
       <tbody>
           <tr>
               <td>1</td>
               <td>张三</td>
               <td>23</td>
           </tr>
           <tr>
               <td>2</td>
               <td>里斯</td>
               <td>24</td>
           </tr>
       </tbody>
   </table>
   <script>
       window.onload = function () {
           var oTable = document.getElementById('table1');
           var oName = document.getElementById('name')
           var oBtn = document.getElementById('btn')
           oBtn.onclick = function()
          {
       for(var i = 0; i < oTable.tBodies[0].rows.length; i++){ //循环每一行
       var oTd = oTable.tBodies[0].rows[i].cells[1].innerHTML.toLowerCase()
                   var oInp = oName.value.toLowerCase()
//if(oTd == oInp){ //比较每一行的第二列和文本行的值是否相等//if(oInp.toLowerCase() == oTd.toLowerCase()){ //将值先转成小写,再进行比较, 或者全部转成大写 toUpperCase()if(oTd.search(oInp) != -1){ //字符串中的search(),如果包含返回字符的位置、不包含返回 -1
         oTable.tBodies[0].rows[i].style.background = 'red'
          }else{
             oTable.tBodies[0].rows[i].style.background = ''
                  }
              }
          }
      }
   </script>
</body>
<body>
  姓名:<input type="text" id="name"><input type="button" value="搜索" id="btn">
   <table border="1" id="table1" width="500">
       <thead>
           <tr>
               <td>ID</td>
               <td>姓名</td>
               <td>年龄</td>
           </tr>
       </thead>
       <tbody>
           <tr>
               <td>1</td>
               <td>张三</td>
               <td>23</td>
           </tr>
           <tr>
               <td>2</td>
               <td>里斯</td>
               <td>24</td>
           </tr>
       </tbody>
   </table>
   <script>
       window.onload = function () {
           var oTable = document.getElementById('table1');
           var oName = document.getElementById('name')
           var oBtn = document.getElementById('btn')
           oBtn.onclick = function()
          {
       for(var i = 0; i < oTable.tBodies[0].rows.length; i++){ //循环每一行
       var oTd = oTable.tBodies[0].rows[i].cells[1].innerHTML.toLowerCase()
                   var oInp = oName.value.toLowerCase()
//if(oTd == oInp){ //比较每一行的第二列和文本行的值是否相等//if(oInp.toLowerCase() == oTd.toLowerCase()){ //将值先转成小写,再进行比较, 或者全部转成大写 toUpperCase()if(oTd.search(oInp) != -1){ //字符串中的search(),如果包含返回字符的位置、不包含返回 -1
         oTable.tBodies[0].rows[i].style.background = 'red'
          }else{
             oTable.tBodies[0].rows[i].style.background = ''
                  }
              }
          }
      }
   </script>
</body>

JavaScript原生实现年份轮播选择效果

thbcm阅读(341)

前言

用 js 实现一个年份轮换选择效果。废话不多说,看图:

一、思路是什么?

  • 布局: 左右箭头使用实体字符 < 和 > 年份5个 span。使用用 flex 布局横向排列。
  • js逻辑:(注:年份数据为 number 数组)a> . 默认展示年份数据前5个。b>. firstIndex 记录要显示的5个年份的起始索引。点击右侧箭头 +1,直到 firstIndex+5 刚好等于年份数组长度,不在递增。点击左侧箭头 -1,直到 firstIndex 为 0,不在递减。初始值为 0。c>.selectedIndex 记录当前点击选中的年份索引。默认显示第一个即 2021。初始值 0。d>.firstIndex 值发生变化,获取 firstIndex,firstIndex+1,firstIndex+2…firstIndex+4 对应的年份,渲染到页面。并且这5个索引中某一个和 selectedIndex 相等,说明选中的年份,刚好在当前页面显示的年份当中。所以,与之相等的 index 对应的 span 添加选中样式,其他4个 span 移除选中样式。
  • css:左右箭头逻辑,默认全部添加可点击样式:firstIndex=0,移除左可点击样式,firstIndex+5=年份数组长度,移除右可点击样式。

二、全部代码

1. html

代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>Title</title>
   <link rel="stylesheet" href="index.css" type="text/css"/>
   <script type="text/javascript" src="echarts.min.js"></script>
   <script type="text/javascript" src="index.js"></script>
</head>
<body>
<div class="container">
​
   <div id="left" class="arrow_left" onclick="clickBefore()" style="cursor:default" unselectable="on" onselectstart="return false;">
       <span><</span>
   </div>
   <div id="wrap" class="wrap">
       <span onclick="selected(this)">1</span>
       <span onclick="selected(this)">2</span>
       <span onclick="selected(this)">3</span>
       <span onclick="selected(this)">4</span>
       <span onclick="selected(this)">5</span>
   </div>
   <div id="right" class="arrow_right arrow_active" onclick="clickNext()" style="cursor:default" unselectable="on" onselectstart="return false;">
       <span>></span>
   </div>
​
</div>
​
<div class="content" id="content">
​
</div>
</body>
</html>

2.js

代码如下:

window.onload = function () {
   /*首次渲染列表*/
   initList(firstIndex);
};
​
let yearArr = [2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021];
yearArr.reverse();
​
/*起始索引*/
let firstIndex = 0;
/*选中索引,默认选中第一个*/
let selectedIndex = 0;
​
​
/**
* 初始化列表
*/
function initList(firstIndex) {
​
   /*渲染页面span列表*/
   let spanList = document.getElementById('wrap').getElementsByTagName('span');
   for (let i = 0; i < spanList.length; i++) {
       let index = firstIndex + i;
       let span = spanList[i];
       span.innerText = yearArr[index];
​
       /*选中样式添加和移除*/
       if (index === selectedIndex) {
           span.classList.add('active');
      } else {
           span.classList.remove('active')
      }
  }
   /*页面内容显示值*/
   document.getElementById('content').innerText = '当前选中年份:' + yearArr[selectedIndex];
}
​
/**
* 下一页
*/
function clickNext(div) {
   if (firstIndex + 5 < yearArr.length) {
       firstIndex = firstIndex + 1;
       initList(firstIndex)
  }
   arrowActive();
}
​
/*
* 上一页
*/
function clickBefore(div) {
   if (firstIndex > 0) {
       firstIndex = firstIndex - 1;
       initList(firstIndex)
  }
   arrowActive();
}
​
/**
* 选中
*/
function selected(span) {
   let value = span.innerText;
   let index = yearArr.findIndex((el) => {
       return el + "" === value;
  })
   selectedIndex = index !== -1 ? index : 0;
   initList(firstIndex);
}
​
/**
* 左右箭头激活
* firstIndex = 0: 右激活 左不
* firstIndex = length-5:左激活 右不
* 其他:全激活
*/
function arrowActive() {
   let left = document.getElementById('left')
   let right = document.getElementById('right')
   left.classList.add('arrow_active');
   right.classList.add('arrow_active');
   if (firstIndex === 0) {
       left.classList.remove('arrow_active');
  } else if (firstIndex === yearArr.length - 5) {
       right.classList.remove('arrow_active');
  }
}

2.css

代码如下:

body{
   margin-top: 80px;
}
.container {
​
   display: flex;
   justify-content: center;
   align-items: center;
   margin: 10px;
}
​
.wrap {
   height: 40px;
   z-index: 1;
   color: black;
   display: flex;
   flex: 1;
   background: rgba(155,226,219,0.5);
   border-radius: 20px;
   margin-left: 20px;
   margin-right: 20px;
}
​
.wrap span {
   flex: 1;
   text-align: center;
   height: 40px;
   line-height: 40px;
   border-radius: 20px;
​
}
​
.active{
   background: #1abc9c;
   color:#fff;
}
​
​
​
.arrow_left {
   left: 10px;
   color: green;
   padding: 0px 14px;
   border-radius: 50%;
   font-size: 30px;
   z-index: 2;
}
​
​
.arrow_right {
   right: 10px;
   color: green;
   padding: 0px 14px;
   border-radius: 50%;
   font-size: 30px;
   z-index: 2;
}
.arrow_active{
   color: blue;
}
​
.content{
   margin-left: 30px;
}

推荐好课:JavaScript微课、ES6微课

联系我们