• Vue 学习笔记 [Part 3]


    作者:故事我忘了
    个人微信公众号:程序猿的月光宝盒

    〇.高阶函数

    0.1 filter()

    const nums = [10, 20, 111, 222, 444, 40, 50]
    // 1.filter函数的使用
    // filter中的回调函数有一个要求: 必须返回一个boolean值
    // true: 当返回true时, 函数内部会自动将这次回调的n加入到新的数组中
    // false: 当返回false时, 函数内部会过滤掉这次的n
    // 10, 20, 40, 50
    let newNums = nums.filter(function (n) {
      return n < 100
    });
    console.log(newNums);
    

    0.2 map()

    const nums = [10, 20, 111, 222, 444, 40, 50]
    // 2.map函数的使用 
    // 原来的newNums*2倍
    // 20, 40, 80, 100
    //newNums是 0.1步骤的结果
    let new2Nums = newNums.map(function (n) {
      return n * 2
    });
    console.log(new2Nums);
    

    0.3 reduce()

    const nums = [10, 20, 111, 222, 444, 40, 50]
    // 3.reduce函数的使用
    // reduce作用对数组中所有的内容进行汇总(相加)
    //new2Nums是0.2步骤的结果
    let total = new2Nums.reduce(function (preValue, n) {
      return preValue + n
    }, 0);
    console.log(total);
    
    //  流程:
    // 第一次: preValue 0, n 20 
    // 第二次: preValue 0+20=20, n 40 
    // 第三次: preValue 20+40=60, n 80
    // 第四次: preValue 20+40+80=140, n 100
    // 最终结果:140+100=240
    

    // 编程范式: 命令式编程/声明式编程
    // 编程范式: 面向对象编程(第一公民:对象)/函数式编程(第一公民:函数)
    // filter/map/reduce
    
    let total = nums.filter(n => n < 100).map(n => n * 2).reduce((pre, n) => pre + n);
    console.log(total);
    
    // 传统的:
    // // 1.需求: 取出所有小于100的数字
    let newNums = []
    for (let n of nums) {
      if (n < 100) {
        newNums.push(n)
      }
    }
    
    // 2.需求:将所有小于100的数字进行转化: 全部*2
    let new2Nums = []
    for (let n of newNums) {
      new2Nums.push(n * 2)
    }
    
    console.log(new2Nums);
    
    
    // 3.需求:将所有new2Nums数字相加,得到最终的结果
    let total = 0
    for (let n of new2Nums) {
      total += n
    }
    
    console.log(total);
    
    用了高阶函数
    // 取出小于100的
    let total = nums.filter(function (n) {
      return n < 100
      // 把取出来的*2
    }).map(function (n) {
      return n * 2
      // 然后再求和
    }).reduce(function (prevValue, n) {
      return prevValue + n
    }, 0);
    console.log(total);
    

    一. 表单绑定v-model

    ​ 表单控件在实际开发中是非常常见的。特别是对于用户信息的提交,需要大量的表单。
    Vue中使用v-model指令来实现表单元素和数据的双向绑定

    1.1. v-model的基本使用

    • v-model 原理=> v-bind:value加上v-on:input

      <!DOCTYPE html>
      <html lang="en">
      <head>
        <meta charset="UTF-8">
        <title>Title</title>
      </head>
      <body>
      
      <div id="app">
        <input type="text" v-model="message">
        {{message}}
      </div>
      
      <script src="../js/vue.js"></script>
      <script>
        const app = new Vue({
          el: '#app',
          data: {
            message: '你好啊'
          }
        })
      </script>
      
      </body>
      </html>
      

      解析:

      ​ 当我们在输入框输入内容时,因为input中的v-model绑定了message,所以会实时将输入的内容传递给messagemessage发生改变。

      ​ 当message发生改变时,因为上面我们使用Mustache语法,将message的值插入到DOM中,所以DOM会发生响应的改变。

      ​ 所以,通过v-model实现了双向的绑定。

      也可以将v-model用于textarea

      原理:

      v-model其实是一个语法糖,它的背后本质上是包含两个操作:

      ​ 1.v-bind绑定一个value属性

      ​ 2.v-on指令给当前元素绑定input事件

      也就是说:

      <input type="text" v-model="message">

      等同于

      <input type="text" v-bind:value="message" v-on:input="message = $event.target.value">

    1.2. v-model和radio/checkbox/select

    1.2.1 v-modelradio
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
    </head>
    <body>
    
    <div id="app">
      <label for="male">
        <input type="radio" id="male" value="男" v-model="sex">男
      </label>
      <label for="female">
        <input type="radio" id="female" value="女" v-model="sex">女
      </label>
      <h2>您选择的性别是: {{sex}}</h2>
    </div>
    
    <script src="../js/vue.js"></script>
    <script>
      const app = new Vue({
        el: '#app',
        data: {
          message: '你好啊',
          sex: '女'
        }
      })
    </script>
    
    </body>
    </html>
    
    1.2.2 v-modelcheckbox 与值绑定

    复选框分为两种情况:单个勾选框和多个勾选框

    ​ 单个勾选框:

    ​ v-model即为布尔值。

    ​ 此时input的value并不影响v-model的值。

    ​ 多个复选框:

    ​ 当是多个复选框时,因为可以选中多个,所以对应的data中属性是一个数组。

    ​ 当选中某一个时,就会将input的value添加到数组中。

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
    </head>
    <body>
    
    <div id="app">
      <!--1.checkbox单选框-->
      <label for="agree">
        <input type="checkbox" id="agree" v-model="isAgree">同意协议
      </label>
      <h2>您选择的是: {{isAgree}}</h2>
      <button :disabled="!isAgree">下一步</button>
    
      <!--2.checkbox多选框-->
      <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>
    
      <!--  从服务器获取的originHobbies,也就是所谓的值绑定 -->
      <label v-for="item in originHobbies" :for="item">
        <input type="checkbox" :value="item" :id="item" v-model="hobbies">{{item}}
      </label>
    </div>
    
    <script src="../js/vue.js"></script>
    <script>
      const app = new Vue({
        el: '#app',
        data: {
          message: '你好啊',
          isAgree: false, // 单选框,默认没选 为false
          hobbies: [], // 多选框,
          originHobbies: ['篮球', '足球', '乒乓球', '羽毛球', '台球', '高尔夫球']
        }
      })
    </script>
    
    </body>
    </html>
    
    1.2.3 v-modelselect

    和checkbox一样,select也分单选和多选两种情况。

    ​ 单选:只能选中一个值。

    ​ v-model绑定的是一个值。

    ​ 当我们选中option中的一个时,会将它对应的value赋值到fruit中

    ​ 多选:可以选中多个值。

    ​ v-model绑定的是一个数组。

    ​ 当选中多个值时,就会将选中的option对应的value添加到数组fruits中

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
    </head>
    <body>
    
    <div id="app">
      <!--1.选择一个-->
      <select name="abc" v-model="fruit">
        <option value="苹果">苹果</option>
        <option value="香蕉">香蕉</option>
        <option value="榴莲">榴莲</option>
        <option value="葡萄">葡萄</option>
      </select>
      <h2>您选择的水果是: {{fruit}}</h2>
    
      <!--2.选择多个 multiple属性 -->
      <select name="abc" 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>
    </html>
    

    1.3. 修饰符

    • lazy

      默认情况下,v-model默认是在input事件中同步输入框的数据的。

      也就是说,一旦有数据发生改变对应的data中的数据就会自动发生改变。

      lazy修饰符可以让数据在失去焦点或者回车时才会更新:

    • number 只能是number类型的数据,但是input默认是空的字符串

      默认情况下,在输入框中无论我们输入的是字母还是数字,都会被当做字符串类型进行处理。

      但是如果我们希望处理的是数字类型,那么最好直接将内容当做数字处理。

      number修饰符可以让在输入框中输入的内容自动转成数字类型

    • trim

      如果输入的内容首尾有很多空格,通常我们希望将其去除

      trim修饰符可以过滤内容左右两边的空格

      <!DOCTYPE html>
      <html lang="en">
      <head>
        <meta charset="UTF-8">
        <title>Title</title>
      </head>
      <body>
      
      <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>{{age}}-{{typeof age}}</h2>
      
        <!--3.修饰符: trim-->
        <input type="text" v-model.trim="name">
        <h2>您输入的名字:{{name}}</h2>
      </div>
      
      <script src="../js/vue.js"></script>
      <script>
        const app = new Vue({
          el: '#app',
          data: {
            message: '你好啊',
            age: 0,
            name: ''
          }
        })
      </script>
      </body>
      </html>
      

    二. 组件化开发

    2.1. 认识组件化

    人面对复杂问题的处理方式:

    ​ 任何一个人处理信息的逻辑能力都是有限的

    ​ 所以,当面对一个非常复杂的问题时,我们不太可能一次性搞定一大堆的内容。

    ​ 但是,我们人有一种天生的能力,就是将问题进行拆解。

    ​ 如果将一个复杂的问题,拆分成很多个可以处理的小问题,再将其放在整体当中,你会发现大的问题也会迎刃而解。

    组件化也是类似的思想:

    ​ 如果我们将一个页面中所有的处理逻辑全部放在一起,处理起来就会变得非常复杂,而且不利于后续的管理以及扩展。

    ​ 但如果,我们讲一个页面拆分成一个个小的功能块,每个功能块完成属于自己这部分独立的功能,那么之后整个页面的管理和维护就变得非常容易了。

    图片

    Vue组件化思想

    ​ 组件化是Vue.js中的重要思想

    ​ 它提供了一种抽象,让我们可以开发出一个个独立可复用的小组件来构造我们的应用。

    ​ 任何的应用都会被抽象成一颗组件树。

    图片

    组件化思想的应用:

    ​ 有了组件化的思想,我们在之后的开发中就要充分的利用它。

    ​ 尽可能的将页面拆分成一个个小的、可复用的组件。

    ​ 这样让我们的代码更加方便组织和管理,并且扩展性也更强。

    ​ 所以,组件是Vue开发中,非常重要的一个篇章。

    2.2. 组件的基本步骤

    注册组件的基本步骤

    组件的使用分成三个步骤:

    ​ 1.创建组件构造器

    ​ 2.注册组件

    ​ 3.使用组件。

    我们来看看通过代码如何注册组件

    ​ 查看运行结果:

    ​ 和直接使用一个div看起来并没有什么区别。

    ​ 但是我们可以设想,如果很多地方都要显示这样的信息,我们是不是就可以直接使用<my-cpn></my-cpn>来完成呢?

    图片

    步骤解析

    1.Vue.extend():

    ​ 调用Vue.extend()创建的是一个组件构造器

    ​ 通常在创建组件构造器时,传入template代表我们自定义组件的模板。

    ​ 该模板就是在使用到组件的地方,要显示的HTML代码。

    ​ 事实上,这种写法在Vue2.x的文档中几乎已经看不到了,它会直接使用下面我们会讲到的语法糖,但是在很多资料还是会提到这种方式,而且这种方式是学习后面方式的基础。

    2.Vue.component():

    ​ 调用Vue.component()是将刚才的组件构造器注册为一个组件,并且给它起一个组件的标签名称。

    ​ 所以需要传递两个参数:

    ​ 1、注册组件的标签名

    ​ 2、组件构造器

    3.组件必须挂载在某个Vue实例下,否则它不会生效。

    ​ 我们来看下面我使用了三次<my-cpn></my-cpn>

    ​ 而第三次其实并没有生效:

    图片

    2.3. 全局组件和局部组件

    当我们通过调用Vue.component()****注册组件时,组件的注册是全局的

    这意味着该组件可以在任意Vue示例下使用。

    ​ 如果我们注册的组件是挂载在某个实例中, 那么就是一个局部组件

    图片

    2.4. 父组件和子组件

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
    </head>
    <body>
    
    <div id="app">
      <cpn2></cpn2>
      <!--<cpn1></cpn1>-->
    </div>
    
    <script src="../js/vue.js"></script>
    <script>
      // 1.创建第一个组件构造器(子组件)
      const cpnC1 = Vue.extend({
        template: `
          <div>
            <h2>我是标题1</h2>
            <p>我是内容, 哈哈哈哈</p>
          </div>
        `
      })
    
    
      // 2.创建第二个组件构造器(父组件),并在其中注册子组件
      const cpnC2 = Vue.extend({
        template: `
          <div>
            <h2>我是标题2</h2>
            <p>我是内容, 呵呵呵呵</p>
            <cpn1></cpn1>
          </div>
        `,
        // 在父组件中注册子组件
        components: {
          cpn1: cpnC1
        }
      })
    
      // root组件
      const app = new Vue({
        el: '#app',
        data: {
          message: '你好啊'
        },
        //注册父组件(局部组件)
        components: {
          cpn2: cpnC2
        }
      })
    </script>
    
    </body>
    </html>
    

    2.5. 注册的语法糖

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
    </head>
    <body>
    
    <div id="app">
      <cpn1></cpn1>
      <cpn2></cpn2>
    </div>
    
    <script src="../js/vue.js"></script>
    <script>
      // 1.全局组件注册的语法糖
      // 1.创建组件构造器
      // const cpn1 = Vue.extend({
      // template: `
      //     <div>
      //       <h2>我是标题1</h2>
      //       <p>我是内容, 哈哈哈哈</p>
      //     </div>
      //   `
      // })
    
      // 2.注册全局组件
      Vue.component('cpn1', {
        template: `
          <div>
            <h2>我是标题1</h2>
            <p>我是内容, 哈哈哈哈</p>
          </div>
        `
      });
    
      // 2.注册局部组件的语法糖
      const app = new Vue({
        el: '#app',
        data: {
          message: '你好啊'
        },
        components: {
          'cpn2': {
            template: `
              <div>
                <h2>我是标题2</h2>
                <p>我是内容, 呵呵呵</p>
              </div>
        `
          }
        }
      })
    </script>
    
    </body>
    </html>
    

    图片

    2.6. 模板的分类写法

    刚才,我们通过语法糖简化了Vue组件的注册过程,另外还有一个地方的写法比较麻烦,就是template模块写法。

    如果我们能将其中的HTML分离出来写,然后挂载到对应的组件上,必然结构会变得非常清晰。

    Vue提供了两种方案来定义HTML模块内容:

    • script

    • template

      图片

    2.7. 数据的存放

    • 子组件不能直接访问父组件
    • 子组件中有自己的data属性, 而且必须是一个函数.也可以有methods等属性
    • 为什么必须是一个函数.
      • 首先,如果不是一个函数,Vue直接就会报错。
      • 其次,原因是在于Vue让每个组件对象都返回一个新的对象,因为如果是同一个对象的,组件在多次使用后会相互影响。

    2.8. 父子组件的通信

    • 父传子: props

    • 子传父: $emit

      图片

    2.8.1 props基本用法(父传子)

    props的值有两种方式:

    ​ 方式一:字符串数组,数组中的字符串就是传递时的名称。

    ​ 方式二:对象,对象可以设置传递时的类型,也可以设置默认值等。

    图片

    2.8.1.2 props数据验证(对象写法)

    验证都支持哪些数据类型呢?

    ​ 1.String

    ​ 2.Number

    ​ 3.Boolean

    ​ 4.Array

    ​ 5.Object

    ​ 6.Date

    ​ 7.Function

    ​ 8.Symbol

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
    </head>
    <body>
    
    <div id="app">
      <!--<cpn v-bind:cmovies="movies"></cpn>-->
      <!--<cpn cmovies="movies" cmessage="message"></cpn>-->
    
      <cpn :cmessage="message" :cmovies="movies"></cpn>
    </div>
    
    
    
    <template id="cpn">
      <div>
        <ul>
          <li v-for="item in cmovies">{{item}}</li>
        </ul>
        <h2>{{cmessage}}</h2>
      </div>
    </template>
    
    <script src="../js/vue.js"></script>
    <script>
      // 父传子: props
      const cpn = {
        template: '#cpn',
        // props: ['cmovies', 'cmessage'],
        props: {
          // 1.类型限制
          // cmovies: Array,
          // cmessage: String,
    
          // 2.提供一些默认值, 以及必传值
          cmessage: {
            type: String,
            default: 'aaaaaaaa',
            required: true
          },
          // 类型是对象或者数组时, 默认值必须是一个函数
          cmovies: {
            type: Array,
            //是个函数
            default() {
              return []
            }
          }
        },
        data() {
          return {}
        },
        methods: {
    
        }
      }
    
      const app = new Vue({
        el: '#app',
        data: {
          message: '你好啊',
          movies: ['海王', '海贼王', '海尔兄弟']
        },
        components: {
          cpn
        }
      })
    </script>
    
    </body>
    </html>
    

    图片

    当有自定义构造函数时,验证也支持自定义的类型

    图片

    2.8.2 自定义事件的基本用法(子传父)

    什么时候需要自定义事件呢?

    ​ 当子组件需要向父组件传递数据时,就要用到自定义事件了。

    ​ 我们之前学习的v-on不仅仅可以用于监听DOM事件,也可以用于组件间的自定义事件。

    自定义事件的流程:

    ​ 1.在子组件中,通过$emit()来触发事件。

    ​ 2.在父组件中,通过v-on来监听子组件事件。

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
    </head>
    <body>
    
    <!--父组件模板-->
    <div id="app">
      <!--v-on监听子组件的自定义事件-->
      <cpn @item-click="cpnClick"></cpn>
    </div>
    
    <!--子组件模板-->
    <template id="cpn">
      <div>
        <button v-for="item in categories"
                @click="btnClick(item)">
          {{item.name}}
        </button>
      </div>
    </template>
    
    <script src="../js/vue.js"></script>
    <script>
      // 1.子组件
      const cpn = {
        template: '#cpn',
        data() {
          return {
            categories: [
              {id: 'aaa', name: '热门推荐'},
              {id: 'bbb', name: '手机数码'},
              {id: 'ccc', name: '家用家电'},
              {id: 'ddd', name: '电脑办公'},
            ]
          }
        },
        methods: {
          btnClick(item) {
            // 发射事件: 自定义事件
            this.$emit('item-click', item)
          }
        }
      }
    
      // 2.父组件
      const app = new Vue({
        el: '#app',
        data: {
    
        },
        components: {
          cpn
        },
        methods: {
          cpnClick(item) {
            console.log('cpnClick', item);
          }
        }
      })
    </script>
    
    </body>
    </html>
    

    图片

  • 相关阅读:
    PHP计算近1年的所有月份
    mysql的索引和锁
    深度解析 https 协议
    linux 常用命令大全
    为什么Python3.6字典变得有序了?
    oddo
    RESTful接口开发规范
    python中的 __inti__ 和 __new__ 方法的区别
    十大经典算法 Python实现
    MongoDB journal 与 oplog,究竟谁先写入?--转载
  • 原文地址:https://www.cnblogs.com/jsccc520/p/12893084.html
Copyright © 2020-2023  润新知