Skip to content

Latest commit

 

History

History
321 lines (193 loc) · 20.9 KB

2017-5.md

File metadata and controls

321 lines (193 loc) · 20.9 KB
title tags notebook
编程日记_2017-5
编程日记

5-8 Python

今天买了PHP的书,却在晚上学习起了Python,大家一直说Python是一门十分简单的语言,所以我下载了Head first Python的电子书。经过短暂的学习,发现学习Python是一个令人愉悦的事情。而且,Python和JS有很多相似之处,例如他们都是弱类型的动态语言。

Python中的数组不叫数组,叫做列表list,严格意义上说它并不等同于数组的功能。用list.append('')添加更多的项,用list.pop(),删除最后一个项,并返回,用**list.remove("itemname")移除特定的项,用list.insert(position, insertItem)在特定位置添加特定项,用list.extend(anotherList)**合并更多的list。

Python通过**isinstance(testName, datatype)来验证一个标识符指示的数据类型是否为datatype,例如测试:isinstance(arr1, list)检测arr1是否是一个列表,类似于JS中的test instanceof datatype。用len()**方法表示某个数据段的长度,类似于JS中的.length;

像instance()和print()这种方法叫做python内置函数(BIF)。

其次,Python的循环语句也更为简单,可以通过for item in list来进行一个列表内的元素遍历,item即为每一项,当然也可以使用while条件为真的时候,处理数据。

Python中的**组(suite)**表示的是代码块,其通过缩进的书写风格来表示。

Python中的函数使用def关键字声明:def functionName():

综上,Python与JS的不同之处在于,前者的条件语句以及函数等代码块中不适用花括号,直接用冒号就可以了。

5-9 Python

Python的逻辑操作符与PHP类似,and,or,not。Python中,不同数据类型的字符串不能够直接用+连接,而是要进行转换。例如一个字符串和一个数字,"this is "+18则会报错,正确的做法是,进行数据类型的转换,"this is " \\\\\\\\+ str(18),还有一种方法是使用%对字符串进行格式化

"this is %d" % 18,用18替换%d,当然,%d替换的是整数,若要替换小数,则是%f,%s替换字符串。

Python还有一些数据类型转换的方法:int(x),float(x),bool(x)

需要注意的是,int()和float()进行转换时,要转换的值并不能转换出现非数字字符的值

Python的input()方法允许用户输入一些内容,并且将输入的内容转换为字符串。例如下面 的代码中,输入的数字会被转换为该数字的字符串形式,使得与num无法进行比较,所以需 要使用int()方法进行数据类型转换。

from random import randint
num = randint(1, 100)
print('请输入一个数字:')
answer = False
while answer == False:
  inputNum = int(input('猜猜看,我想的是什么数字:'))

  if inputNum < num:
    print('%d太小了' % inputNum)
  elif inputNum > num:
    print('%d太大了' % inputNum)
  else:
    print('猜对了!')
    answer = True

其次,在上面的代码第一行,引入了Python随机函数库,具体细节有待学习。

再者,注意上面代码中的条件判断语句的格式。

在循环中,continue表示跳过本轮循环,继续下一轮;break表示跳出循环,不再执行。

5-10 Python

Python的函数由def关键字后面跟上标识符、括号以及冒号定义,冒号下面就是通过缩进表示函数体。

函数的调用与JS一致,在函数标识符后面加上括号即可(有参数还需要加上参数)。

函数定义的时候定义的参数叫做形参,函数调用的时候传入的参数叫做实参。

函数仍然有局部变量之说,可以使用global关键字定义一个全局变量,不管它在什么地方定义

Python的变量查找与JS不同,在下面这个例子中,定义了一个全局变量x,并且在函数内部打印之前给其赋值,又 在函数外部为其赋不同的值,那么print会打印哪一个值呢?

def global_func():
    global x

    print(x)
    x = 200  

x = 100 
global_func()

