前端笔记
JavaScript
ES6
ECMAScript6.0(以下简称ES6,ECMAScript是一种由Ecma国际通过ECMA-262标准化的脚本),是JavaScript语言的下一代标准,2015年6月正式发布,从ES6开始的版本号采用年号,如
ES2015,就是ES6。 ES2016,就是ES7。 ES2017,就是ES8。 ECMAScript是规范,JS的规范的具体实现。
声明变量的方式
- 如果我们在一个大括号体中声明变量,那么let声明的变量不会作用到{}外,var声明的变量则会越域跳到{}外
- var可以多次声明同一变量,而let则会报错
- var定义的变量在定义之前可以使用,let定义的变量在定义之前不可使用。(变量提升问题)
<script>
{
var a = 1;
let b = 2;
}
console.log(a);
console.log(b);
var m = 1
var m = 2
let n = 3
let n = 4
console.log(m)
console.log(n)
console.log(x);
var x = 10;
console.log(y);
let y = 20;
const a = 1;
a = 3;
</script>
解构表达式
- 支持
let arr = [1,2,3]; let [a,b,c] = arr; 这种语法 - 支持对象解析:
const { name: abc, age, language } = person; 冒号代表改名,旧:新 - 字符串函数
- 支持一个字符串为多行``
- 占位符功能 ${}
<script>
let arr = [1,2,3];
let [a,b,c] = arr;
const person = {
name: "jack",
age: 21,
language: ['java', 'js', 'css']
}
const { name: abc, age, language } = person;
let str = "hello.vue";
console.log(str.startsWith("hello"));
console.log(str.endsWith(".vue"));
console.log(str.includes("e"));
console.log(str.includes("hello"));
let ss = `<div>
<span>hello world<span>
</div>`;
function fun() {
return "这是一个函数"
}
let info = `我是${abc},今年${age + 10}了, 我想说: ${fun()}`;
</script>
函数优化
支持函数形参默认值 function add2(a, b = 1) { 支持不定参数 function fun(…values) { 支持箭头函数 var print = obj => console.log(obj); 箭头函数+结构 var hello2 = **({name}) => console.log(“hello,” +name);**本来应该是person.name
<script>
function add(a, b) {
b = b || 1;
return a + b;
}
function add2(a, b = 1) {
return a + b;
}
function fun(...values) {
console.log(values.length)
}
fun(1, 2)
fun(1, 2, 3, 4)
var print = obj => console.log(obj);
var sum = (a, b) => a + b;
var sum2 = function (a, b) {
c = a + b;
return a + c;
}
var sum2 = (a, b) => {
c = a + b;
return a + c;
}
const person = {
name: "jack",
age: 21,
language: ['java', 'js', 'css']
}
function hello(person) {
console.log("hello," + person.name)
}
var hello2 = ({name}) => console.log("hello," +name);
</script>
对象优化
可以使用Object.keys()/values/entries方法获取对象的键值对(属性名/值)等信息 Object.assgn(target,source1,source2) 合并传入参数的变量 如果属性名和属性值的变量名相同,可以省略const person2 = { age, name } 代表age属性的值是变量age的值 …代表取出该对象所有属性拷贝到当前对象。let someone = { …p1 }
<script>
const person = {
name: "jack",
age: 21,
language: ['java', 'js', 'css']
}
console.log(Object.keys(person));
console.log(Object.values(person));
console.log(Object.entries(person));
const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3 };
Object.assign(target, source1, source2);
const age = 23
const name = "张三"
const person1 = { age: age, name: name }冒号前为要赋值的变量名,冒号后为当前声明对象的属性名
const person2 = { age, name }
let person3 = {
name: "jack",
eat: function (food) {
console.log(this.name + "在吃" + food);
},
eat2: food => console.log(person3.name + "在吃" + food),
eat3(food) {
console.log(this.name + "在吃" + food);
}
}
let p1 = { name: "Amy", age: 15 }
let someone = { ...p1 }
let age1 = { age: 15 }
let name1 = { name: "Amy" }
let p2 = {name:"zhangsan"}
p2 = { ...age1, ...name1 }
</script>
map和reduce
map() :接收一个函数,将原数组中的所有元素用这个函数处理后放入新数组返回。 reduce() :为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素。
<script>
let arr = ['1', '20', '-5', '3'];
arr = arr.map(item=> item*2);
arr.reduce(callback,[initialValue])
1、previousValue (上一次调用回调返回的值,或者是提供的初始值(initialValue))
2、currentValue (数组中当前被处理的元素)
3、index (当前元素在数组中的索引)
4、array (调用 reduce 的数组)*/
let result = arr.reduce((a,b)=>{
console.log("上一次处理后:"+a);
console.log("当前正在处理:"+b);
return a + b;
},100);
</script>
promise
promise对象可以优化异步操作,比如封装ajax异步操作。
<script>
function get(url) {
return new Promise((resolve, reject) => {
$.ajax({
url: url,
success: function (data) {
resolve(data);
},
error: function (err) {
reject(err)
}
})
});
}
get("mock/user.json")
.then((data) => {
console.log("用户查询成功~~~:", data)
return get(`mock/user_corse_${data.id}.json`);
})
.then((data) => {
console.log("课程查询成功~~~:", data)
return get(`mock/corse_score_${data.id}.json`);
})
.then((data)=>{
console.log("课程成绩查询成功~~~:", data)
})
.catch((err)=>{
console.log("出现异常",err)
});
</script>
**promise小总结:**以前嵌套ajax的时候很繁琐。现在使用promise就很方便了,步骤如下:
- 把Ajax封装到Promise中,赋值给let p
- 在Ajax中成功使用resolve(data),失败使用reject(err)
- p.then().catch()
模块化import/export
模块化就是把代码进行拆分,方便重复利用。类似于java中的导包,而JS换了个概念,是导模块。
模块功能主要有两个命令构成 export 和import
- export用于规定模块的对外接口
- import用于导入其他模块提供的功能
#user.js
var name = "jack"
var age = 21
function add(a,b){
return a + b;
}
export {name,age,add}
#hello.js
export default {
sum(a, b) {
return a + b;
}
}
#main.js
import abc from "./hello.js"
import {name,add} from "./user.js"
abc.sum(1,2);
console.log(name);
add(1,3);
Vue
MVVM思想
**M:**model 包括数据和一些基本操作 **V:**view 视图,页面渲染结果 View-model:模型与视图间的双向操作(无需开发人员干涉) 视图和数据通过VM绑定起来,model里有变化会自动地通过Directives填写到视图view中,视图表单中添加了内容也会自动地通过DOM Listeners保存到模型中。即只要我们Model发生了改变,View上自然就会把改变的内容表现出来。 当用户修改了View,Model中的数据也会跟着改变。使用MVVM是开发人员从烦琐的D0M操作中解放出来,把关注点放在如何操作Model数据上。
Vue的初步使用:
使用步骤:
- 首先创建出vue实例(new vue()),然后在括号里面传入跟这个vue实例有关的数据,比如其关联的哪个页面的模板,然后是关联模板的相关信息需要声明出来如关联数据(data),关联方法(methods)。
- 在dom中想使用vue中的model数据信息可以使用两对大括号{{},其代表从model数据模型中放到view视图中
- v-model实现双向绑定,即model和view的改变对双方都是可见的。
<body>
<div id="app">
<input type="text" v-model="num">
v-model实现双向绑定。此处代表输入框和vue里的data绑定
<button v-on:click="num++">点赞</button>
v-on:click是绑定单击事件的,可以直接声明单击事件内容,也可以绑定回调函数。
<button v-on:click="cancel">取消</button>
<h1> {{name}} ,非常帅,有{{num}}个人为他点赞{{hello()}}</h1>
h1中num属性值改变原理:num属性先从vue中拿到值填充到dom,input标签中如果改变num值,vue实例则会更新,然后此处也更新
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: "#app",
data: {
name: "张三",
num: 1
},
methods:{
cancel(){
this.num -- ;
},
hello(){
return "1"
}
}
});
</script>
</body>
在vue中其指令都以v-开头。
v-text、v-html
{{}}:<div>123{{}}</div> 这种写法叫插值表达式也就是说大括号里面是表达式(其支持js语法),可以计算,可以取值,可以调用js内置函数。但是这个表达式必须有返回结果!插值表达式也可以直接获取Vue实例中定义的数据或者函数。
**插值闪烁:**使用{{}}方式在网速较慢时会出现问题。在数据未加载完成时,页面会显示出原始的{{}} ,加载完毕后才显示正确数据,我们称为插值闪烁。v-html 和v-text命令能解决这个问题。
<body>
<div id="app">
<span v-html="msg"></span>//v-html命令作用是把内容用html语法解析之后内容表示出来
<br/>
<span v-text="msg"></span>//v-text命令作用是把内容以text的形式表示出来,而不会把其用别的语言的语法进行解析
</div>
<script src="../node_modules/vue/dist/vue.js"></script>
<script>
new Vue({
el:"#app",
data:{
msg:"<h1>Hello</h1>",
link:"http://www.baidu.com"
},
methods:{
hello(){
return "World"
}
}
})
</script>
</body>
v-bind
但是插值表达式只能用在标签体里(
标签内> 标签体
),不能用在标签内。,如果我们这么用
是不起作用的,所以需要
这种用法。
v-bind:可以简写为:。冒号后为要绑定的属性名,表示把model绑定到view(它是单向绑定),比如可以设置src、title、class等。
而且我们可以在浏览器里把link的属性值进行修改,那么dom里的链接地址也会进行改变。
class里有哪些内容可以通过vue数据的bool值添加删除,而在style属性中属性值的形式是k:v值,所以可以直接对value进行修改来达到修改具体样式的目的。
<body>
<div id="app">
<a v-bind:href="link">跳转</a>
<span v-bind:class="{active:isActive,'text-danger':hasError}"
:style="{color: color1,fontSize: size}">你好</span>
</div>
<script src="../node_modules/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el:"#app",
data:{
link: "http://www.baidu.com",
isActive:true,
hasError:true,
color1:'red',
size:'36px'
}
})
</script>
</body>
v-model
v-bind是单向绑定,只能从model到view。而v-model是双向绑定,不止能从model到view,还能从view到model。这个常用语用户可以修改页面内容的标签使用,如表单中的多选框,自定义组件。
<body>
<div id="app">
精通的语言:如果是多选框,那么会把每个value值赋值给vue中vm对象的language属性
<input type="checkbox" v-model="language" value="Java"> java<br/>
<input type="checkbox" v-model="language" value="PHP"> PHP<br/>
<input type="checkbox" v-model="language" value="Python"> Python<br/>
选中了 {{language.join(",")}}
</div>
<script src="../node_modules/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el:"#app",
data:{
language: []
}
})
</script>
</body>
v-on
事件监听可以使用v-on指令
语法格式为:v-on:事件类型=“方法” ,可以简写成**@事件类型=“方法”**
事件冒泡:如果大小div都有单机事件,点了内部div相当于外部div也点击到了,那么两个div的单击事件会同时触发。
v-on指令可以使用.stop事件修饰符阻止事件冒泡
语法格式是v-on:事件类型.事件修饰符=“方法”
还可以绑定按键修饰符
v-on:keyup.up=“num+=2” @keyup.down=“num-=2” @click.ctrl=“num=10”
<body>
<div id="app">
<button v-on:click="num++">点赞</button>
<button @click="cancel">取消</button>
<h1>有{{num}}个赞</h1>
大div
<div style="border: 1px solid red;padding: 20px;" v-on:click.once="hello">这里once的意思是只会触发一次单击事件
小div
<div style="border: 1px solid blue;padding: 20px;" @click.stop="hello">
<br />
<a href="http://www.baidu.com" @click.prevent.stop="hello">去百度</a>//prevent的意思是阻止其默认事件的发生。
</div>
</div>
绑定按键修饰符
<input type="text" v-model="num" v-on:keyup.up="num+=2" @keyup.down="num-=2" @click.ctrl="num=10"> <br />
</div>
<script src="../node_modules/vue/dist/vue.js"></script>
<script>
new Vue({
el:"#app",
data:{
num: 1
},
methods:{
cancel(){
this.num--;
},
hello(){
alert("点击了")
}
}
})
</script>
</body>
v-for
可以遍历数组[]和字典{} 。
对于数组<li v-for="(item,index) in collection"> in后面跟的是要遍历的集合,括号里面就是遍历出来的集合里的元素。
对于字典<li v-for="(value,key,index) in Object"> in后面跟的是要遍历的元素,括号里面就是遍历出来的元素里的属性。
<body>
<div id="app">
<ul>
<li v-for="(user,index) in users" :key= "user.name" v-if="user.gender == '女'">
当前索引:{{index}} ==> {{user.name}} ==>
{{user.gender}} ==>{{user.age}} <br>
对象信息:
<span v-for="(v,k,i) in user">{{k}}=={{v}}=={{i}};</span>
</li>
</ul>
</div>
<script src="../node_modules/vue/dist/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data: {
users: [
{ name: '柳岩', gender: '女', age: 21 },
{ name: '张三', gender: '男', age: 18 },
{ name: '范冰冰', gender: '女', age: 24 },
{ name: '刘亦菲', gender: '女', age: 18 },
{ name: '古力娜扎', gender: '女', age: 25 }
]
},
})
</script>
</body>
v-if和v-show
在vue实例的data指定一个bool变量,然后v-show赋值即可。
show里的字符串也可以比较
if是根据表达式的真假,切换元素的显示和隐藏(操作dom元素)
**区别:**show的标签F12一直都在,if的标签会移除;if操作dom树对性能消耗大
<body>
<div id="app">
<button v-on:click="show = !show">点我呀</button>
<h1 v-if="show">if=看到我....</h1>
<h1 v-show="show">show=看到我</h1>
</div>
<script src="../node_modules/vue/dist/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data: {
show: true
}
})
</script>
</body>
v-else和v-else-if
<body>
<div id="app">
<button v-on:click="random=Math.random()">点我呀</button>
<span>{{random}}</span>
<h1 v-if="random>=0.75">
看到我啦? >= 0.75
</h1>
<h1 v-else-if="random>=0.5">
看到我啦? >= 0.5
</h1>
<h1 v-else-if="random>=0.2">
看到我啦? >= 0.2
</h1>
<h1 v-else>
看到我啦? < 0.2
</h1>
</div>
<script src="../node_modules/vue/dist/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data: { random: 1 }
})
</script>
</body>
计算属性和侦听器
计算属性computed
计算属性的属性不是具体值,而是通过一个函数计算出来的,随时变化的(只要计算属性方法体内的变量值变)
<div id="app">
<p>原始字符串: {{ message }}</p>
<p>计算后反转字符串: {{ reversedMessage }}</p>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
message: 'Runoob!'
},
computed: {
reversedMessage: function () {
return this.message.split('').reverse().join('')
}
}
})
</script>
<body>
<div id="app">
<ul>
<li>西游记; 价格:{{xyjPrice}},数量:<input type="number" v-model="xyjNum"> </li>
<li>水浒传; 价格:{{shzPrice}},数量:<input type="number" v-model="shzNum"> </li>
<li>总价:{{totalPrice}}</li>
{{msg}}
</ul>
</div>
<script src="../node_modules/vue/dist/vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
xyjPrice: 99.98,
shzPrice: 98.00,
xyjNum: 1,
shzNum: 1,
msg: ""
},
computed: {
totalPrice(){
return this.xyjPrice*this.xyjNum + this.shzPrice*this.shzNum
}
},
watch: {
xyjNum: function(newVal,oldVal){
if(newVal>=3){
this.msg = "库存超出限制";
this.xyjNum = 3
}else{
this.msg = "";
}
}
},
})
</script>
</body>
监听$watch
监听属性watch,我们可以通过watch来响应数据的变化。
<div id = "app">
<p style = "font-size:25px;">计数器: {{ counter }}</p>
<button @click = "counter++" style = "font-size:25px;">点我</button>
</div>
<script type = "text/javascript">
var vm = new Vue({
el: '#app',
data: {
counter: 1
}
});
vm.$watch('counter', function(nval, oval) {
alert('计数器值的变化 :' + oval + ' 变为 ' + nval + '!');
});
要监听的属性值:function(新值,旧值){
方法体
}
}
</script>
过滤器filter
定义filter组件后,管道符后面跟具体过滤器{{user.gender | genderFilter}} 表示|前面的属性值传入后面的过滤器方法,然后把过滤器方法中的处理结果进行返回,最后{{}}中展示的是过滤器方法的处理结果。
<body>
<div id="app">
<ul>
<li v-for="user in userList">
{{user.id}} ==> {{user.name}} ==> {{user.gender == 1?"男":"女"}} ==>
{{user.gender | genderFilter}} ==> {{user.gender | genderFilter}}
</li>
</ul>
</div>
<script src="../node_modules/vue/dist/vue.js"></script>
<script>
Vue.filter("gFilter", function (val) {
if (val == 1) {
return "男~~~";
} else {
return "女~~~";
}
})
let vm = new Vue({
el: "#app",
data: {
userList: [
{ id: 1, name: 'jacky', gender: 1 },
{ id: 2, name: 'peter', gender: 0 }
]
},
filters: {
genderFilter(val) {
if (val == 1) {
return "男";
} else {
return "女";
}
}
}
})
</script>
</body>
组件化
在大型应用开发的时候,页面可以划分成很多部分。往往不同的页面,也会有相同的部分。例如可能会有相同的头部导航。
但是如果每个页面的每个部分都手动开发,这无疑增加了我们开发的成本。所以我们会把页面的不同部分拆分成独立的组件,然后在不同页面就可以共享这些组件,避免重复开发。
在vue里,所有的vue实例都是组件,组件其实也是一个vue实例,因此它在定义时也会接收:data、methods、生命周期函数等,不同的是组件不会与页面的元素绑定(所以不写el),否则就无法复用了,因此没有el属性。 但是组件渲染需要html模板,所以增加了template属性,值就是HTML模板 **data必须是一个函数,不再是一个对象。**因为我们需要复用组件,那么data如果还是一个对象的话可能这个值会出现类似多线程下的值错误一样,但我们定义成了函数之后,每次调用这个函数都会返回一个新的data。 全局组件定义完毕,任何vue实例都可以直接在HTML中通过组件名称来使用组件了 下面的html内容是在说:
- 如果使用vue对象中的el属性指定了值为”#app”,则代表
<div id="app"> 这个块跟下面的new Vue对象绑定 - vue对象里如果指定了components属性,是指:标签里有子标签,
'button-counter': buttonCounter 代表有个组件叫buttonCounter,可以填充标签<button-counter>
全局组件
// 定义一个名为 button-counter的新全局组件
Vue.component('button-counter', {
data: function () { // data是函数
return {
count: 0
}
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>' // 渲染的模板
})
// 上面代码的意思是组件名为button-counter
的html内容为template的内容,然后template中的数据要用data函数进行返回。
全局注册的组件可以用在其被注册之后的任何 (通过 new Vue ) 新创建的 Vue 根实例,也包括其组件树中的所有子组件的模板中。
局部组件
局部组件需要我们像声明一个变量一样声明一个组件,然后把这个组件注册进vue实例的components属性中,这样我们就可以在vue实例绑定的dom中使用这个组件了。
注意:局部注册的组件在其子组件中不可用
<div id="app">
<runoob></runoob>
</div>
<script>
var Child = {
template: '<h1>自定义组件!</h1>'
data: function () {
return {
count: 0
}
}
new Vue({
el: '#app',
components: {
'runoob': Child
}
})
</script>
生命周期钩子函数
每个vue实例在被创建时都要经过一系列的初始化过程:创建实例,装载模板、渲染模板等等。vue为生命周期中的每个状态都设置了钩子函数(监听函数)。每当vue实例处于不同的生命周期时,对应的钩子函数就会被触发调用。
<body>
<div id="app">
<span id="num">{{num}}</span>
<button @click="num++">赞!</button>
<h2>{{name}},有{{num}}个人点赞</h2>
</div>
<script src="../node_modules/vue/dist/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data: {
name: "张三",
num: 100
},
methods: {
show() {
return this.name;
},
add() {
this.num++;
}
},
beforeCreate() {
console.log("=========beforeCreate=============");
console.log("数据模型未加载:" + this.name, this.num);
console.log("方法未加载:" + this.show());
console.log("html模板未加载:" + document.getElementById("num"));
},
created: function () {
console.log("=========created=============");
console.log("数据模型已加载:" + this.name, this.num);
console.log("方法已加载:" + this.show());
console.log("html模板已加载:" + document.getElementById("num"));
console.log("html模板未渲染:" + document.getElementById("num").innerText);但Span内容仍为{{num}}
},
beforeMount() {
console.log("=========beforeMount=============");
console.log("html模板未渲染:" + document.getElementById("num").innerText);
},
mounted() {
console.log("=========mounted=============");
console.log("html模板已渲染:" + document.getElementById("num").innerText);
},
beforeUpdate() {
console.log("=========beforeUpdate=============");
console.log("数据模型已更新:" + this.num);
console.log("html模板未更新:" + document.getElementById("num").innerText);
},
updated() {
console.log("=========updated=============");
console.log("数据模型已更新:" + this.num);
console.log("html模板已更新:" + document.getElementById("num").innerText);
}
});
</script>
</body>
|