JS笔记

JSON

import json
# 对象转字符串
str = json.dumps(dict,ensure_ascii=False)

# ensure_ascii=True或不设置
str = json.dumps(dict) # 这时前端拿到的是未解码的数据:{"key1":"\u7528\u6237\u8f93...", ...}

obj = json.loads(str) # 字符串转对象

js

JSON.parse(str) # 字符串转字典
JSON.stringify(dict) # 字典转字符串 

js中:日期格式化

var ss = Date.parse(ar.create_time);
var date = new Date(ss);
p.innerText = ar.user + " " + date.toDateString();

js中变量加 var 是局部变量不加var 是全局变量

jQuery

$(..).prop(属性名)
$(..).prop(属性名, 属性值)

页面错误提示

<span id="errormsg" style="color:red;"></span>
...
#JS
$('#errormsg').text("错误信息") # 在span元素中显示错误信息

数组遍历

for

var name = ['Peter','Stark','Jack'];
// for 循环
for(var i = 0; i < name.length; i++) {
  console.log(name[i]);
}

var name = ['Peter','Stark','Jack'];
// 先缓存 name.length
for(var i = 0, len = name.length; i < len; i++) {
  console.log(name[i]);
}

while

// while 循环
var i = 0;
while (i < name.length) {
  console.log(name[i]);
  i++;
}
//while 逆向遍历
var i = name.length;
while (i--) {
  console.log(name[i]);
}

for in

数组既可遍历对象,也可遍历数组。遍历数组时也会遍历非数字键名,所以不推荐 for..in 遍历数组

var a = [1, 2, 3];
for (var key in a) {
  console.log(a[key]);
}

const object = {
  name: 'Peter',
  age: 12,
  isHuman: true
};
for (let key in object) {
  console.log(key + '---' + object[key]);
}

for of (ES6)

var arr = ['a','b','c'];
for(let item of arr) {
  console.log(item);
}

forEach()

用来遍历数组中的每一项,不影响原数组,性能差
缺陷 你不能使用break语句中断循环,也不能使用return语句返回到外层函数

var arr = [1,2,3,4];
arr.forEach = (function(item) {
  console.log(item);
})

const info = [
  {id: 1000, name: 'zhangsan'},
  {id: 1001, name: 'lisi'},
  {id: 1002, name: 'wangwu'}
]
arr.forEach( function(item) {
  console.log(item.id + '---' + item.name);
})

map()

支持return,相当与原数组克隆了一份,把克隆的每项改变了,不影响原数组

var arr = [1,2,3,4];
arr.map( function(item) {
  return item;
})

var arr = ['a','b','c'];
var newArray = arr.map(x => x);
alert(newArray); // ['a','b''c']

var newArray = arr.map(function (item) {
  return [expression];
})

JS使用make safe字符串

nav.innerHTML = arg.data.pagination_str;

a标签不跳转的三种方法

# 1:onclick时间返回false:
<a href="https://www.baidu.com" onclick="return false">a标签不跳转</a>

# 2:用href伪协议;
 写法一:最常用的方法,也是最周全的方法,void是一个操作符,void(0)返回undefined,地址不发生跳转。
<a href="javaScript:void(0);">a标签不跳转</a>
 写法二:这种写法跟写法一类似,区别只是执行了一条空的js代码。
<a href="javaScript:;">a标签不跳转</a>

# 3、使用(#)
跳转到当前页面顶部,当页面内容较多时,还是会有跳转的感觉。不推荐使用
<a href="#">a标签不跳转</a>

JS代码操作表格行的添加和删除

...
<tbody id='tb'>
  ...