结果是print出100,并不是当前作用于下的200,其原因在于x = 200定义在print之后,当没有在print语句执行 之前为x赋值的话,函数会在全局作用域下查找赋值。

可以在设置函数形参的时候为函数传递默认参数值,用来当调用时没有设置参数响应参数之时,如果调用时提供了 相关的参数值,则会覆盖默认参数值。

def printSomething(msg, times = 2):
print(msg * times)

printSomething('ha')  #'haha'
printSomething('xi', 3) # 'xixixi'

需要注意的是,只有在形参列表末尾的那些参数才可以拥有默认参数。也就是说,在没有默认参数的参数前面不能 有设置了默认参数的参数。

当参数较多的时候,可以在调用的时候,通过形参标识符直接为关键参数赋值,这样可以使得函数调用更灵活,而 且不受形参顺序的影响(因为会有标识符来确认参数位置),如下例:

def key_para(a, b=1, c=2):
print('a =',a,',b =',b,',c =',c)

key_para(1) #a = 1 ,b = 1 ,c = 2
key_para(2, b=3, c=5) #a = 2 ,b = 3 ,c = 5
key_para(c=3, a=100) #a = 100 ,b = 1 ,c = 3

下午,发现了一个JavaScript30计划,也就是30天,每天用纯JS(ES6)写一个页面。今天做的是做一个键盘模拟鼓点的页 面,其中需要掌握的知识点如下:

  1. 按下键盘事件结合keyCode,来确定哪个键位被按下(每个键位的keyCode是唯一的)。
  2. 使用ES6字符串模板以及querySelctor()来确定与按下键位相关联的div块,以便于改变其样式。const key = document.querySelector(div[data-type="${event.keyCode}"]) .字符串模板的使用方法是,将字符串包裹在反引号``中,字符串中的变量部分用${}包裹。
  3. 使用Array.from()方法将类数组对象以及可迭代对象转变为真正的数组。
  4. 在键盘按下之后,相应的div会发生transition样式变化,故而显示变化之后需要清除这些变化,会使用到一个transitionend事件,表示CSS中触发了transition属性之后的响应。
  5. Element.classList表示元素的class类数组列表,可以通过其.add()remove()方法,添加或者移除响应的类名,以达到div样式的切换。

在线地址

5-11 JS

今早重写了昨天的JS30效果,用以检测掌握程度。过程中注意到background-size: cover;的CSS属性,并不明晰。 查询文档,发现此CSS属性有三种类型的值,第一种是例子中用到的cover,第二种是contain,第三种是width/height. 第三种好理解,前两种的区别是:cover表示背景图片尺寸会保持图像宽高比,尽可能放大,最大为原始大小。如果图 像的宽或者高等于容器的宽或者高的时候,它会停止放大,哪怕此时某一部分还是空白的。后者表示背景图片尺寸保持 图像宽高比,尽可能方法,一直到充满整个容器,如果宽或者高溢出容器,则会按照位置裁剪。

5-12 JS

昨天的JS30任务是写一个钟表效果,在指南文档的提示下,我能够将基本的逻辑写下来,但是,期间主要出现了两 大问题:第一是,在new Date()的时候,将其放在了更新时间函数的外面,使得每次调用函数的时候,时间并咩 有得到更新。其次是,关于三针转动角度的问题,我忽略了指针初始位置,需要在旋转开始时先旋转90度,使其到 达零点位置。

昨天的重点是 CSS3 transform 问题。需要多加应用。

5-14 JS

JS30 第三个任务我可以通过作者的提示完成基本功能,共用了22行代码(不包括 CSS),作者通过遍历添加事件,只用了6行代码,说明目前我还是停留在写出面条式代码的阶段,但是,好现象是,我能够通过自己写出功能,这是进步。

说回任务本身。昨天的任务涉及到了 dataset 属性,CSS 全局变量的使用,这两个东西是我前面没有接触到的。

HTMLElement.dataset 属性

