T O P

[资源分享]     两万字Vue.js基础学习笔记(一)

  • By - 楼主

  • 2021-07-28 00:00:01
  • Vue.js学习笔记(一)

    Vue 的核心库只关注视图层,方便与第三方库或既有项目整合。

    HTML + CSS + JS : 视图 : 给用户看,刷新后台给的数据

    网络通信 : axios

    页面跳转 : vue-router

    状态管理:vuex

    Vue-UI : ICE , Element UI

    1. VUE 概述
      Vue (读音/vju/, 类似于view)是一套用于构建用户界面的渐进式框架,发布于2014年2月。与其它大型框架不同的是,Vue被设计为可以自底向上逐层应用。Vue的核心库只关注视图层,不仅易于上手,还便于与第三方库(如: vue-router: 跳转,vue-resource: 通信,vuex:管理)或既有项目整合
    2. 前端三要素
      HTML (结构) :超文本标记语言(Hyper Text Markup Language) ,决定网页的结构和内容
      CSS (表现) :层叠样式表(Cascading Style sheets) ,设定网页的表现样式
      JavaScript (行为) :是一种弱类型脚本语言,其源代码不需经过编译,而是由浏览器解释运行,用于控制网页的行为
    3. JavaScript框架
      jQuery: 大家熟知的JavaScript框架,优点是简化了DOM操作,缺点是DOM操作太频繁,影响前端性能;在前端眼里使用它仅仅是为了兼容IE6、7、8;

    Angular: Google收购的前端框架,由一群Java程序员开发,其特点是将后台的MVC模式搬到了前端并增加了模块化开发的理念,与微软合作,采用TypeScript语法开发;对后台程序员友好,对前端程序员不太友好;最大的缺点是版本迭代不合理(如: 1代-> 2代,除了名字,基本就是两个东西;截止发表博客时已推出了Angular6)

    React: Facebook出品,一款高性能的JS前端框架;特点是提出了新概念[虚拟DOM]用于减少真实DOM操作,在内存中模拟DOM操作,有效的提升了前端渲染效率;缺点是使用复杂,因为需要额外学习一门[JSX] 语言;

    Vue:一款渐进式JavaScript框架,所谓渐进式就是逐步实现新特性的意思,如实现模块化开发、路由、状态管理等新特性。其特点是综合了Angular (模块化)和React (虚拟DOM)的优点;

    Axios :前端通信框架;因为Vue 的边界很明确,就是为了处理DOM,所以并不具备通信能力,此时就需要额外使用一个通信框架与服务器交互;当然也可以直接选择使用jQuery提供的AJAX通信功能;

    前端三大框架:Angular、React、Vue

    ES6语法

    1.不一样的变量声明:const和let

    ES6推荐使用let声明局部变量,相比之前的var(无论声明在何处,都会被视为声明在函数的最顶部)
    let和var声明的区别:

    var x = '全局变量';
    {
      let x = '局部变量';
      console.log(x); // 局部变量
    }
    console.log(x); // 全局变量
    
    <body>
      <button>按钮1</button>
      <button>按钮2</button>
      <button>按钮3</button>
      <button>按钮4</button>
      <button>按钮5</button>
      <script>
        // 变量作用域:变量在什么位置内是可用的
        // ES5之前因为if和for都没有块级作用域的概念,所以在很多时候,我们都必须借助于function的作月域来解决应用外面变量的问题
        // 闭包可以解决这个问题: 函数是一个作用域
        // ES6中加入了let,let它是有if和for块级作用域
    
        // ES5语法
        // var btns = document.getElementsByTagName('button');
        // for(var i = 0; i<btns.length; i++){
        //   (function(num){
        //     bnts[num].addEventListener('click',function(){
        //       console.log('第'+num+'个按钮被点击');
        //     })
        //   })(i)
        // }
    
        // ES6语法
        const btns = document.getElementsByTagName('button')
        for (let i = 1; i < btns.length; i++) {
          btns[i].addEventListener('click', function () {
            console.log('第' + i + '个按钮被点击');
          })
        }
      </script>
    </body>
    

    let表示声明变量,而const表示声明常量,两者都为块级作用域;

    const 声明的变量都会被认为是常量,意思就是它的值被设置完成后就不能再修改了,且const定义标识符时,必须赋值:

    建议:在ES6开发中,优先使用const,只有需要改变某一个标识符的时候才使用let。

    const a = 1
    a = 0 //报错
    

    如果const的是一个对象,对象所包含的值(内部属性)是可以被修改的。抽象一点儿说,就是对象所指向的地址没有变就行:

    const student = { name: 'cc' }
    
    student.name = 'yy';// 不报错
    student  = { name: 'yy' };// 报错
    

    有几个点需要注意:

    • let 关键词声明的变量不具备变量提升(hoisting)特性
    • let 和 const 声明只在最靠近的一个块中(花括号内)有效
    • 当使用常量 const 声明时,请使用大写变量,如:CAPITAL_CASING
    • const 在声明时必须被赋值

    2.模板字符串

    在ES6之前,我们往往这么处理模板字符串:
    通过“\”和“+”来构建模板

    $("body").html("This demonstrates the output of HTML \
    content to the page, including student's\
    " + name + ", " + seatNumber + ", " + sex + " and so on.");
    

    而对ES6来说

    1. 基本的字符串格式化。将表达式嵌入字符串中进行拼接。用${}来界定;
    2. ES6反引号(``)直接搞定;
    $("body").html(`This demonstrates the output of HTML content to the page, 
    including student's ${name}, ${seatNumber}, ${sex} and so on.`);
    

    3.箭头函数(Arrow Functions)

    ES6 中,箭头函数就是函数的一种简写形式,使用括号包裹参数,跟随一个 =>,紧接着是函数体;

    箭头函数最直观的三个特点。

    • 不需要 function 关键字来创建函数
    • 省略 return 关键字
    • 继承当前上下文的 this 关键字
    // ES5
    var add = function (a, b) {
        return a + b;
    };
    // 使用箭头函数
    var add = (a, b) => a + b;
    
    // ES5
    [1,2,3].map((function(x){
        return x + 1;
    }).bind(this));
        
    // 使用箭头函数
    [1,2,3].map(x => x + 1);
    

    细节:当你的函数有且仅有一个参数的时候,是可以省略掉括号的。当你函数返回有且仅有一个表达式的时候可以省略{} 和 return;

    4. 函数的参数默认值

    在ES6之前,我们往往这样定义参数的默认值:

    // ES6之前,当未传入参数时,text = 'default';
    function printText(text) {
        text = text || 'default';
        console.log(text);
    }
    
    // ES6;
    function printText(text = 'default') {
        console.log(text);
    }
    
    printText('hello'); // hello
    printText();// default
    

    5.Spread / Rest 操作符

    Spread / Rest 操作符指的是 ...,具体是 Spread 还是 Rest 需要看上下文语境。

    当被用于迭代器中时,它是一个 Spread 操作符:

    function foo(x,y,z) {
      console.log(x,y,z);
    }
     
    let arr = [1,2,3];
    foo(...arr); // 1 2 3
    

    当被用于函数传参时,是一个 Rest 操作符:当被用于函数传参时,是一个 Rest 操作符:

    function foo(...args) {
      console.log(args);
    }
    foo( 1, 2, 3, 4, 5); // [1, 2, 3, 4, 5]
    

    6.二进制和八进制字面量

    ES6 支持二进制和八进制的字面量,通过在数字前面添加 0o 或者0O 即可将其转换为八进制值:

    let oValue = 0o10;
    console.log(oValue); // 8
     
    let bValue = 0b10; // 二进制使用 `0b` 或者 `0B`
    console.log(bValue); // 2
    

    7.对象和数组解构

    // 对象
    const student = {
        name: 'Sam',
        age: 22,
        sex: '男'
    }
    // 数组
    // const student = ['Sam', 22, '男'];
    
    // ES5;
    const name = student.name;
    const age = student.age;
    const sex = student.sex;
    console.log(name + ' --- ' + age + ' --- ' + sex);
    
    // ES6
    const { name, age, sex } = student;
    console.log(name + ' --- ' + age + ' --- ' + sex);
    

    8.对象超类

    ES6 允许在对象中使用 super 方法:

    var parent = {
      foo() {
        console.log("Hello from the Parent");
      }
    }
     
    var child = {
      foo() {
        super.foo();
        console.log("Hello from the Child");
      }
    }
     
    Object.setPrototypeOf(child, parent);
    child.foo(); // Hello from the Parent
                 // Hello from the Child
    

    9.for...of 和 for...in

    for...of 用于遍历一个迭代器,如数组:

    let letters = ['a', 'b', 'c'];
    letters.size = 3;
    for (let letter of letters) {
      console.log(letter);
    }
    // 结果: a, b, c
    

    for...in 用来遍历对象中的属性:

     let stus = ["Sam", "22", "男"];
     for (let stu in stus) {
       console.log(stus[stu]);
      }
    // 结果: Sam, 22, 男
    

    10.ES6中的类

    ES6 中支持 class 语法,不过,ES6的class不是新的对象继承模型,它只是原型链的语法糖表现形式。

    函数中使用 static 关键词定义构造函数的的方法和属性:

    class Student {
      constructor() {
        console.log("I'm a student.");
      }
     
      study() {
        console.log('study!');
      }
     
      static read() {
        console.log("Reading Now.");
      }
    }
     
    console.log(typeof Student); // function
    let stu = new Student(); // "I'm a student."
    stu.study(); // "study!"
    stu.read(); // "Reading Now."
    

    类中的继承和超集:

    class Phone {
      constructor() {
        console.log("I'm a phone.");
      }
    }
     
    class MI extends Phone {
      constructor() {
        super();
        console.log("I'm a phone designed by xiaomi");
      }
    }
     
    let mi8 = new MI();
    

    extends 允许一个子类继承父类,需要注意的是,子类的constructor 函数中需要执行 super() 函数。
    当然,你也可以在子类方法中调用父类的方法,如super.parentMethodName()。
    在 这里 阅读更多关于类的介绍。

    有几点值得注意的是:

    • 类的声明不会提升(hoisting),如果你要使用某个 Class,那你必须在使用之前定义它,否则会抛出一个 ReferenceError 的错误
    • 在类中定义函数不需要使用 function 关键词

    1、基本认识vue

    • 轻量级,体积小是一个重要指标。Vue.js 压缩后有只有 20多kb (Angular 压缩后 56kb+,React 压缩后 44kb+)
    • 移动优先。更适合移动端,比如移动端的 Touch 事件
    • 易上手,学习曲线平稳,文档齐全
    • 吸取了 Angular(模块化)和 React(虚拟 DOM)的长处,并拥有自己独特的功能,如:计算属性
    • Vue是一个渐进式的框架可以将Vue作为你应用的一 部分嵌入其中,带来更丰富的交互体验。
    • 开源,社区活跃度高
    • Vue有很多特点和Web开发中常见的高级功能
      • 解耦视图和数据.
      • 可复用的组件
      • 前端路由技术
      • 状态管理
      • 虚拟DOM

    下载地址

    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
    
    • NPM安装

    初识vue.js

    <body>
        
        <div id="app">{{message}}</div> //执行到这里显然出对应的HTML
    
        <script src="../js/vue.js"></script>
        <script>
            //执行这里创建Vue实例,并且对原HTML进行解析和修改。
            //编程范式:声明式编程
            const app = new Vue({   //创建Vue实例
                el:'#app',   //用于指定要挂载的元素
                data:{       //定义数据
                    message:"洛依尘!"
                }
            })
            //元素js的做法(编程范式:命令式编程)
            // 1.创建div元素,设置id属性
            // 2.定义一个变量叫message
            // 3.将message变量放在前面的div元素中显示
        </script>
    </body>
    

    MVVM 模式

    MVVM 源自于经典的 Model–View–Controller(MVC)模式(期间还演化出了 Model-View-Presenter(MVP)模式,可忽略不计)。MVVM 的出现促进了 GUI 前端开发与后端业务逻辑的分离,极大地提高了前端开发效率。MVVM 的核心是 ViewModel 层,它就像是一个中转站(value converter),负责转换 Model 中的数据对象来让数据变得更容易管理和使用,该层向上与视图层进行双向数据绑定,向下与 Model 层通过接口请求进行数据交互,起呈上启下作用。

    如下图所示:

    img

    简单画了一张图来说明 MVVM 的各个组成部分:

    img

    分层设计一直是软件架构的主流设计思想之一,MVVM 也不例外。

    View 层

    View 是视图层,也就是用户界面。前端主要由 HTML 和 CSS 来构建,为了更方便地展现 ViewModel 或者 Model 层的数据,已经产生了各种各样的前后端模板语言,比如 FreeMarker、Marko、Pug、Jinja2等等,各大 MVVM 框架如 KnockoutJS,Vue,Angular 等也都有自己用来构建用户界面的内置模板语言。

    Model 层

    Model 是指数据模型,泛指后端进行的各种业务逻辑处理和数据操控,主要围绕数据库系统展开。后端的处理通常会非常复杂

    ViewModel 层

    ViewModel 是由前端开发人员组织生成和维护的视图数据层。在这一层,前端开发者对从后端获取的 Model 数据进行转换处理,做二次封装,以生成符合 View 层使用预期的视图数据模型。需要注意的是 ViewModel 所封装出来的数据模型包括视图的状态和行为两部分,而 Model 层的数据模型是只包含状态的,比如页面的这一块展示什么,那一块展示什么这些都属于视图状态(展示),而页面加载进来时发生什么,点击这一块发生什么,这一块滚动时发生什么这些都属于视图行为(交互),视图状态和行为都封装在了 ViewModel 里。这样的封装使得 ViewModel 可以完整地去描述 View 层。由于实现了双向绑定,ViewModel 的内容会实时展现在 View 层,这是激动人心的,因为前端开发者再也不必低效又麻烦地通过操纵 DOM 去更新视图,MVVM 框架已经把最脏最累的一块做好了,我们开发者只需要处理和维护 ViewModel,更新数据视图就会自动得到相应更新,真正实现数据驱动开发。看到了吧,View 层展现的不是 Model 层的数据,而是 ViewModel 的数据,由 ViewModel 负责与 Model 层交互,这就完全解耦了 View 层和 Model 层,这个解耦是至关重要的,它是前后端分离方案实施的重要一环。

    image-20210508173816636

    Vue实例的options

    • el:
      类型 : string | HTMLElement
      作用 : 决定之后Vue实例会管理哪一个DOM。
    • data:
      类型 : Object | Function (组件当中data必须是一个函数)
      作用 : Vue实例对应的数据对象。
    • methods:
      类型 : { [key: string]: Function }
      作用 : 定义属于Vue的一 些方法,可以在其他地方调用,也可以在指令中使用。

    vue实例的生命周期

    一、解析

    1、什么是生命周期:从Vue实例创建、运行、到销毁期间,总是伴随着各种各样的事件,这些事件,统称为生命周期!

    2、生命周期钩子 = 生命周期函数 = 生命周期事件

    3、主要的生命周期函数分类:

    - 创建期间的生命周期函数:

    + beforeCreate:实例刚在内存中被创建出来,此时,还没有初始化好 data 和 methods 属性

    + created:实例已经在内存中创建OK,此时 data 和 methods 已经创建OK,此时还没有开始 编译模板

    + beforeMount:此时已经完成了模板的编译,但是还没有挂载到页面中

    + mounted:此时,已经将编译好的模板,挂载到了页面指定的容器中显示

    - 运行期间的生命周期函数:

    + beforeUpdate:状态更新之前执行此函数, 此时 data 中的状态值是最新的,但是界面上显示的 数据还是旧的,因为此时还没有开始重新渲染DOM节点

    + updated:实例更新完毕之后调用此函数,此时 data 中的状态值 和 界面上显示的数据,都已经完成了更新,界面已经被重新渲染好了!

    - 销毁期间的生命周期函数:

    + beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。

    + destroyed:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

    <body>
      <div id="app">
        <input type="button" value="修改msg" @click="msg='No'">
        <h3 id="h3">{{ msg }}</h3>
      </div>
    
      <script>
        // 创建 Vue 实例,得到 ViewModel
        var vm = new Vue({
          el: '#app',
          data: {
            msg: 'ok'
          },
          methods: {
            show() {
              console.log('执行了show方法')
            }
          },
          beforeCreate() { // 这是我们遇到的第一个生命周期函数,表示实例完全被创建出来之前,会执行它
            console.log(this.msg)
            this.show()
            // 注意: 在 beforeCreate 生命周期函数执行的时候,data 和 methods 中的 数据都还没有没初始化
          },
          created() { // 这是遇到的第二个生命周期函数
            console.log(this.msg)
            this.show()
            //  在 created 中,data 和 methods 都已经被初始化好了!
            // 如果要调用 methods 中的方法,或者操作 data 中的数据,最早,只能在 created 中操作
          },
          beforeMount() { // 这是遇到的第3个生命周期函数,表示 模板已经在内存中编辑完成了,但是尚未把 模板渲染到 页面中
            console.log(document.getElementById('h3').innerText)
            // 在 beforeMount 执行的时候,页面中的元素,还没有被真正替换过来,只是之前写的一些模板字符串
          },
          mounted() { // 这是遇到的第4个生命周期函数,表示,内存中的模板,已经真实的挂载到了页面中,用户已经可以看到渲染好的页面了
            console.log(document.getElementById('h3').innerText)
            // 注意: mounted 是 实例创建期间的最后一个生命周期函数,当执行完 mounted 就表示,实例已经被完全创建好了,此时,如果没有其它操作的话,这个实例,就静静的 躺在我们的内存中,一动不动
          },
    
    
          // 接下来的是运行中的两个事件
          beforeUpdate() { // 这时候,表示 我们的界面还没有被更新【数据被更新了吗?  数据肯定被更新了】
            console.log('界面上元素的内容:' + document.getElementById('h3').innerText)
            console.log('data 中的 msg 数据是:' + this.msg) 
            // 得出结论: 当执行 beforeUpdate 的时候,页面中的显示的数据,还是旧的,此时 data 数据是最新的,页面尚未和 最新的数据保持同步
          },
          updated() {
            console.log('界面上元素的内容:' + document.getElementById('h3').innerText)
            console.log('data 中的 msg 数据是:' + this.msg)
            // updated 事件执行的时候,页面和 data 数据已经保持同步了,都是最新的
          }
        });
      </script>
    </body>
    

    img

    2、基本语法

    1、插值操作

    Mustache语法

    <div id="app">
    	<h2>{{massage}}</h2>
      <h2>{{massage}},洛依尘</h2>
      <h2>{{firstName+lastName}}</h2>
      <h2>{{firstName+' '+lastName}}</h2>
      <h2>{{counter*2}}</h2>
    </div>
    
    <body>
    	<script src="../js/vue.js"></script>
    	<script>
    		const app = new Vue({
    			el: "#app",
    			data: {
    				massage: "你好",
            firstName:"kobe",
            lastName:"bryant",
            counter:200
    			}
    		})
    	</script>
    </body>
    

    v-once指令

    该指令后面不需要跟任何表达式(比如之前的v-for后面是由跟表达式的

    该指令表示元素和组件(组件后面才会学习)只渲染- 次,不会随着数据的改变而改变

    <h2 v-once>{{massage}}</h2>
    

    v-html

    该指令后面往往会跟上一个string类型
    会将string的html解析出来并且进行渲染

    	<h2>{{url}}</h2>  <!-- <a href="www.baidu.com">百度一下</a> -->
    	<h2 v-html="url"></h2>  <!-- 百度一下 -->
    

    v-text

    都是用于将数据显示在界面中,但是通常只接受一个string类型

    	<h2 v-text="massage">,洛依尘</h2>	<!--你好-->
    

    v-pre

    用于跳过这个元素和它子元素的编译过程,用于显示原本的Mustache语法

    	<h2 v-pre>{{massage}}</h2> <!-- {{massage}} -->
    

    v-cloak

    在某些情况下,f防止浏览器可能会直接显然出未编译的Mustache标签。

    <style>
    		[v-cloak] {
    			display: none;
    		}
    	</style>
    </head>
    
    <div id="app" v-cloak>
    	<h2>{{massage}}</h2>
    	<h2 v-once>{{massage}}</h2>
    	<h2>{{url}}</h2> <!-- <a href="www.baidu.com">百度一下</a> -->
    	<h2 v-html="url"></h2> <!-- 	百度一下 -->
    	<h2 v-text="massage">,洛依尘</h2>
    	<!--你好-->
    	<h2 v-pre>{{massage}}</h2> <!-- {{massage}} -->
    </div>
    
    <body>
    	<script src="../js/vue.js"></script>
    	<script>
    		//在vue解析之前,div里有一个属性c-cloak
    		//在vue解析之后,div里没有一个属性c-cloak
    		const app = new Vue({
    			el: "#app",
    			data: {
    				massage: "你好",
    				url: '<a href="www.baidu.com">百度一下</a>'
    			}
    		})
    	</script>
    </body>
    

    2、绑定属性

    v-bind

    v-bind用于绑定一个或多个属性值,或者向另-一个组件传递props值

    <div id="app">
        
      <!-- <img src="{{imgURL}}" alt=""> -->
      <!--  错误的用法:这里不可以使用mustache语法-->
        
      <!-- 正确用法:使用v-band指令 -->
      <a v-bind:href="aHref">百度</a>
      <img v-bind:src='imgURL' alt="" >
    
      <!-- 语法糖的写法 -->
      <a :href="aHref">百度</a>
      <img :src='imgURL' alt="" >
        
    </div>
    
    <body>
    	<script src="../js/vue.js"></script>
    	<script>
    		const app = new Vue({
    			el: "#app",
    			data: {
    				massage: "你好",
            imgURL:'https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png',
            aHref:"https://www.baidu.com/"
    			}
    		})
    	</script>
    </body>
    

    v-bind 动态绑定class(对象语法)

    • 可以通过{ }绑定一个类
    • 也可以通过判断,传入多个值
    • 和普通类同时存在,并不冲突
    • 如果过于复杂,可以放在一个methods或者computed中
    <style>
        .active{
          color: red;
        }
      </style>
    </head>
    
    <div id="app">
    	<!-- <h2 class="active">{{massage}}</h2>
      <h2 :class="active">{{massage}}</h2> -->
      
      <!-- <h2 :class="{类名1:ture,类名2:boolean}">{{massage}}</h2> 对class对象进行选择-->
      <h2 v-bind:class="{active: isActive , line: isLine}">{{massage}}</h2>   
      <!-- 将内容放在一个methods里,并调用 -->
      <h2 v-bind:class="getClasses()">{{massage}}</h2>   
      <button v-on:click="bntClick">按钮</button>
      <!-- 监听按钮,使用bntClick方法 -->
    </div>
    
    <body>
    	<script src="../js/vue.js"></script>
    	<script>
    		const app = new Vue({
    			el: "#app",
    			data: {
    				massage: "你好",
            active:'active',
            isActive:true,  //设置boolean值决定是否启用
            isLine:true
    			},
          methods:{
            bntClick: function(){
              this.isActive=!this.isActive
            },
            getClasses:function(){
              return {active: this.isActive, line: this.isLine}
            }
          }
    		})
    	</script>
    </body>
    

    v-bind 动态绑定class(数组语法)

    <div id="app">
      <!-- 如果在[]数组里的元素加了引号,代表他是一个字符串,而不是引用一个变量 -->
      <h2 :class="[active,line]">{{massage}}</h2>
      <h2 :class="['active','line']">{{massage}}</h2>
      <h2 :class="getClasses()">{{massage}}</h2>
    </div>
    
    <body>
    	<script src="../js/vue.js"></script>
    	<script>
    		const app = new Vue({
    			el: "#app",
    			data: {
    				massage: "你好",
            active:"aaa",
            line:"bbb"
    			},
          methods:{
            getClasses:function(){
              return [this.active,this.line]
            }
          }
    		})
    	</script>
    </body>
    

    小作业:点击列表中的哪一项, 那么该项的文字变成红色

    <style>
    		.active {
    			color: red;
    		}
    	</style>
    </head>
    
    <div id="app">
    	<ul>
    		<li v-for="(item, index) in movies" :class="{active: currentIndex === index}" @click="liClick(index)">
                <!-- {active: currentIndex === index}当currentIndex === index为true时,改变颜色  -->
    			{{index}}.{{item}}
    		</li>
    	</ul>
    </div>
    
    <body>
    	<script src="../js/vue.js"></script>
    	<script>
    		const app = new Vue({
    			el: "#app",
    			data: {
    				movies: ['海王', '火影忍者', '进击的巨人', '死神'],
    				currentIndex: 0
    			},
    			methods: {
    				liClick(index) {
    					this.currentIndex = index
    				}
    			}
    		})
    	</script>
    </body>
    

    v-bind 绑定style

    <div id="app">
    	<!-- <h2 :style="{key(属性名):value(属性值)}">{{massage}}</h2> -->
    
      <!-- 这里要加' '要不然vue会去解析50px这个变量然后报错 -->
      <h2 :style="{fontSize: '50px'}">{{massage}}</h2>
      
      <!-- finalSize当成一个变量在使用 -->
      <h2 :style="{fontSize: finalSize}">{{massage}}</h2>
    
      <!-- 也可以拼接 -->
      <h2 :style="{fontSize: finalSize + 'px',color:finalColor}">{{massage}}</h2>
    
      <!-- 数组语法 -->
      <h2 :style="[baseStyle,baseStyle1]">{{massage}}</h2>
    </div>
    
    <body>
    	<script src="../js/vue.js"></script>
    	<script>
    		const app = new Vue({
    			el: "#app",
    			data: {
    				massage: "你好",
            finalSize: 100,
            finalColor: 'red',
            baseStyle:{color:'red'},
            baseStyle1:{fontSize:'75px'}
    			}
    		})
    	</script>
    </body>
    

    3、计算属性

    一、什么是计算属性

      模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。

    二、计算属性的用法

      在一个计算属性里可以完成各种复杂的逻辑,包括运算、函数调用等,只要最终返回一个结果就可以。

    <div id="app">
    	<h2>{{firstName+' '+lastName}}</h2>
      <h2>{{fullName}}</h2>
      <h2>总价格:{{totalPrice}}</h2>
    </div>
    
    <body>
    	<script src="../js/vue.js"></script>
    	<script>
    		const app = new Vue({
    			el: "#app",
    			data: {
    				firstName:"luo",
            lastName:"yichen",
            books:[
              {id:100, name: 'java核心技术' , price:100},
              {id:101, name: 'c核心技术' , price:100},
              {id:102, name: 'php核心技术' , price:100},
              {id:103, name: 'python核心技术' , price:100}
            ]
    			},
          // computed: 计算属性()
          computed:{
            fullName:function(){
              return this.firstName+' '+this.lastName
            },
            totalPrice:function(){
              let result =0
              for (let i=0;i < this.books.length; i++){
                result += this.books[i].price
              }
              return result;
            }
          }
    		})
    	</script>
    

    计算属性的getter和setter

    每个计算属性都包含一个getter和一个setter

    • 在上面的例子中,我们只是使用getter来读取。
    • 在某些情况下,你也可以提供一个setter方法 (不常用)。
    • 在需要写setter的时候,代码如下: .
    <div id="app">
     <h2>{{fullName}}</h2>
    </div>
    
    <body>
     <script src="../js/vue.js"></script>
     <script>
       const app = new Vue({
         el: "#app",
         data: {
           firstName: "luo",
           lastName: "yichen",
         },
         computed: {
           // fullName: function () {
           //   return this.firstName + ' ' + this.lastName
           // }
           // 计算属性一般没有set值,只读属性。
           fullName:{
             set: function(newValue){
               const names = newValue.split(" ");
               this.firstName = names[0];
               this.lastName = names[1];
             }, 
             get: function(){
               return this.firstName + ' ' + this.lastName
             }
           },
           // 简洁写法
           // fullName:function(){
           //   return this.firstName+' '+this.lastName
           // }
         }
       })
     </script>
    </body>
    

    计算属性与methods对比

    <div id="app">
      <!-- 通过拼接:语法过于繁琐 -->
      <h2>{{firstName}} {{lastName}}</h2>
      <!-- 通过定义methods 每次都要调用-->
      <h2>{{getFullName()}}</h2>
      <!-- 通过computed 如果没有发生改变只需要调用一次-->
      <h2>{{fullName}}</h2>
    </div>
    
    <body>
      <script src="../js/vue.js"></script>
      <script>
        const app = new Vue({
          el: "#app",
          data: {
            firstName: "luo",
            lastName: "yichen"
          },
          methods: {
            getFullName: function () {
              return this.firstName + ' ' + this.lastName
            }
          },
          computed: {
            fullName: function () {
              return this.firstName + ' ' + this.lastName
            }
          }
        })
      </script>
    </body>
    

    4、事件监听

    可以用 v-on 指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码。

    获取到浏览器参数的event对象: $event

    <div id="app">
    	<h2>{{counter}}</h2>
      <button v-on:click="increment">+</button>
      <button v-on:click="decrement">-</button>
      <!-- 语法糖 当没参数时()可以不用写 -->
      <button @click="increment">+</button>
      <button @click="decrement">-</button>
    
      <!-- 事件调用时没有参数 -->
      <button @click="bnt1Click()">按钮1</button>
      <button @click="bnt1Click">按钮1</button>
    
      <!-- 在事件定义前,写函数省略了小括号,但是方法本身需要一个参数,这个时候
      Vue会将浏览器默认生成的event事件对象作为参数传入方法中 -->
      <button @click="bnt2Click(123)">按钮2</button> 
      <button @click="bnt2Click()">按钮2</button>
      <button @click="bnt2Click">按钮2</button>
    
      <!-- 定义方法时,我们需要event对象,同时又需要其他参数 -->
      <!-- 在调用方式时,如何手动的获取到浏览器参数的event对象: $event -->
      <button @click="bnt3Click('abc',$event)">按钮3</button>
    </div>
    
    <body>
    	<script src="../js/vue.js"></script>
    	<script>
    		const app = new Vue({
    			el: "#app",
    			data: {
    				counter: 0
    			},
          methods:{
            increment(){
              this.counter++
            },
            decrement(){
              this.counter--
            },
            bnt1Click(){
              console.log("bnt1Click");
            },
            bnt2Click(abc){
              console.log("--------------",abc);
            },
            bnt3Click(abc,event){
              console.log("++++++++++++++", abc,event);
            }
          }
    		})
    
        // 如果我们函数需要参数,但是没有传入参数,那么函数的形参为undefined
        function abc(name){
          console.log(name);
        }
        abc()
    	</script>
    </body>
    

    v-on的修饰符

    1. .stop修饰符的使用

      当多对标签进行重叠的时候, 你点击最上面的一层标签的时候, 会自动的冒泡到他下面的所有标签上面
      .stop就是阻止冒泡使用的

    2. .prevent修饰符的使用

      form表单提交时候或者在点击a标签的时候, 会阻止提交或跳转

    3. .keyup监听某个键盘的键帽

      监听某个键盘的键位

    4. .once修饰符的使用

      绑定后只会触发一次

    <div id="app">
      <!-- 1. .stop -->
      <div @click='divClick'>
        aaaaa
        <button @click.stop='bntClick'>按钮</button>
      </div>
    
      <!-- 2. .prevent  -->
      <form action="baidu">
        <input type="submit" value="提交" @click.prevent='submitClick'>
      </form>
    
      <!-- 3. 监听某个键盘的键位 -->
      <input type="text" @keyup.enter="keyUp">
    
      <!-- 4. once修饰符的使用 -->
      <button @click.once='bnt2Click'>按钮</button>
    </div>
    
    
    
    <body>
      <script src="../js/vue.js"></script>
      <script>
        const app = new Vue({
          el: "#app",
          data: {
            massage: "你好"
          },
          methods: {
            bntClick() {
              console.log('bnt')
            },
            divClick() {
              console.log('div')
            },
            submitClick() {
              console.log("submitClick")
            },
            keyUp() {
              console.log("up")
            },
            bnt2Click() {
              console.log('bnt2');
            }
          }
        })
      </script>
    </body>
    

    5、条件判断

    v-if的原理:
    v-if后面的条件为false时,对应的元素以及其子元素不会渲染。
    也就是根本没有不会有对应的标签出现在DOM中。

    <div id="app">
      <h2 v-if="score>90">优秀</h2>
      <h2 v-else-if="score>80">良好</h2>
      <h2 v-else-if="score>60">及格</h2>
      <h2 v-else>不及格</h2>
    
      <h1>{{result}}</h1>
    
      <h2 v-if="isShow">{{massage}}</h2>
      <h1 v-else>当isShow为false时显示我</h1>
    
    </div>
    
    <body>
      <script src="../js/vue.js"></script>
      <script>
        const app = new Vue({
          el: "#app",
          data: {
            massage: "你好",
            isShow: true,
            score: 99
          },
          computed: {
            result() {
              let showMessage = '';
              if (this.score >= 90) {
                showMessage = "优秀"
              } else if (this.score >= 80) {
                showMessage = "良好"
              }
              // ...
              return showMessage
            }
          }
        })
      </script>
    </body>
    

    用户切换的小案例

    <div id="app">
    	<span v-if="isUser">
        <label for="username">用户账号</label>
        <input type="text" id="username" placeholder="用户账号" key='username'>
      </span>
      <span v-else>
        <label for="emailname">用户邮箱</label>
        <input type="text" id="emailname" placeholder="用户邮箱" key='emailname'>
      </span>
      <button @click="isUser = !isUser">切换类型</button>
    </div>
    
    <body>
    	<script src="../js/vue.js"></script>
    	<script>
    		const app = new Vue({
    			el: "#app",
    			data: {
    				isUser:true
    			}
    		})
    	</script>
    </body>
    

    小问题:

    • 如果我们在有输入内容的情况下,切换了类型,我们会发现文字依然显示之前的输入的内容。
    • 但是按道理讲,我们应该切换到另外一个input元素中了。
    • 在另一个input元素中,我们并没有输入内容。
    • 为什么会出现这个问题呢?

    问题解答:

    • 这是因为Vue在进行DOM渲染时,出于性能考虑,会尽可能的复用已经存在的元素,而不是重新创建新的元素。
    • 在上面的案例中, Vue内部会发现原来的input元素不再使用,直接作为else中的input来使用了.

    解决方案:

    • 如果我们不希望Vue出现类似重复利用的问题,可以给对应的input添加key
    • 并且我们需要保证key的不同

    Virtual DOM 是什么?

    img

    Virtual DOM 其实就是一棵以 JavaScript 对象( VNode 节点)作为基础的树,用对象属性来描述节点,实际上它只是一层对真实 DOM 的抽象。最终可以通过一系列操作使这棵树映射到真实环境上。

    简单来说,可以把Virtual DOM 理解为一个简单的JS对象,并且最少包含标签名( tag)、属性(attrs)和子元素对象( children)三个属性。不同的框架对这三个属性的命名会有点差别。

    对于虚拟DOM,咱们来看一个简单的实例,就是下图所示的这个,详细的阐述了模板 → 渲染函数 → 虚拟DOM树 → 真实DOM的一个过程

    img

    Virtual DOM 作用是什么?

    虚拟DOM的最终目标是将虚拟节点渲染到视图上。但是如果直接使用虚拟节点覆盖旧节点的话,会有很多不必要的DOM操作。例如,一个ul标签下很多个li标签,其中只有一个li有变化,这种情况下如果使用新的ul去替代旧的ul,因为这些不必要的DOM操作而造成了性能上的浪费。

    为了避免不必要的DOM操作,虚拟DOM在虚拟节点映射到视图的过程中,将虚拟节点与上一次渲染视图所使用的旧虚拟节点(oldVnode)做对比,找出真正需要更新的节点来进行DOM操作,从而避免操作其他无需改动的DOM。

    其实虚拟DOM在Vue.js主要做了两件事:

    • 提供与真实DOM节点所对应的虚拟节点vnode
    • 将虚拟节点vnode和旧虚拟节点oldVnode进行对比,然后更新视图

    v-if和v-show的区别

    v-show控制的是节点的display属性 v-if是将节点删除了 如果节点需要频繁显示隐藏 使用v-show性能更佳!

    <div id="app">
      <!-- v-if: 当条件为false时,包含v-if指令的元素,根本就不会存在dom中 -->
      <h2 v-if='isShow' id="aaa">{{massage}}</h2>
      <!-- V- show:当条件为false时,v-show只是给我们的元素添加一个行内样式: display: none -->
      <h2 v-show='isShow' id="bbb">{{massage}}</h2>
    </div>
    
    <body>
      <script src="../js/vue.js"></script>
      <script>
        const app = new Vue({
          el: "#app",
          data: {
            massage: "你好",
            isShow: true
          }
        })
      </script>
    </body>
    

    6、循环遍历

    当我们有一组数据需 要进行渲染时,我们就可以使用v-for来完成。
    v-for的语法类似于JavaScript中的for循环。
    格式如下: item in items的形式。

    <div id="app">
      <!-- 1.在遍历的过程中,没有使用索引值(下标值) -->
      <ul>
        <li v-for='item in names'>{{item}}</li>
      </ul>
    
      <!-- 2.在遍历过程中,获取索引值 -->
      <ul>
        <li v-for='(item,index) in names'>
          {{index+1}}.{{item}}
        </li>
      </ul>
    
      <!-- 1.在遍历对象的过程中,如果只是获取一个值,那么获取到的是value -->
      <ul>
        <li v-for="item in info">{{item}}</li>
      </ul>
      <!-- 2., 获取key和value 格式(value,key) -->
      <ul>
        <li v-for="(value,key) in info">{{value}}-{{key}}</li>
      </ul>
      <!-- 3. 获取key和value和index 格式(value,key,index)-->
      <ul>
        <li v-for="(value,key,index) in info">{{value}}-{{key}}-{{index}}</li>
      </ul>
    </div>
    
    <body>
      <script src="../js/vue.js"></script>
      <script>
        const app = new Vue({
          el: "#app",
          data: {
            names: ['why', 'who', 'what', 'where']	//遍历数组
          },
          info: {									//遍历对象
            name: 'lyc',
            age: 18,
            height: 1.88
          }
        })
      </script>
    </body>
    

    v-for加key属性

    • 为什么需要这个key属性呢(了解) ?

      • 这个其实和Vue的虚拟DOM的Diff算法有关系。
      • 这里我们借用React' S diff algorithm中的一张图来简单说明一下:
    • 当某一层有很多相同的节点时,也就是列表节点时,我们希望插入一一个新
      的节点

      • 我们希望可以在B和C之间加一一个F , Diff算法默认执行起来是这样的。
      • 即把C更新成F , D更新成C , E更新成D ,最后再插入E ,是不是很没有
        效率?
    • 所以我们需要使用key来给每个节点做一个唯一标识

      • Diff算法就可以正确的识别此节点

      • 0找到正确的位置区插入新的节点。

    所以一句话, key的作用主要是为了高效的更新虚拟DOM。

    image-20210517163534869

    image-20210517163043021

    哪些数组方法是响应式的

    <body>
      <script src="../js/vue.js"></script>
      <script>
        const app = new Vue({
          el: "#app",
          data: {
            letters: ['A', 'C', 'B', 'D', 'E']
          },
          methods: {
            btnClick() {
              // 1.push()   在数组最后添加元素
              this.letters.push('aaa','bbb')
    
              // 2.pop()      在数组最后删除一个元素
              this.letters.pop();
    
              // 3.shift()   删除在数组第一个元素
              this.letters.shift();
    
              // 4.unshift() 在数组最前面添加元素
              this.letters.unshift('ddd','ddd');
    
              // 5.splice()   删除/插入/替换元素
              // 删除元素: 第一参数传入你从第几个元素开始删除,第二参数传入你要删除的几个元素(如果没有传,就删除后面所有元素)
              // 插入元素: 第二个传入0,后面跟上要添加的值
              // 替换元素: 第二参数传入你要删除元素,后面追加你要写入的元素完成替换
              this.letters.splice(1,3,'m','n','l')
    
              // 6.sort()     排序
              this.letters.sort()
    
              // 7.reverse()  反转
              this.letters.reverse()
    
              // 注意:通过索引值直接来修改数组中的元素 不是响应式
              // this.letters[0]='bbbbbbbbbbbb'
              // set(要修改的对象,索引值,修改后的值)
              Vue.set(this.letters,0,'bbbbbb')
            }
          }
        })
    
        // 扩展知识:可变参数
        // function sum(...sum){
        //   console.log(sum);
        // }
        // sum(11,223,44,56,77,889,9,1)
      </script>
    </body>
    

    6、表单绑定

    • 表单控件在实际开发中是非常常见的。特别是对于用户信息的提交,需要大量的表单。
    • Vue中使用v-model指令来实现表单元素和数据的双向绑定。
    <body>
    
      <div id="app">
        <input type="text" v-model="massage">
        {{massage}}
      </div>
    
      <script src="../js/vue.js"></script>
      <script>
        const app = new Vue({
          el: "#app",
          data: {
            massage: "你好"
          }
        })
      </script>
    </body>
    
    • 当我们在输入框输入内容时
    • 因为input中的v-model绑定了message ,所以会实时将输入的内容传递给message , message发生改变。
    • 当message发生改变时,因为上面我们使用Mustache语法,将message的值插入到DOM中,所以DOM会发生响应的改变。
    • 所以,通过v-model实现了双向的绑定。

    原理:

      <div id="app">
        <!-- <input type="text" v-model="massage"> -->
        <!-- <input type="text" :value="massage" @input="valueChange"> -->
        <input type="text" :value="massage" @input="massage = $event.target.value">
        {{massage}}
      </div>
    
      <script src="../js/vue.js"></script>
      <script>
        const app = new Vue({
          el: "#app",
          data: {
            massage: "你好"
          },
          methods: {
            valueChange(event) {
              this.massage = event.target.value;
            }
          }
        })
      </script>
    
    </body>
    

    v-model结合radio类型

    <div id="app">
      <label for="">
        <input type="radio" id="male" value="男" v-model="sex">男
      </label>
      <label for="">
        <input type="radio" id="female" value="女" v-model="sex">女
      </label>
      <h2>{{sex}}</h2>
    </div>
    
    <body>
      <script src="../js/vue.js"></script>
      <script>
        const app = new Vue({
          el: "#app",
          data: {
            message: "你好",
            sex:'男'
          }
        })
      </script>
    </body>
    

    v-model结合checkbox类型

    单个勾选框: .

    • v-modelI即为布尔值。
    • 此时input的value并不影响v-model的值。

    多个复选框:

    • 多个复选框时,因为可以选中多个,所以对应的data中属性是一个数组。
    • 当选中某一个时 ,就会将input的value添加到数组中。
    <div id="app">
      <!-- 单选框 -->
      <!-- <label for="agree">
        <input type="checkbox" id="agree" v-model="isAgree">同意协议
      </label>
      <h2>{{isAgree}}</h2>
      <button :disabled="!isAgree">下一步</button> -->
    
      <!-- 多选框 -->
        <!-- <input type="checkbox" value="篮球" v-model="hobbies">篮球
        <input type="checkbox" value="足球" v-model="hobbies">足球
        <input type="checkbox" value="排球" v-model="hobbies">排球
        <input type="checkbox" value="手球" v-model="hobbies">手球
        <h2>{{hobbies}}</h2> -->
    
        <label v-for="item in originHobbies" :for="item">
          <input type="checkbox" :value="item" :id="item" v-model="hobbies">{{item}}
        </label>
      </div>
    
    <body>
      <script src="../js/vue.js"></script>
      <script>
        const app = new Vue({
          el: "#app",
          data: {
            message: "你好",
            isAgree: false,//单选框
            hobbies:[],//多选框 
            originHobbies:['篮球','足球','乒乓球','台球','高尔夫球']
              //也可以通过值绑定来从服务器获取值
          }
        })
      </script>
    </body>
    

    v-model结合select

    单选:只能选中一个值。

    • v-model绑定的是一个值。
    • 当我们选中option中的一个时,会将它对应的value赋值到mySelect中

    多选:可以选中多个值。

    • v-model绑定的是一个数组。
    • 当选中多个值时,就会将选中的option对应的value添加到数组mySelects中
    <body>
    
      <div id="app">
        <!-- 1、选择一个 -->
        <select name="abc" id=""  v-model="fruit">
          <option value="苹果">苹果</option>
          <option value="香蕉">香蕉</option>
          <option value="榴莲">榴莲</option>
          <option value="西瓜">西瓜</option>
        </select>
        <h2>{{fruit}}</h2>
    
        <!-- 2、选择多个 -->
        <select name="abc" id=""  v-model="fruits" multiple>
          <option value="苹果">苹果</option>
          <option value="香蕉">香蕉</option>
          <option value="榴莲">榴莲</option>
          <option value="西瓜">西瓜</option>
        </select>
        <h2>{{fruits}}</h2>
      </div>
    
        <script src="../js/vue.js"></script>
        <script>
          const app = new Vue({
            el: "#app", 
            data: {
              message: "你好",
              fruit:"香蕉",
              fruits:[]
            }
          })
        </script>
    
    </body>
    

    v-model的修饰符

    lazy修饰符:

    • 默认情况下, v- model默认是在input事件中同步输入框的数据的。
    • 也就是说, 一旦有数据发生改变对应的data中的数据就会自动发生
      改变。
    • lazy修饰符可以让数据在失去焦点或者回车时才会更新:

    number修饰符:

    • 默认情况下,在输入框中无论我们输入的是字母还是数字,都会被
      当做字符串类型进行处理。
    • 但是如果我们希望处理的是数字类型,那么最好直接将内容当做数
      字处理。
    • number修饰符可以让在输入框中输入的内容自动转成数字类型:

    trim修饰符:

    • 如果输入的内容首尾有很多空格,通常我们希望将其去除
    • trim修饰符可以过滤内容左右两边的空格
    <div id="app">
      <!-- 1.修饰符:lazy -->
      <input type="text" v-model.lazy="message">
      <h2>{{message}}</h2>
    
      <!-- 2.修饰符:number -->
      <input type="number" v-model.number="age">
      <h2>{{typeof age}}</h2>
    
      <!-- 3.修饰符:trim -->
      <input type="text" v-model.trim="name">
      <h2>{{name}}</h2>
    </div>
    
    <body> 
      <script src="../js/vue.js"></script>
      <script>
        const app = new Vue({
          el: "#app",
          data: {
            message: "你好",
            age:12,
            name:''
          }
        })
      </script>
    </body>
    

    综合-书籍购物车案例

    • HTML
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
      <link rel="stylesheet" href="./style.css">
    
    </head>
    
    <body>
    
      <div id="app">
        <div v-if="books.length">
          <table>
            <thead>
              <tr>
                <th></th>
                <th>书籍名称</th>
                <th> 出版日期</th>
                <th> 价格</th>
                <th> 购买数量</th>
                <th> 操作</th>
              </tr>
            </thead>
            <tbody>
              <tr v-for="(item,index) in books">
                <td>{{item.id}}</td>
                <td>{{item.name}}</td>
                <td>{{item.date}}</td>
                <td>{{item.price | showPrice}}</td>
                <td>
                  <button @click="decrement(index)" v-bind:disabled="item.count <= 1">-</button>
                  {{item.count}}
                  <button @click="increment(index)">+</button>
                </td>
                <td><button @click="removeHandler(index)">移除</button></td>
              </tr>
            </tbody>
          </table>
          <h2>
            总价格: {{totalPrice | showPrice}}
          </h2>
        </div>
        <div v-else>
          <h1>购物车为空</h1>
        </div>
      </div>
      <script src="../js/vue.js"></script>
      <script src="./main.js"></script>
    </body>
    
    </html>
    
    • CSS
    table{
      border: 1px solid #000;
      border-collapse: collapse;
      border-spacing: 0;
    }
    th,td{
      padding: 8px 16px;
      border: 1px solid #000;
      text-align: left;
    }
    
    th{
      background-color: #f7f7f7;
      color: #5c6b77;
      font-weight: 600;
    }
    
    • JS
    const app = new Vue({
      el: "#app",
      data: {
        books: [{
            id: 1,
            name: '《算法导论》',
            date: "2006-9",
            price: 85.00,
            count: 1
          },
          {
            id: 2,
            name: '《算法导论》',
            date: "2006-9",
            price: 85.00,
            count: 1
          },
          {
            id: 3,
            name: '《算法导论》',
            date: "2006-9",
            price: 85.00,
            count: 1
          },
          {
            id: 4,
            name: '《算法导论》',
            date: "2006-9",
            price: 85.00,
            count: 1
          }
        ]
      },
      methods: {
        // getFinalPrice(price){
        //   return '¥'+price.toFixed(2) //toFixed(2)保留两位小数
        // }
        increment(index) {
          this.books[index].count++
        },
        decrement(index) {
          this.books[index].count--
        },
        removeHandler(index) {
          this.books.splice(index, 1)
        }
      },
      filters: { //过滤器
        showPrice(price) {
          return '¥' + price.toFixed(2)
        }
      },
      computed: {
        totalPrice() {
          let totalPrice = 0;
          for (let i = 0; i < this.books.length; i++) {
            totalPrice += this.books[i].price * this.books[i].count;
          }
          return totalPrice;
        }
      }
    })
    

    JS高阶函数

    编程范式:命令式编程/声明式编程

    编程范式:面向对象编程(第一公民:对象)/函数式编程(第一公民:函数)

    filter/map/reduce

    filter中的回调函数有一个要求:必须返回一个 boolean值

    true:当返回true时,函数内部会自动将这次回调的n加入到新的数组中

    false:当返回false时,函数内部会过滤掉这次的n

    • 基本写法
    const nums = [10,20,111,222,444,40,50]
    
    // 1.需求:取出小于100的数字
    let newNums = []
    for(let n of nums){
      if(n > 100){
        newNums.push(n)
      }
    }
    
    // 2.需求:将所有小于160的数字进行转化:全部*2
    let new2Nums = []
    for(let n of newNums){
      new2Nums.push(n*2)
    }
    
    // 3.需求:将所有new2Nums数字相加,得到最终的记过
    let total = 0
    for(let n of new2Nums){
      total +=n
    }
    console.log(total)
    
    • 高阶写法
    const nums = [10,20,111,222,444,40,50]
    // 1.filter函数的使用
    let newNums = nums.filter(function(n){
      return n<100
    })
    console.log(newNums)
    
    // 2.map函数的使用
    let new2Nums = newNums.map(function(n){
      return n*2
    })
    console.log(new2Nums)
    
    // 3.reduce函数的使用
    // reduce作用对数组中所有的内容进行汇总
    let total = new2Nums.reduce(function(preValue,n){
      return preValue + n;
    },0)
    console.log(total)
    // 第一次: revalue 0  n 20
    // 第二次: revalue 20 n 40
    // 第二次: revalue 60 n 80
    // 第二次: revalue 140 n 100
    // 240
    
    • 高阶综合写法
    const nums = [10,20,111,222,444,40,50]
    
    // 综合
    let total = nums.filter(function(n){
      return n<100
    }).map(function(n){
      return n*2
    }).reduce(function(preValue,n){
      return preValue + n;
    },0) //初始化
    console.log(total)
    
    //使用箭头函数进一步简化
    let total = nums.filter(n => n<100).map(n => n*2).reduce((pre,n) => pre+n)
    console.log(total)
    

    点击转跳第二部分内容

    本帖子中包含资源

    您需要 登录 才可以下载,没有帐号?立即注册