#JS
<script>
  function createRow(data, nid) {
    var tr = document.createElement('tr'); # 创建表格行
    var tdId = document.createElement('td'); # 创建id单元格
    tdId.innerHTML = nid;
    $(tr).append(tdId)

    var tdUser = document.createElement('td'); # 创建User单元格
    tdUser.innerHTML = data.username;
    $(tr).append(tdUser)

    var tdAge = document.createElement('td'); # 创建年龄单元格
    tdAge.innerHTML = data.age;
    $(tr).append(tdAge)

    var tdClass = document.createElement('td'); # 创建班级单元格
    # 找到页面中name=cls_id的select,并从select中找到value=data.cls_id的option,取出这个option的text
    var text = $('select[name="cls_id"]).find('option[value="'+data.cls_id+"']).text()
    tdClass.innerHTML = text;
    $(tr).append(tdClass)
    ...
    # 添加行的删除和编辑按钮
    var tdEdit = '<td style="font-size: 20px;"><a class="glyphicon glyphicon-remove icon"></a><a class="fa fa-pencil-square-o icon"></a></td>';
    $(tr).append(tdEdit)
    
    $('#tb').append(tr) # 将新行添加到表格中
  }      
</script>

删除行

# 给所有表格行的删除按钮添加 class:del—row
<td style="font-size: 20px;">
  <a class="glyphicon glyphicon-remove icon del-row"></a>
  <a class="fa fa-pencil-square-o icon"></a>
</td>
# 绑定删除按钮事件
<script>
  $(function(){
    ...
    bindDel();
    ...
  }
  function bindDel(){
    $('.del-row').click(function(){
      $('#delModal').modal('show');
      // 获得当前行id
      var rowID = $(this).parent().parent().attr('nid');
      // 在模态框里添加了一个id=delNid的input隐藏标签,方便记录和给后台提交删除记录的id
      $('#delNid').val(rowID);
    })
  }
</script>

事件委托

$(‘要绑定标签的上级标签’).on(‘click’, ‘要绑定的标签’, function() {})

# 旧版本
$(‘要绑定标签的上级标签’).delegate(‘要绑定的标签’, ‘click’, function() {})
target定义(英译:目标,目的):
    target 事件属性可返回事件的目标节点(触发该事件的节点),如生成事件的元素、文档或窗口。
语法:
    event.target
    event.target.nodeName   //获取事件触发元素标签name(li,p...)
    event.target.id       //获取事件触发元素id
    event.target.className  //获取事件触发元素classname
    event.target.innerHTML  //获取事件触发元素的内容(li)
    等。。。

jquery:this 与 e.target区别
    this会冒泡。e.target不冒泡就是指向事件触发的dom。
(这里说的this会冒泡,就是指的是会将目标函数点击的事件不自身处理,将事件委托到他的父元素节点上
。例如下面的例子,e.target指的是目标函数)
HTML部分
<ul>
<li><b>Click me!</b></li>
<li class="li">You can also <b>Click me!</b></li>
</ul>
#JS部分
<stript>
	$('li').click(function(e){ //点击的是<b>标签的时候
		console.log($(e.target)); // 返回值指的是<b>
		console.log($(this)); //返回值值的是<li>
	})
</stript>

#正确的事件委托使用方法
<stript>
$('ul').click(function(e){
	if(e.target.className==='li'){//点击元素下面的class为li的元素
		console.log($(e.target))
	}
});
或者
$('ul').on('click',function(e){
	if(e.target.nodeName.toLowerCase() === 'li'){//点击li标签的时候出发。注意:点击li里面的元素也是不行的,必须点击li标签
		console.log('123')
	}
});
</stript>

原理
三种写法

# 1、用on方法
$(function(){
  $("#lists").on("click","li",function(event){
    var target = $(event.target);
    target.css("background-color","red");
  })
})
# 2.用delegate()方法
$(function(){
  $("#lists").delegate("li","click",function(event){
    var target = $(event.target);
    target.css("background-color","red");
  })
})
#on()方法和delegate()方法对于事件委托的写法很像。
#并且执行事件委托的时候只有子元素(本文中的li)会触发事件,
#而代为执行的父元素(本文中为ul)不会触发事件,所以我们不需要盘判断触发事件的元素节点名,这一点明显优于原生的JavaScript。
# 3.用bind()方法
$(function(){
    $("#lists").bind("click","li",function(event){
        var target = $(event.target);
        if(target.prop("nodeName")=="LI"){
        target.css("background-color","red");}
    })
})
#bind()方法同原生的JavaScript实现方法一样,当父元素代子元素执行事件时,父元素也会触发事件,
#所以我们需要判断一下触发事件的元素名。此外,用bind()方法给元素绑定事件的时候要注意,
#它只能给已经存在DOM元素添加事件,不能给未来存在DOM

JS添加行的完善

// 由于事件绑定只在网页加载完成的时候进行,
// 因此即使JS添加行时,给按钮添加了class:del-row,
// 该按钮的点击依然不会触发点击函数

// 完善:在事件绑定时,不会行的删除按钮进行点击绑定,改为给table添加事件委托
<script>
  ...
  function bindDel(){
    $('#tb').on('click', '.del-row', function(){
      $('#delModal').modal('show');
      // 获得当前行id
      var rowID = $(this).parent().parent().attr('nid');
      // 在模态框里添加了一个id=delNid的input隐藏标签,方便记录和给后台提交删除记录的id
      $('#delNid').val(rowID);
    })
  }
</script>

模态框编辑数据相关

<body>
  ...
  {% for row in stu_list %}
    <tr nid="{{ row.id }}">
      <td na="nid">{{ row.id }}</td>
      <td na="user">{{ row.username }}</td>
      <td na="age">{{ row.age }}</td>
      <td na="gender">{{ row.gender }}</td>
      <td na="cls_id" cid="{{ row.cls.id }}">{{ row.cls.title }}</td>
      <td style="font-size: 20px;">
  			<a class="glyphicon glyphicon-remove icon del-row"></a>
  			<a class="fa fa-pencil-square-o icon edit-row"></a>
			</td>
    </tr>
  {% endfor %}
  ...

  <script>
    function bindEdit(){
        $('#tb').on('click','.edit-row',function () {
            $('#editModal').modal('show');
            // 获取当前行的所有数据
            // 将数据赋值到对应对话框的指定位置
            $(this).parent().prevAll().each(function () {
                var v = $(this).text();
                var n = $(this).attr('na');
                if(n=='cls_id'){
                    var cid = $(this).attr('cid');
                    $('#editModal select[name="cls_id"]').val(cid);
                }else if(n=='gender'){
                    if(v=='True'){
                        $('#editModal :radio[value="1"]').prop('checked',true);
                    }else{
                        $('#editModal :radio[value="0"]').prop('checked',true);
                    }
                }else{
                    $("#editModal input[name='"+ n + "']").val(v)
                }
            });
        })
    }
  </script>
</body>

其它

var list = [];
list.push("123")  # 将python中append

# form
$('#form_id').serialize() // 将form中的数据存为字典,即get/post时发送请求的数据

window.location.href='http://www.*****.com'; // JS跳转

js的空值

JavaScript本身没有判断一个变量是不是空值的函数,因为变量有可能是string,object,number,boolean等类型,类型不同,判断方法也不同。
https://zhuanlan.zhihu.com/p/325874564

function isEmpty(v) {
    switch (typeof v) {
    case 'undefined':
        return true;
    case 'string':
        if (v.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g, '').length == 0) return true;
        break;
    case 'boolean':
        if (!v) return true;
        break;
    case 'number':
        if (0 === v || isNaN(v)) return true;
        break;
    case 'object':
        if (null === v || v.length === 0) return true;
        for (var i in v) {
            return false;
        }
        return true;
    }
    return false;
}

一些实践记录

ajax、事件委托、dom操作:

<script>
        $(function () {
            bindPagination(); # 添加事件委托给分页控件的ul
            loadArticles(); # 加载文章数据
        });
        function bindPagination() {
            $('#ulpagination').on('click', "li", function(event){
                var p = event.target.getAttribute('p'); #event.target就是点击的a标签,a标签有页码属性“p”
                if (p==null){ return false;} # 如果页码属性”p“没有定义,说明没有对应的页,则返回。
                $.get({  #ajax
                    url:event.target.getAttribute('base_url'), # a标签中还有base_url属性,指定往哪里发送请求
                    dataType:'JSON',
                    data:{'p':p},
                    success:function (arg) {
                        list = JSON.parse(arg.data.articles); #data的articles是对象序列化得到的字典字符串,需要再次json解析
                        createArticleElements(list); # 创建和添加文章元素
                        ul = document.getElementById('ulpagination');
                        ul.innerHTML = arg.data.pagination_str; # 添加分页控件。注意innerHTML与innerText有区别
                    }
                })

            })
        }
        function loadArticlesBy(ths,filter,param) { # 根据标签/分类/日期请求文章数据
            console.log(filter,param);
            myClass = 'my_active'; # a标签的className
            if (ths.className.split(" ").indexOf(myClass) >= 0){ #点击的a标签是否已经有这个className
                return false; # 如果有了,说明已经按这个条件筛选了。不需要重新请求文章数据了
            }
            var url = "/{{ blog.site }}/" + filter + "/" + param + "/";
            console.log(url);
            $.get({
                url:url,
                dataType:'JSON',
                success:function (arg) {
                    if (arg.status){
                        list = JSON.parse(arg.data.articles);
                        createArticleElements(list);
                        ul = document.getElementById('ulpagination');
                        ul.innerHTML = arg.data.pagination_str;
{#                        a = document.getElementsByTagName('a');#}
                        al = $("a[mya]");  #拿到设置了mya属性的a标签,是一个数组
                        for (var i=0,len = al.length;i<len;i++){
                            $(al[i]).removeClass(myClass); # 清除所有a标签class的myClass类
                        }
                        $(ths).addClass(myClass); # 将被点击的a标签的class添加myClass
                    }
                }
            });
        }
        function loadArticles(){
            var url = "/{{ blog.site }}/articles/";
            $.get({
                url:url,
                dataType:'JSON',
                success:function (arg) {
                    if (arg.status){
                        list = JSON.parse(arg.data.articles);
                        createArticleElements(list);
                        ul = document.getElementById('ulpagination');
                        ul.innerHTML = arg.data.pagination_str;
                    }
                }
            });
        }
        function createArticleElements(articles) {
            ul = document.getElementById('ulArticles');
            while (ul.children.length>0)   # 清除ul中的子元素,即文章li
                ul.removeChild(ul.lastElementChild);
            for (var i=0,len=articles.length; i<len; i++) {
                ar = articles[i].fields; #用django serialeriz序列化的对象的属性在fields里面
                arID = articles[i].pk; #用django serialeriz序列化的对象id变成pk
                li = document.createElement('li');
                h = document.createElement('h3');
                h.innerText = ar.title; # 设置文本的方法
                li.appendChild(h);
                ul.appendChild(li);

                sum = document.createElement('div');
                sum.setAttribute('class', 'article-summary'); #设置属性的方法
                sum.innerText = ar.summary;
                li.appendChild(sum);

                p = document.createElement('p');
                p.innerText = ar.create_time;
                li.appendChild(p);

                s1 = document.createElement('span');
                s1.innerText = '  评论数:' + ar.comment_count;
                p.appendChild(s1);

                s2 = document.createElement('span');
                s2.innerText = '点赞数:' + ar.up_count;
                p.appendChild(s2);

                a = document.createElement('a');
                a.innerText = ' 编辑';
                a.setAttribute('href', '/articles/' + arID + "/edit/");
                p.appendChild(a);
            }
        }
    </script>

for循环删除子标签的问题
报错:Failed to execute 'removeChild' on 'Node': parameter 1 is not of type 'Node'.
目的:JS 动态表格,读取数据创建表格,点击删除单元格删除该行。
问题:删除时,删除第一行后,再删除第二行会造成第三行删除,并且最终剩下的一行无法删除。
原因:tbody.removeChild(tbody.children[i]) 中每次删除后,
tbody.children[i] 的值就变成了删除前的tbody.children[i+1]。
解决方案:改为 tbody.removeChild(this.parentNode);
正确方法:
while (ul.children.length>0):
ul.removeChild(ul.lastElementChild);

document DOM节点的attributes

NamedNodeMap 对象
在 HTML DOM 中, the NamedNodeMap 对象 表示一个无顺序的节点列表。
我们可通过节点名称来访问 NamedNodeMap 中的节点。

获取class属性值:
console.log(ths.className); 如果没有定义,返回空字符串
console.log(ths.attributes.getNamedItem('class')); 如果没有定义,返回undefined
都可以获取class 如:class="a b c" 就返回 字符串“a b c”

jQuery对象与DOM对象之间的转换方法

jQuery对象是包装DOM对象后产生的,但是两者却不能混用,DOM对象才能使用DOM方法,jQuery对象才能使用jQuery方法,以下介绍两者转换的方法:

#jQuery对象转成DOM对象:
(1)jQuery对象实际上是一个数据对象,可以通过[index]方法获得相应的DOM对象。
如:var $v=$("#v"); //得到jQuery对象
var v=$("v")[0];//转换成DOM对象2)jQuery本身可以通过.get(index)方法得到相应的DOM对象
如:var $v=$("#v"); //得到jQuery对象
var v=$v.get(0);

#DOM对象转成jQuery对象:
对于已经是一个DOM对象,只需要用$()将DOM对象包装起来,就能获得jQuery对象了
如:var v=document.getElementById("v"); //得到DOM对象
var $v=$(v); //转成jQuery对象
转换后,就可以任意使用jQuery的方法了

以下方法都正确:
$("#div").html();
$("#div")[0].innerTHML;
$("#div").eq(0)[0].innerHTML;
$("#div").get(0).innerHTML;
$(document.getElementById("div")).html()

平时在使用过程中可以在变量前面加$以区分DOM对象和jQuery对象,添加$的为jQuery对象,没有的则为DOM对象

js判断数组中是否存在某个元素(四种方法)

#方法一:利用indexOf 
#不存在返回-1,存在返回第一次出现的索引
var arr = [100,20,50,58,6,69,36,45,78,66,45]
if(arr.indexOf(66)==-1){
  console.log("不存在")
}else{
  console.log("存在,索引是:",arr.indexOf(66))
}

#方法二:利用find
#它的参数是一个回调函数,所有数组元素依次遍历该回调函数,直到找出第一个返回值为true的元素,
#然后返回该元素,否则返回undefined。
var arr = [100,20,50,58,6,69,36,45,78,66,45]
arr.find(function(value,index,arr){
      if(value==45){
            console.log("存在",index)    
      }
}) #查找45,find会找出所有存在的45以及索引

#方法三:利用some
#some方法同样用于检测是否有满足条件的元素,如果有,则不继续检索后面的元素,直接返回true,
#如果都不符合,则返回一个false。用法与find相似,只是find是返回满足条件的元素,
#some返回的是一个Boolean值,从语义化来说,是否包含返回布尔值更贴切
let arr = [100,20,50,58,6,69,36,45,78,66,45]
// some
let result = arr.some(ele => ele === 45) //true
if (result) {
//do something...
};

#方法四:includes 
#ES6新增的数组方法,用于检测数组是否包含某个元素,如果包含返回true,否则返回false,比较厉害的是,能直接检测NaN:
#优点 就不用说了,最简单的做法没有之一,不用回调,不用复杂的写法,一个方法直接搞定。
#缺点 是低版本浏览器支持不是很友好
let arr = [100,20,50,58,6,69,36,45,78,66,45,NaN]
// 法四
let flag = arr.includes(1100)
let flag1 = arr.includes(NaN)

console.log(flag,flag1)
posted @   Bruce_JRZ  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
点击右上角即可分享
微信分享提示