dataset 属性允许访问所在DOM元素自定义的data属性列表,一般以 "data-" 打头来命名,并且只可以包含数字字母以及 -.:_ 四个字符组成,它的结构是一个DOMString映射表,在访问的时候,其前面的 data 以及特殊符号被去除。例如,在任务中,给每个表单元素设置了 "data-sizing" 属性,取值为 "px",由此可以通过this.dataset.sizing 来访问设置的 data-sizing 属性。

CSS全局变量

CSS全局变量是CSS允许以变量的形式,在:root伪元素下设立一些常用的重复使用的样式属性,在需要使用的位置使用 var()的形式来访问引用。在本例中,通过使用根元素 :root 选择器来在根元素(即HTML标签)上设置了 --base, --spacing, --blur 三个全局变量,为其赋初始值,并在 img 元素上进行引用。如下:

img {
      background-color: var(--base);
      padding: var(--spacing);
      filter: blur(var(--blur));
    }

这样做的好处是,如果页面中多次引用了某个变量,例如某个字体颜色,在需要改变页面中所有的颜色时,只需要将变量的初始值一处进行修改,则会应用到全部引用的位置。在这个例子中,通过借助 style.setProperty() 来动态修改 CSS 变量,而达到表单元素变化时,CSS变量随之改变,则应用到图片上的样式也同时改变,而达到目的。类似于Sass等中的CSS变量。只不过 Sass 中以美元符号 $ 打头,而CSS全局变量则以 -- 打头。

额外需要注意的是,style.setProperty 的语法,其可以接受三个参数,分别是属性名、值以及优先级(可以通过 !important 来提高优先级)。举个例子,要设置一个 div 元素的 margin 值为 0 auto,可以这样设置: document.querySelector('div').style.setProperty('margin', '0 auto'); 其实相当于 JQuery 的element.css() 操作。

5-16 JS

day4 的任务中,新见了一个控制台调试技巧:console.table,这个输出方式会将数组或者 object 中的可枚举属性以表格的形式输出。

其次就是 Array 的一一些操作方法的熟练使用问题,尤其是 Array.reduce() 方法,其可以接受一个回调函数和一个操作初始值,回调函数接受两个参数,第一个参数代表和初始值作用后的累加值,第二个参数表示数组中的所有遍历元素(从左到右),而如何累加,则有函数部分决定,也就是说,这里的累加并不是指加法,而是一个积累的作用过程。例如下面的例子:

[1, 2, 3, 4, 5, 6].reduce((result, val) => result - val, 10)

则实现以10为基础,进行一个累减操作。也就是 10 - 1 - 2 - 3 - 4 - 5 - 6 = -11;

5-18 JS

今天遇到一个 JS 的新操作——document.createDocumentFragment,此特性用于创建一个空白的文档片段。也可以理解为一个空白的 DOM 元素容器,它同样可以赋值给一个变量:

let frag = document.createDocumentFragment();

这个特性的优势在于,其只是一个需要附加到 DOM 树上的 DOM 子元素容器,开始存在于内存之中,当此元素被插入到 DOM 树之后,这个结构会被其上面附加的 DOM 节点代替,故而不会引起页面回流,故而不影响页面性能。

参考这里

5-19 JS

看了网上面向对象式的轮播图组件,才算是对面向对象思维有了一次实践意义上的认知。所谓面向对象就是一种组件化的包装,而留一个实例化的接口。一般情况下,采用构造函数实例化的形式。在 ES6 中,提供了 class 关键字,可以用更好的形式展现面向对象思维。难怪 JJC 会说,首先你是一个程序员,然后你才是一个前端程序员。

另外,在编程过程中,函数应该尽可能小而美,这样的好处是代码条理比较清晰,而不是大杂烩一般。实现一个功能,首先是划分需要实现哪几条任务,进行功能实现上的划分,也就是在 MIT 公开课上,老师思维逻辑图的原因。

5-20 CSS and JS

