前后端对比:
image.png

ES6

ES6简介

ECMAScript 是浏览器脚本语言的规范,而各种我们熟知的 js 语言,如JavaScript则是规范的具体实现;
JavaScript三大组成部分:

  1. **ECMAScript**:语句语法规范;
  2. **BOM**:浏览器对象模型;
  3. **DOM**:文档对象模型;

    ES6新特性

    let 声明变量

    1、

    var声明的变量往往会越域 ,**let**声明的变量有严格局部作用域

    1. <script>
    2. {
    3. var a = 1;
    4. let b = 2;
    5. }
    6. console.log(a);
    7. console.log(b);
    8. </script>

    image.png

    2、

    var可以声明多次,**let**只能声明一次

    1. <script>
    2. var m=1;
    3. var m=3;
    4. let n=2;
    5. </script>

    3、

    var会变量提升,let不存在变量提升

    1. <script>
    2. console.log("x的值:"+x);//声明前使用
    3. var x = 10;
    4. console.log("y的值:"+y);//声明前使用
    5. let y = 20;
    6. </script>

    image.png

    const声明常量(只读变量)

    1. <script>
    2. //1.声明之后不允许改变
    3. //2.一但声明必须初始化,否则会报错
    4. const a=1;
    5. </script>

    解构表达式

    用数组结构赋值(方便)

    1. <script>
    2. let arr=[1,2,3];
    3. //用数组结构将1,2,3分别赋值给x,y,z
    4. let [x,y,z] = arr;
    5. </script>

    对象结构

    1. <script>
    2. //先声明一个常量
    3. const person={
    4. name:"张三",
    5. age:"19",
    6. language:["java","english","chinese"]
    7. }
    8. //将name,age,language三个属性拿出来
    9. const {name,age,language}=person;
    10. //将name的属性值赋值到abc中
    11. const{name:abc}=person;
    12. console.log(name,age,language,abc);
    13. </script>

    字符串扩展

    几个新的 API

    1. <script>
    2. //字符串扩展
    3. let str = "hello.vue";
    4. console.log(str.startsWith("hello"));
    5. //判断是否以"hello"开始,返回true
    6. console.log(str.endsWith(".vue"));
    7. //判断是否以".vueo"结束,返回true
    8. console.log(str.includes("e"));
    9. //判断是否含"e",返回true
    10. console.log(str.includes("hello"));
    11. //判断是否含"hello",返回true
    12. </script>

    字符串模板

    模板字符串相当于加强版的字符串,用反引号 `,除了作为普通字符串,还可以用来定义多行字符串,还可以在字符串中加入变量和表达式。

    </script>       
    //1、声明多行字符串,以前还需要拼串,现在不需要了
    let xml=`
         <div>
           <span>hello world<span> 
         </div>`;
    console.log(xml);
    //2、字符串插入变量和表达式。变量名写在${}中,${}中也可以写表达式,写方法;
    let name1 = "张三"; 
    let age1 = 18; 
    let info = `我是${name1},今年${age1+10}了`; 
    console.log(info)
    </script>
    

    函数优化

    函数参数默认值

    <script>
    /*以前的做法*/
    function add(a, b) { 
     //判断b是否为空,为空就给默认值1 
     b = b || 1; 
     return a + b; 
    }
    // 传一个参数 
    console.log(add(10));
    /*现在新特性的做法*/
    function add1(a,b=1){
     return a+b;
    }
    console.log(add1(10))
    </script>
    

    不定参数

    <script>
    function say(...canshu){
    console.log(canshu.length)//输出参数的个数
    }
    say(1);//输出1个
    say(1,2,3,4,5,6,7,6)//输出8个
    </script>
    

    箭头函数

    </script>
    /*箭头函数*/
    var print1=obj => console.log(obj);
    //只有一个参数且方法体只有一行的方法
    print1("hello")//调用
    
    var print2=(a,b)=>a+b;
    //多个参数,只有一行返回值
    console.log(print2(1,2))
    
    var print3=(a,b)=>{
     c=a+b;
     return c*c;
    }//多个参数,方法体不止一行
    console.log(print3(1,2))
    </script>
    

    对象优化

    ES6 给Object 拓展了许多新的方法,如:

  • keys(obj):获取对象的所有key形成的数组
  • values(obj):获取对象的所有value形成的数组
  • entries(obj):获取对象的所有keyvalue形成的二维数组。格式:[[k1,v1],[k2,v2],...]
  • assign(dest, ...src):将多个src对象的值拷贝到dest中。(第一层为深拷贝,第二层为浅拷贝)

    <script>
      /*1、新增的 API*/
      const person = { 
          name: "jack", 
          age: 21, 
          language: ['java', 'js', 'css'] 
          }
      console.log(Object.keys(person));//["name", "age", "language"] 
      console.log(Object.values(person));//["jack", 21, Array(3)] 
      console.log(Object.entries(person));//打印出key,value
    
      const target = { a: 1 }; 
      const source1 = { b: 2 }; 
      const source2 = { c: 3 }; 
      //Object.assign方法的第一个参数是目标对象,后面的参数都是源对象。 
      Object.assign(target, source1, source2); 
      console.log(target)//输出结果为:{a: 1, b: 2, c: 3}
      /*2、声明对象简写*/
      const age = 23 
      const name = "张三"
      // 传统 
      const person1 = { age: age, name: name } 
      console.log(person1) 
      // ES6:属性名和属性值变量名一样,可以省略 
      const person2 = { age, name } 
      console.log(person2) //{age: 23, name: "张三"}
      /*3、对象的函数属性简写*/
      let person3 = { 
          name: "jack", 
          // 以前: 
          eat: function (food) { 
              console.log(this.name + "在吃" + food); 
          },
          // 箭头函数版:这里拿不到this 
          eat2: food => console.log(person3.name + "在吃" + food), 
          // 简写版: 
          eat3(food) { 
              console.log(this.name + "在吃" + food); 
          }     
      }
      person3.eat("apple");//jack在吃apple
      person3.eat2("apple");//jack在吃apple
      person3.eat3("apple");//jack在吃apple
    </script>
    

    对象拓展运算符

    拓展运算符{...}用于取出参数对象所有可遍历属性然后拷贝到当前对象。

    <script>        
      // 1、拷贝对象(深拷贝) 
      let p1 = { name: "Amy", age: 15 } 
      let someone = { ...p1 }//将p1的属性以及值拷贝到someone中
      // 2、合并对象 
      let myage = { age: 15 } 
      let myname = { name: "Amy" } 
      let p2 = { ...myage, ...myname }//将这两者的属性以及值拷贝到p2中
      //如果两个对象的字段名重复,后面对象字段值会覆盖前面对象的字段值 
      console.log(p2) //{age: 15, name: "Amy"}
    </script>
    

    mapreduce方法

    数组中新增了mapreduce方法。

    map

    接收一个函数,将原数组中的所有元素用这个函数处理后放入新数组返回。

    <script>
      let arr = ['1', '20', '-5', '3']; 
      console.log(arr) 
      //数组中的字符都转化为数字,并*2
      arr = arr.map(s => parseInt(s)*2); 
      console.log(arr) 
    </script>
    

    reduce

    语法: arr.reduce(callback,[initialValue])
    **reduce**为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:初始值(或者上一次回调函数的返回值),当前元素值,当前索引,调用**reduce**的数组。
    **callback**(执行数组中每个值的函数,包含四个参数)

  • previousValue(上一次调用回调返回的值,或者是提供的初始值(initialValue))

  • currentValue(数组中当前被处理的元素)
  • index(当前元素在数组中的索引)
  • array(调用reduce的数组)

initialValue(作为第一次调用callback的第一个参数。)

<script>
    let arr1 = [2, 40, -10, 6]; 
    let result=arr.reduce((a,b) => {
        console.log("上一次处理后:"+a)
        console.log("当前正在处理:"+b)
        return a+b;
    },100)
    console.log(result);
</script>

image.png

Promise

JavaScript的世界中,所有代码都是单线程执行的。由于这个“缺陷”,导致JavaScript的所有网络操作,浏览器事件,都必须是异步执行。异步执行可以用回调函数实现。一旦有一连串的ajax请求a,b,c,d...后面的请求依赖前面的请求结果,就需要层层嵌套。这种缩进和层层嵌套的方式,非常容易造成上下文代码混乱,我们不得不非常小心翼翼处理内层函数与外层函数的数据,一旦内层函数使用了上层函数的变量,这种混乱程度就会加剧……总之,这种层叠上下文的层层嵌套方式,着实增加了神经的紧张程度。

场景

  1. 查出当前用户信息;
  2. 按照当前用户的id查出他的课程;
  3. 按照当前课程id查出分数;
    传统嵌套方法(比较乱)
    <script>
     /*
         1、查出当前用户信息
         2、按照当前用户的id查出他的课程
         3、按照当前课程id查出分数
     */
     //以前的方法
     $.ajax({
         url:"mock/user.json",
         success(data){
             console.log("查询用户:",data);
             $.ajax({
                 url:`mock/user_corse_${data.id}.json`,
                 success(data){
                     console.log("查询到课程:",data);
                     $.ajax({
                         url:`mock/corse_score_${data.id}.json`,
                         success(data){
                             console.log("查询到课程分数:",data); 
                         }
                     });
                 },
             });
         },
     });
    </script>
    
    使用Promise
    <script>
     //使用promise封装异步操作
     //1、先声明一个公用函数
     function get(url,data){
         return new Promise((ifsuccess,iferror)=>{
             $.ajax({
                 url:url,
                 data:data,
                 success:function(data){
                     ifsuccess(data)//成功的话
                 },
                 error:function(err){
                     iferror(data)//失败的话
                 }
             });
         });
     }
     //2、进行操作
     get("mock/user.json")
         .then((data)=>{//动态取值就需要用``号不能用双引号
             console.log("查询用户:",data);
             return get(`mock/user_corse_${data.id}.json`); 
         }).then((data)=>{//then得到上一步成功的数据
             console.log("查询到课程:",data);
             return get(`mock/corse_score_${data.id}.json`); 
         }).then((data)=>{
             console.log("查询到课程成绩:",data);
         }).catch((err)=>{
             console.log("出现异常:",err);
         });
    </script>
    

    模块化

    什么是模块化

    模块化就是把代码进行拆分,方便重复利用。类似java中的导包:要使用一个包,必须先 导包。而JS中没有包的概念,换来的是模块
    模块功能主要由两个命令构成:exportimport
  • export命令用于规定模块的对外接口。
  • import命令用于导入其他模块提供的功能。

    导出export

    const util={
    sum(a,b){
      return a+b;
    }
    }
    var name="zzk"
    export {util,name}
    //还可以简写为:
    // export const util={
    //     sum(a,b){
    //         return a+b;
    //     }
    // }
    

    export不仅可以导出对象,一切JS变量都可以导出。比如:基本类型变量、函数、数组、对象。
    image.png

    导入import

    import util from "./hello.js"//“./”一个点“.”代表当前目录
    import name from "./hello.js"
    //也可以直接import {util,name} from "./hello.js"
    var c=util.sum(1,2)
    console.log(c)
    console.log(name)
    

    vue

    更多信息访问vue官网:vuejs.org

    MVVM思想

  • M:即 Model,模型,包括数据和一些基本操作;

  • V:即 View,视图,页面渲染结果;
  • VM:即 View-Model,模型与视图间的双向操作(无需开发人员干涉);

MVVM之前,开发人员从后端获取需要的数据模型,然后要通过DOM操作Model渲染到View中。而后当用户操作视图,我们还需要通过DOM获取View中的数据,然后同步到Model中;
MVVM中的VM要做的事情就是把DOM操作完全封装起来,开发人员不用再关心ModelView之间是如何互相影响的:

  • 只要我们Model发生了改变,View上自然就会表现出来。
  • 当用户修改了ViewModel中的数据也会跟着改变。

把开发人员从繁琐的DOM操作中解放出来,把关注点放在如何操作Model上。
image.png

安装

npm安装:**npm install vue**(安装最新稳定版)之后通过**<script>**标签引入
【注意:npm安装的话你的project名不能和安装的依赖同名】
也可以直接下载然后**<script>**标签下引入;
npm安装:

  • 先执行初始化命令**npm init -y**表示此项目交由npm管理,之后就会生成一个文件package.json
  • 之后再执行命令**npm install vue**安装(如果安装特定版本可以直接在**vue**后面加**@版本号**);

    使用

    helloworld程序:

    <div id="app">
    <h1>{{name}},很帅</h1>
    </div>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script>
    let vm=new Vue({
      el: "#app",
      data: {
        name: "张三"
      }
    })
    </script>
    

    而且页面数据还可以根据前端控制台输入动态改变:
    image.png

    双向绑定

    效果:我们修改表单项,num会发生变化。我们修改 num,表单项也会发生变化。为了实时观察到这个变化,我们将num输出到页面。
    我们不需要关注他们为什么会建立起来关联,以及页面如何变化,我们只需要做好数据和视图的关联即可(MVVM)

    <div id="app">
    <input type="text" v-model="num">
    <h1>{{name}},很帅,{{num}}人为他点赞</h1>
    </div>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script>
    let vm=new Vue({
      //属性名和属性值一样的时候可以只写“属性(名|值),”
      el: "#app",
      data: {
        name: "张三",
        num: 1
      }
    })
    </script>
    

    image.png
    输入框标签里面添加一个属性_v-model_并赋值,在需要输出的地方_{{这个属性值}}_,然后在vue对象的data属性值添加上该值并附上默认值即可;

    事件处理

    在标签中添加一个属性v-on:xxx="xxx",其中xxx为要对某个属性做的操作,例如还是上面的例子,我添加一个<button_v-on:click_="num++">点赞</button>则每点击一次则vue实例中data属性中的num属性就会+1;
    还可以单独写一个方法,点击时调用这个方法来操作数据(把方法都放在vue实例的methods属性里面);

    <button v-on:click="cancle">取消点赞</button>
    ...
    <script>
    let vm=new Vue({
      el: "#app", //与某元素绑定属性
      data: {            //封装数据
        name: "张三",
        num: 11
      },
      methods:{        //封装方法
        cancle(){
          this.num--;
        }
      }
    })
    </script>
    

    指令

    v-textv-html

    可以使用v-textv-html指令来替代双大括号{{}}

    说明:
  • **v-text**:将数据输出到元素内部,如果输出的数据有HTML代码,会作为普通文本输出;

  • **v-html**:将数据输出到元素内部,如果输出的数据有HTML代码,会被渲染;
  • 只能用在标签体里面;

    v-bind(单向绑定)

    **v-bind**给html标签的属性进行绑定(即双引号里面的内容)

    <!-- 给html标签的属性进行绑定 -->
    <div id="app">
    <a v-bind:href="link">go baidu</a>
    </div>
    <script src="../node_modules/vue/dist/vue.js"></script>
    <script>
    new Vue({
      el: "#app",
      data:{
        link: "http://www.baidu.com"
      },
    });
    </script>
    

    image.png
    并且还对属性styleclass做了单独的增强:

    <!-- 给html标签的属性进行绑定 -->
    <div id="app">
    <a v-bind:href="link">go baidu</a><br>
    <!-- 还对class属性和style属性进行了增强 -->
    <span v-bind:class="{active:isActive,'text-danger':hasError}" 
          v-bind:style="{color:clo,fontSize:fsize}">测试</span>
    <!-- 根据isActive的bool值进行判断是否class="active" -->
    <!--根据hasError的bool值进行判断是否class="'text-danger'"
              (因为“-”是非法的,所以加个单引号,也可直接驼峰命名textDnger)-->
    <!-- 下面同理 -->
    </div>
    <script src="../node_modules/vue/dist/vue.js"></script>
    <script>
    new Vue({
      el: "#app",
      data:{
        link: "http://www.baidu.com",
        isActive:false,
        hasError:true,
        clo:'red',
        fsize: '66px'
      },
    });
    

    image.png

    v-model(双向绑定)

    <div id="app">
    请选择: <br>  
    <input type="checkbox" v-model="language" value="java"><br>
    <input type="checkbox" v-model="language" value="phpa"><br>
    <input type="checkbox" v-model="language" value="golang"><br>
    你选择的有:
    <span v-text="language"></span>
    </div>
    <script>
    let vm=new Vue({
      el:"#app",
      data:{
        language:[]
        //选中的属性值把存在language的数组里面
      },
    })
    </script>
    

    image.png

    <div id="app">
    <h1>你写的是:{{msg}}</h1>
    <br>
    <input type="text" v-model:value="msg">
    <!--value可省略,即写为v-modele="msg"-->
    </div>
    <script>
    new Vue({
      el: '#app',
      data: {
        msg:""
      }
    })
    </script>
    

    image.png

    v-on

    基础用法

    调用事件,例如调用点击事件:

    <div id="app">
    <button v-on:click="numAdd">+{{num}}</button><br>
    <!--也可以简写:@click=xxx-->
    <span v-text="num"></span>
    </div>
    <script>
    new Vue({
      el:"#app",
      data:{
        num: 1
      },
      methods:{
        numAdd(){
          this.num+=2
        }
      }
    });
    </script>
    

    事件修饰符

    事件冒泡问题:子元素的操作连带了父元素;例如:

    <div id="try" v-on:click="hello">
          大div <br>
          <div @click="hello">
              小div
          </div>
      </div>
      <script>
          new Vue({
              el: '#try',
              methods:{
                  hello(){
                      alert("点击了")
                  }
              },
          });
    </script>
    

    这样的话点击“小div”的话就会alert("点击了")两次,这就属于时间冒泡事件;
    为了解决这个问题,Vue.js 为 v-on提供了事件修饰符。修饰符是由点开头的指令后缀来表示的。

  • .stop :阻止事件冒泡到父元素;

  • .prevent:阻止默认事件发生;
  • .capture:使用事件捕获模式;
  • .self:只有元素自身触发事件才执行。(冒泡或捕获的都不执行)
  • .once:只执行一次;

这里就可以用:<div_@click.stop_="hello">

按键修饰符(v-on:keyup@keyup)

在监听键盘事件时,我们经常需要检查常见的键值。Vue允许为v-on在监听键盘事件时添加按键修饰符;
全部的按键别名:

  • .enter
  • .tab
  • .delete
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

例如:在一个输入框内按”上键”数值增加,按”下键”数值减少,如下:
<inputv-model="num1"type="text"v-on:keyup.up="num1++"@keyup.down="num1--">
也可以用设置组合键,例如:
<inputv-model="num1"@click.ctrl="num1+=10">
这样ctrl+单击数据就会+10;

v-for

遍历用的;

<div id="app">
  <ul>
    <li v-for="(user,index) in users":key="user.name">
      <!--遍历的时候加上“:key”来区分不同数据,提高vue渲染效率,key值为数据里面的唯一属性-->
      <!--第一个参数是值,第二个参数值索引-->
      当前索引:{{index}};当前元素值:{{user.name}}--->{{user.age}} <br>
    </li>
  </ul>
</div>
<script>
  new Vue({
    el:"#app",
    data:{
      //定义一个对象数组
      users:[ 
        {name:"张三",age:12},
        {name:"李宗盛",age:22},
        {name:"瘦鸡",age:32},
        {name:"事件",age:42},
        {name:"微软",age:15},
      ]
    }
  });
</script>

v-ifv-show

<h1 v-if="bool">如果bool=true就看到我v-if</h1><br>
<h1 v-show="bool">如果bool=true就看到我v-show</h1><br>

不同的是当bool=falsev-if所在元素是消失,而v-show所在元素是用style="display: none;"修饰:
image.png

计算属性和侦听器

<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>
  </ul>
  {{msg}}
</div>
<script>
  new Vue({
    el: '#app',
    data:{
      xyjPrice: 190.1,
      shzPrice: 12.12,
      xyjNum: 1,
      shzNum: 1,
      msg: "",
    },
    computed:{//声明一个计算属性
      totalPrice(){//完成总价的计算
        return this.xyjNum*this.xyjPrice+this.shzNum*this.shzPrice
      }
    },
    watch:{//声明一个监听器,监听西游记的数量
      xyjNum: function(newVal,oldVal){
        //新式语法可以直接写为: xyjNum:(..){..}   
        if(newVal>3){
          this.msg="购买数量过多"
        }else{
          this.msg=""
        }
      }
    },
  });
</script>

image.png

过滤器

过滤器不改变真正的data,而只是改变渲染的结果,并返回过滤后的版本。在很多不同的情况下,过滤器都是有用的,比如尽可能保持API响应的干净,并在前端处理数据的格式。

<div id="app">
  <ul>
    <li v-for="user in userList">
      {{user.id}}===>{{user.name}}==>{{user.age}}
      ==>{{user.age|ageFilter}}==>{{user.age|gFilter}}<br>
      <!--用管道符“|”将user.age传入ageFilter方法的参数中-->
    </li>
  </ul>
</div>
<script>
  //声明一个全局过滤器
  //(必须声明在局部过滤器之前,否则全局过滤器失效)
  Vue.filter("gFilter",function(val){
    if(val>=18){
      return"成年~~~~~";
    }else{
      return"未成年~~~~";
    }
  });
  new Vue({
    el:"#app",
    data:{
      userList:[
        {id:1,name:"张三",age:13},
        {id:2,name:"张静怡",age:23},
        {id:3,name:"张诺",age:17},
      ]
    },
    filters:{//声明一个局部过滤器
      ageFilter(val){
        if(val>=18){
          return"成年";
        }else{
          return"未成年";
        }
      }
    },
  }); 
</script>

组件化

在大型应用开发的时候,页面可以划分成很多部分。往往不同的页面,也会有相同的部分。例如可能会有相同的头部导航。 但是如果每个页面都独自开发,这无疑增加了我们开发的成本。
所以我们会把页面的不同部分拆分成独立的组件,然后在不同页面就可以共享这些组件,避免重复开发。在vue里,所有的vue实例都是组件;

全局组件

<div id="app">
  <counter></counter> <!--调用自定义全局组件-->
  <!--用组件名声明一个标签名 -->
</div>
<script>    
  //1、全局声明注册一个组件
  Vue.component('counter',{//参数是组件名
    template: '<button @click="count++">我被点击了{{count}}次</button>',
    data(){
      return{count:1}
    }
  });
  new Vue({
    el:"#app",
    data:{
      count: 1,
    }
  });
</script>
  • 组件其实也是一个**Vue**实例,因此它在定义时也会接收:datamethods生命周期函数
  • 不同的是组件不会与页面的元素绑定,否则就无法复用了,因此没有el属性。
  • 但是组件渲染需要html模板,所以增加了template属性,值就是HTML模板 ;
  • 全局组件定义完毕,任何vue实例都可以直接在HTML中通过组件名称来使用组件了
  • data必须是一个函数,不再是一个对象;

image.png

局部组件

一旦全局注册,就意味着即便以后你不再使用这个组件,它依然会随着Vue的加载而加载。因此,对于一些并不频繁使用的组件,我们会采用局部注册。

<div id="root"> 
  <!--调用自定义局部组件-->
  <my-counter></my-counter>
</div>
<script>
  //声明一个局部组件
  const myCounter={
    template: '<button @click="count++">我被点击{{count}}次</button>',
    data(){
      return{count:1}
    }
  };
  new Vue({
    el:"#root",
    data:{
      count:1
    },
    //components就是当前vue对象子组件集合。
    components:{//在此放入所有自定义局部组件
      'my-counter':myCounter
    }
  });
</script>

组件的**data**属性必须是函数!一个组件的data选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝;
image.png

Vue生命周期和钩子函数

生命周期

每个Vue实例在被创建时都要经过一系列的初始化过程 :创建实例,装载模板,渲染模板等等。Vue为生命周期中的每个状态都设置了钩子函数(监听函数)。每当Vue实例处于不同的生命周期时,对应的函数就会被触发调用。
image.png

钩子函数使用

  • beforeCreated:我们在用Vue时都要进行实例化,因此,该函数就是在Vue实例化时调用,也可以将他理解为初始化函数比较方便一点,在Vue1.0时,这个函数的名字就是init。
  • created:在创建实例之后进行调用。
  • beforeMount:页面加载完成,没有渲染。如:此时页面还是{{name}}
  • mounted:我们可以将他理解为原生js中的window.onload=function({.,.});或许大家也在用jquery,所以也可以理解为jquery中的$(document).ready(function(){….}),他的功能就是:在dom文档渲染完毕之后将要执行的函数,该函数在 Vue1.0 版本中名字为compiled。 此时页面中的{{name}}已被渲染成张山;
  • beforeDestroy:该函数将在销毁实例前进行调用。
  • destroyed:改函数将在销毁实例时进行调用。
  • beforeUpdate:组件更新之前。
  • updated:组件更新之后。

    <div id="root">
    <button @click="age++">{{name}}:{{age}}</button>
    </div>
    <script>
    new Vue({
      el: '#root',
      data:{
        name:"张山",
        age:1,
      },
      beforeCreate() {
        console.log("数据模型加载前");
      },
      created(){
        console.log("数据模型加载完成");
      },
      beforeMount(){
        console.log("页面加载完成,没有渲染");
      },
      beforeDestroy(){
        console.log("实例销毁前");
      },
      destroyed(){
        console.log("实例销毁完成");
      },
      beforeUpdate(){
        console.log("准备修改")
      }
    });
    </script>
    

    image.png

    使用Vue脚手架进行模块化开发

    初始化步骤:

    1、全局安装webpack:npm install webpack -g
    2、安装vue脚手架(这里与老师版本一致4.0.3):npm i -g @vue/cli@4.0.3 --force

    • (--force表示覆盖以前的vue脚手架版本)
    • 可用命令vue-V检查所安装vue脚手架版本或是否安装成功vue脚手架;

3、初始化项目:vue init webpack 项目名vue脚手架使用webpack模板初始化项目)
4、进入都初始化项目的vue-demo目录里面,执行语句npm run dev项目运行,运行成功浏览器访问http://localhost:8080/,如下:
image.png

项目结构

image.png
image.png
运行流程:

  • 进入页面首先加载index.htmlmain.js文件。
  • main.js导入了一些模块【vue、app、router】,并且创建vue实例,关联index.html页面的<div id=”app”>元素。使用了router,导入了App组件。并且使用<App/>标签引用了这个组件;
  • 第一次默认显示App组件。App组件有个图片和<router-view>,所以显示了图片。但是由于<router-view>代表路由的视图,默认是访问/#/路径(router路径默认使用HASH模式)。在router中配置的/是显示HelloWorld组件。
  • 所以第一次访问,显示图片和HelloWorld组件。
  • 我们尝试自己写一个组件,并且加入路由。点击跳转。需要使用<router-link to="/foo">Go to Foo</router-link>标签;

    手动构建一个单文件组件

    // 组件三要素:template,script,style
    <template>
      <div>
          <h1>你好hello{{name}}</h1>
      </div>
    </template>
    <script>
    export default{
      data() {
          return {
              name: '张静怡',
          };
      },
    }
    </script>
    <style>
    </style>
    

    然后在**router**里面加上这个vue的路由;

    ...
    import Hello from '@/components/Hello'
    //引入刚才创建的Hello.vue
    ...
    //下面创建这个路由
    {
    path: '/hello',
    name: "hello",
    component: Hello,
    }
    

    详情见官网:vueRouter

    Vue整合ElementUI快速开发

    elementUI组件库网址:element.eleme.cn

  • npm安装:npm i element-ui -S(也可以手动下载下来)

  • 之后在main.js里面引入:
    • importElementUIfrom'element-ui';
    • import'element-ui/lib/theme-chalk/index.css';
  • 之后让Vue使用ElementUIVue.use(ElementUI)
  • 然后根据自己的需要在组件库选取组件使用;

    axios

    axios是独立于vue的一个项目,基于promise用于浏览器和node.jshttp客户端;

  • 在浏览器中可以帮助我们完成ajax请求的发送;

  • node.js中可以向远程接口发送请求;

    nodejs

    nodejs**JavaScript**运行环境,类似于java里面的jdk,不需要浏览器通过nodejs直接运行js文件;

    简介

    什么是Node.js

    简单的说Node.js就是运行在服务端的JavaScript
    Node.js是一个事件驱动I/O服务端JavaScript环境,基于GoogleV8引擎,V8引擎执行Javascript的速度非常快,性能非常好。

    Node.js有什么用

  • 如果你是一个前端程序员,你不懂得像PHP、Python或Ruby等动态编程语言,然后你想创建自己的服务,那么Node.js是一个非常好的选择。

  • Node.js是运行在服务端的JavaScript,如果你熟悉Javascript,那么你将会很容易的学会Node.js
  • 当然,如果你是后端程序员,想部署一些高性能的服务,那么学习Node.js也是一个非常好的选择。

**cmd**查看**nodejs**版本:**node -v**

npm

npm简介

什么是npm

npm全称Node Package Manager,是Node.js包管理工具,是全球最大的模块生态系统,里面所有的模块都是开源免费的;也是Node.js的包管理工具,相当于前端的Maven

npm工具的安装位置

我们通过npm可以很方便地下载**js**库,管理前端工程。
Node.js默认安装的npm包和工具的位置:Node.js目录\node_modules

  • 在这个目录下你可以看见npm目录,npm本身就是被npm包管理器管理的一个工具,说明 Node.js已经集成了npm工具;
  • **cmd**查看npm版本:npm** -v**

    使用

    项目初始化

    **cmd**在目标文件夹内执行命令**npm init**执行初始化(会让你选择默认js文件name属性,vue版本等信息,也可以直接执行**npm init -y**全部使用默认值);

    按照提示输入相关信息,如果是用默认值则直接回车即可。

    name:项目名称;

    version:项目版本号;

    description:项目描述;

    keywords:{Array}关键词,便于用户搜索到我们的项目;

    最后会生成package.json文件,这个是包的配置文件,相当于mavenpom.xml

    我们之后也可以根据需要进行修改。

修改npm镜像

  • 设置淘宝镜像npm config set registry https://registry.npm.taobao.org
  • 查看**npm**配置信息npm config list
  • 测试,比如下载**jquery**npm install jquery
  • 也可以直接根据配置文件下载:直接根据配置文件下载,直接执行npm install
    • image.png
      • #使用**npm install**安装依赖包的最新版,
      • #模块安装的位置:**项目目录\node_modules**
      • #安装会自动在项目目录下添加**package-lock.json**文件,这个文件帮助锁定安装包的版本
      • #同时**package.json**文件中,依赖包会被添加到**dependencies**节点下,类似**maven**中的 **<dependencies>**
      • #**npm**管理的项目在备份和传输的时候一般不携带**node_modules**文件夹

      **npm install**

      • #根据**package.json**中的配置下载依赖,初始化项目

      **npm install jquery@指定版本号**

      • #如果安装时想指定特定的版本

      # 局部安装:依赖只在当前项目中能用

      • #**devDependencies**节点:开发时的依赖包,项目打包到生产环境的时候不包含的依赖
      • #使用-D参数将依赖添加到**devDependencies**节点
      • **npm install --save-dev eslint**#或**npm install -D eslint**

      #全局安装

      • #Node.js全局安装的npm包和工具的位置:**用户目录\AppData\Roaming\npm\node_modules**
      • #一些命令行工具常使用全局安装的方式
      • **npm install -g webpack**

#更新包(更新到最新版本) npm update 包名 #全局更新 npm update -g 包名 #卸载包 npm uninstall 包名 #全局卸载 npm uninstall -g 包名

模块化开发

首先在文件夹中初始化:npm init

es5写法

自定义方法

//定义两个自定义方法
const sum=function(a,b){
    return parseInt(a)+parseInt(b);
}
const subtract=function(a,b){
    return parseInt(a)-parseInt(b);
}
//设置2个方法可以被其他js调用
module.exports={
    sum,subtract
}

调用自定义方法

/*调用自定义方法*/
const m=require('./myMethod.js')
console.log(m.sum(1,1));
console.log(m.subtract(1,1));

结果

PS E:\IDEAworks\classroom\moduleDemo\es5> node .\useMyMethod.js 2 0

es6写法

注:**es6不能直接用,需要进行转码,转码过程较为复杂,之后在框架中会直接进行转码,这里不转码**

自定义方法

/*自定义方法:myMethod.js*/
//定义两个可以被其他js调用的自定义方法
//定义方法-1
export function sum(a,b){
    return parseInt(a)+parseInt(b);
}
export function subtract(a,b){
    return parseInt(a)-parseInt(b);
}
//定义方法-2
export default{
    sum(a,b){
        return parseInt(a)+parseInt(b);
    },
    subtract(a,b){
        return parseInt(a)-parseInt(b);
    }
}

调用自定义方法

/*调用自定义方法:useMyMethod.js*/
//调用方法-1
import {sum,subtract} from "./myMethod1.js"
console.log(sum(1,1));
console.log(subtract(1,1));
//调用方法-2
import * as m from "./myMethod1.js"
console.log(m.sum(1,1));
console.log(m.subtract(1,1));

跨域问题

比如前后端调用,**3**个地方:**访问协议****访问ip****端口号**有任何一个不一样就会产生跨域问题,不能正常访问,跨域问题本质是浏览器对ajax请求的一种限制;

解决

  1. 在后端接口controller添加注解**@CrossOrigin**
  2. 使用httpclient
  3. 通过gateway网关;