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>

图片

猜你喜欢

转载自www.cnblogs.com/jsccc520/p/12893084.html