昨天去面试,遇到几个题,其实并不难,但当场没能给出很理想的答案,今天回顾一下。

  1. 不用Math和数组排序方法,取出数组中的最大值和平均值

这个题我在看书的时候遇到过,但还是表现很含糊,可见看书的时候没有自己练习,只知其然的缘故。其实就是包装一个Math.max()方法,下面给出解决。

// 返回数组最大值
function max(arr) {
  var max = arr[0];

  for (var i = 0; i < arr.length; i++) {
    if (arr[i] > max) {
      max = arr[i];
    }
  }

  return max;
}

// 返回数组平均数
function getArg(arr) {
  // 最简单方法是使用reduce()累加再求平均值,但不允许
  var sum = 0,
      len = arr.length;
  for (var i = 0; i < len; i++) {
    sum += arr[i];
  }
  return sum/len;
}
  1. 实现这样一个函数:传入一个小数,返回其保留两位小数的结果 当时给出的思路是,用 indexOf 判断小数点的位置,然后用 slice() 截取位置后两位以前的部分,最后还需使用 parseFloat()转为 Number。是这样:
function keepTwoPlaceDecimal(num) { 
  var strNum = num.toString();
  var indexOfDot = strNum.indexOf('.') + 3; 
  return parseFloat(strNum.slice(0, indexOfDot)); 
}

现在一想,真实够折腾,而且当传入的数字没有两位以上小数或者根本找不到小数点时,程序并不会实现功能。有一个 toFixed() 方法,可以通过传入参数,直接控制保留的小数位数,并且在位数不足时会自动补0.位数超过要求四舍五入截取。

function keepTwoPlaceDecimal(num) {
  return parseFloat(num.toFixed(2));
}
  1. 使用 HTML + CSS 实现一行文本超出一定范围自动换行 这个题我完全没有思路,下来一查,竟然有 word-breakword-wrap 这种特性,这位特性以前是见过的~在几个 id 分别为 wrap1, wrap2 的 div 上分别应用以下样式: word-break: normal | break-all | keep-all; normal 表示使用默认的换行规则,break-all 表示对于非中日韩文本,可以在任意字符间断行。keep-all 表示 CJK 文本不换行,其他字符像 normal 时一样换行。

div { margin-top: 20px; } #wrap1 { width: 200px; border: 1px solid #000; word-break: break-all; } #wrap2 { width: 200px; border: 1px solid #000; word-break: keep-all; }

效果如下:

  • word-break: break-all
  • word-break: keep-all

5-23 JS

关于几个相对单位:

  • rem: 以设置在 root 元素的 font-size 属性值为标准,也就是 1rem 等于一倍的 root 元素的 font-size;
  • em: 以当前字体的 font-size 属性值为标准,也就是 1em 等于一倍的 font-size;
  • ex: 以当前字体的高度值为标准的单位值,以小写状态为依据,1ex = 1 font height. 在大多数字体下,1ex = 0.5em;
  • vh: 1/100 的视口高度值

5-25 CSS

今天学到的: vertical-align 属性用来指定行内元素以及表格元素的对齐方式。其大部分取值相对于父元素来讲的。针对行内元素与表格元素的标准当然是不一样的。对于行内元素来讲,当属性值为 top 的时候,表示其与整行的最顶端对齐。

CSS 指定字符编码的写法:@charset 'UTF-8'.

在表单元素中,文本框和按钮采用不一样的盒子模型,前者是标准盒子模型,后者是 IE 盒子模型。

对于 Sass 的嵌套特性,不应该用得太浪,因为,嵌套层次过深,其编译出来的 CSS 会十分冗余,在降低代码整洁度的同时,更是大大影响页面性能。

Sass 中的 Mixins 常用的一点是处理 CSS3 属性中的前缀属性,可以使编码量大大降低。例如,可以包装下面这样一个关于 border-radius 的混合:

@mixin borderRadius($border-radius: 10px) { border-radius: $border-radius; -o-border-radius: $border-radius; -moz-border-radius: $border-radius; -webkit-border-radius: $border-radius; }

这个 Mixins 设置了一个大小为 10px 的圆角,在需要的时候,使用 @include borderRadius; 来调用,如果想改变大小,只需要更换参数即可:@include borderRadius(20px);

继承一般用于提炼出公共样式,然后在需要的地方通过 @extends 来调用。但是,如果调用的类名组织的样式在其他地方出现过的话,它会把出现过的该类下的所有代码全都继承过来,使得代码失去控制。

%placeholder 特性是十分强大的特性,通过 % 定义的样式,只要不通过 @extends 调用,它就不会产生任何多余的代码,相当于没存在过,可以说,这个特性完美滴解决了前面继承的问题。

5-29 Vue

Vue 在过去的一年飞快成长,已经是前端开发框架中的佼佼者之一。因为其简单易上手等优点,很快为广大开发者接受。但是,如果你是一名并没有实际开发经验,不了解数据绑定,组件化思想的初学者,很容易在这些基本概念中眩晕(我便是如此)。在这种时候,一定不要着急,或者说气馁,要沉下气来,从基本的原理和概念入手学习,做到不乱于心。

Vue 的优秀特性主要表现为:双向数据绑定以及组件化的构建形式,同时 Vue 提供了一些第三方的轻量库,开发者借助这些库可以实现各种开发需求。下面是一些基本概念的东西。

  • 全局 API:Vue 提供一些全局的操作函数,例如 Vue.extend() 可以在 Vue 基础构造器之上,创建一个它的“子类”,其可以接受包含该组件选项的对象。而对于 Vue 的插件,例如 Vue-router ,在使用的时候,需要使用 Vue.use() 方法进行注册。
  • 选项:对于数据和 DOM ,Vue 都提供一些基本的选项,以便于数据渲染和 DOM 关联。对于数据选项,有最基本的 Data 属性,来表示 Vue 实例的数据对象,可以通过 vm.$data 来访问原始数据对象。Vue 使用 props 属性来接收来自于父组件的数据,它可以是简单的数组,也可以是进行配置高级选项(类型检测、默认值)的对象。通过 computed 计算属性来进行数据操作。除此之外,还有 watch 选项进行表达式观察,使用 methods 选项定义示例方法。

用于 DOM 观察的选项较少,el 用于指定一个 DOM 元素作为实例的挂载目标。使用 template 字符串模板作为实例的标识,其可以替换 el 指定的挂载元素。

  • 生命周期钩子选项。Vue 同样提供了一些 Vue 组件生命周期特定时期的钩子。下图是 Vue 组件的生命周期示意图:

Vue 还有一些基本 API ,可参考其文档

值得注意的是,还有一些基于实例的操作,可以通过 vm.$ 的形式来进行访问。例如对于一个组件示例 app, 我们可以通过 app.$on('click', function () {}) 来为其绑定点击事件。可以通过 app.$data 来访问 app 的 data 方法下的所有数据。

  • 指令。Vue 提供一些基本的操作指令,例如 v-text 可以更新元素的文本内容,v-if 可以进行基本的条件判断渲染,v-bind 用于绑定 DOM 元素的属性,v-model 在表单控件上实现数据双向绑定。

Tips: v-textt-html 的区别:前者相当于插入 textContent 的内容,而后者则相当于 innerHTML 的内容,后者安全性不高。在下面的实例中,可以很清晰地看到区别:

<template>
<div id="app">
  <h1 v-text="imgEle"></h1>
  <h2 v-html="imgEle"></h2>
  <!-- <router-view></router-view> -->
</div>
</template>

<script>
export default {
  name: 'app',
  data () {
    return {
      imgEle: '<img src=\'http://i2.muimg.com/567571/6c2cfa8bcf63a117.jpg\'>'
    }
  }
}
</script>

h1 显示的内容为 imgEle 指示的字符串内容,而后者则会渲染出一张图片来。