vue基础知识总结

一、vue区分动态绑定class和style:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述 在这里插入图片描述

二、reduce方法

1、语法
arr.reduce(callback,[initialValue])

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

callback (执行数组中每个值的函数,包含四个参数)

    1、previousValue (上一次调用回调返回的值,或者是提供的初始值(initialValue))
    2、currentValue (数组中当前被处理的元素)
    3、index (当前元素在数组中的索引)
    4、array (调用 reduce 的数组)

initialValue (作为第一次调用 callback 的第一个参数。)
2、实例解析 initialValue 参数

先看第一个例子:

var arr = [1, 2, 3, 4];
var sum = arr.reduce(function(prev, cur, index, arr) {
    console.log(prev, cur, index);
    return prev + cur;
})
console.log(arr, sum);
打印结果:
1 2 1
3 3 2
6 4 3
[1, 2, 3, 4] 10

这里可以看出,上面的例子index是从1开始的,第一次的prev的值是数组的第一个值。数组长度是4,但是reduce函数循环3次。

再看第二个例子:

var  arr = [1, 2, 3, 4];
var sum = arr.reduce(function(prev, cur, index, arr) {
    console.log(prev, cur, index);
    return prev + cur;
},0) //注意这里设置了初始值
console.log(arr, sum);
打印结果:
0 1 0
1 2 1
3 3 2
6 4 3
[1, 2, 3, 4] 10

这个例子index是从0开始的,第一次的prev的值是我们设置的初始值0,数组长度是4,reduce函数循环4次。

结论如果没有提供initialValue,reduce 会从索引1的地方开始执行 callback 方法,跳过第一个索引。如果提供initialValue,从索引0开始。

注意:如果这个数组为空,运用reduce是什么情况?

var  arr = [];
var sum = arr.reduce(function(prev, cur, index, arr) {
    console.log(prev, cur, index);
    return prev + cur;
})
//报错,"TypeError: Reduce of empty array with no initial value"

但是要是我们设置了初始值就不会报错,如下:

var  arr = [];
var sum = arr.reduce(function(prev, cur, index, arr) {
    console.log(prev, cur, index);
    return prev + cur;
},0)
console.log(arr, sum); // [] 0

所以一般来说我们提供初始值通常更安全

3、reduce的简单用法

当然最简单的就是我们常用的数组求和,求乘积了。

var  arr = [1, 2, 3, 4];
var sum = arr.reduce((x,y)=>x+y)
var mul = arr.reduce((x,y)=>x*y)
console.log( sum ); //求和,10
console.log( mul ); //求乘积,24
4、reduce的高级用法

(1)计算数组中每个元素出现的次数

let names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];

let nameNum = names.reduce((pre,cur)=>{
  if(cur in pre){
    pre[cur]++
  }else{
    pre[cur] = 1 
  }
  return pre
},{})
console.log(nameNum); //{Alice: 2, Bob: 1, Tiff: 1, Bruce: 1}

(2)数组去重

let arr = [1,2,3,4,4,1]
let newArr = arr.reduce((pre,cur)=>{
    if(!pre.includes(cur)){
      return pre.concat(cur)
    }else{
      return pre
    }
},[])
console.log(newArr);// [1, 2, 3, 4]

(3)将二维数组转化为一维

let arr = [[0, 1], [2, 3], [4, 5]]
let newArr = arr.reduce((pre,cur)=>{
    return pre.concat(cur)
},[])
console.log(newArr); // [0, 1, 2, 3, 4, 5]

将多维数组转化为一维

let arr = [[0, 1], [2, 3], [4,[5,6,7]]]
const newArr = function(arr){
   return arr.reduce((pre,cur)=>pre.concat(Array.isArray(cur)?newArr(cur):cur),[])
}
console.log(newArr(arr)); //[0, 1, 2, 3, 4, 5, 6, 7]

(4)对象里的属性求和

var result = [
    {
        subject: 'math',
        score: 10
    },
    {
        subject: 'chinese',
        score: 20
    },
    {
        subject: 'english',
        score: 30
    }
];

var sum = result.reduce(function(prev, cur) {
    return cur.score + prev;
}, 0);
console.log(sum) //60

三、计算属性computed

1.计算属性的本质是computed对象(属性)中套了一个对象(属性),而这个对象里有两个方法,一个set,另一个是get。
在这里插入图片描述
2.一般情况set方法不需要实现,只需要get方法,即为只读属性但是当我们在修改属性值的时候,就会触发set方法。

3.计算属性和methods对比
当界面多次渲染属性时,computed只调用一次,性能较高,内部对计算属性做了缓存,会观察计算属性是否改变,没改变就返回原来结果。
在这里插入图片描述

四、块级作用域等于闭包

1.在ES6之前,for和if没有作用域,而函数是有的。以下是函数的闭包。
在这里插入图片描述
ES5中的var是没有块级作用域的(if/for)
ES5之前因为if和for没有块级作用域的概念,所以在很多时候,我们都必须借助于function的作用域来解决应用外面变量的问题

ES6中的let是由有块级作用域的(if/for)
ES6中,加入了let,let是有if和for的块级作用域、

2.const
在开发中,优先使用const,除非要改变某一标识符的时候,才使用let。
注意:
(1)在给const修饰的标识符赋值之后,不能修改。
(2)在使用const定义标识符,必须进行赋值。
(3)常量的含义是指向的对象不能修改,但可以改变对象内部属性。

这里const修饰了一个变量obj,它现在指向一个对象,对象里面有几个属性,现在整体的obj有个内存地址0x333,obj指向对象的本质就是它保存了对象的0x333这个地址。
现在有个新的对象,有个新的地址0x666,经过const修饰之后,就不能指向新的对象。
现在假设要改0x333这个地址里面的对象属性,假如name值变成了’kobe’,但这里的地址没变,里面的属性值可以随便改,但是如果要obj这个变量经过const修饰之后指向一个新的对象就不可以了。
在这里插入图片描述
3.对象字面量增强写法
对象字面量:在图中,对象字面量就是{}。
在这里插入图片描述
对象字面量不仅能放属性,也能放函数。
在这里插入图片描述
属性的增强写法。它自动会把属性名称作为key,属性值作为value,所以可以简化写法。
在这里插入图片描述
函数的增强写法,不需要先写key,再写个function()。
在这里插入图片描述

五、事件监听

单个参数,拿到event
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
方法中多个参数拿到event------$event
在这里插入图片描述
在这里插入图片描述

六、v-if/v-else

在这里插入图片描述
在这里插入图片描述
input复用问题:
在这里插入图片描述
在这里插入图片描述

七、v-for

在这里插入图片描述
在DOM渲染到浏览器之前,会有一个虚拟DOM。
这里的插入元素,没有key时,它会逐个对比(相当于顺序表),挨个对比,把不一样的逐个按顺序替换。
在绑定了key之后(key不是随便绑定的,是需要与循环的item一一对应,所以不要绑定index,index并不与item一一对应,要绑定item---->v-for=“item in arr” :key=“item” ),有了key内存里就是链表,插入的时候是根据key插入,不是根据顺序插入,key就好比身份证号,是唯一的,在插队的时候,根据身份证号可以直接插队,没有身份证号就会按照顺序插队。
有了key之后进行diff算法时,它会先查看有key的li发生变化了没有,没有变化就会直接运用,在插入元素的时候,会创建一个新元素,并把这个新元素插入到正确的位置,以此提高性能。
在这里插入图片描述
有些时候改变数组的值,界面上不会实时更新,所以需要使用数据的一些响应式方法。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

八、过滤器filters

一般来说,filters是一个函数,把要过滤的参数传入filters的函数里面。
在这里插入图片描述
在这里插入图片描述
补充:数组遍历的几种方式:
编程范式:命令式编程(一步步命令) / 声明式编程(拿到数据,把数据保存到某个位置,然后做个指令声明,比如v-for,之后会对数据自动进行编译,现在愈发流行)
编程范式:面向对象编程(尽可能把很多东西抽象成一个对象,因为对象可封装可继承还有多态性,第一公民是对象)/ 函数式编程(第一公民是函数,把东西抽象成函数,好处:可进行链式编程)
在这里插入图片描述
在这里插入图片描述

九、高阶函数

1.filter函数
在这里插入图片描述
2.map函数
在这里插入图片描述
3.reduce函数(重点)
在这里插入图片描述

十.v-model

1.实现了双向绑定
在这里插入图片描述
2.本质:在这里插入图片描述3.v-model结合radio类型
在这里插入图片描述
4.v-model结合checkbox(单选框和多选框)
单选是布尔类型,多选是数组类型。
在这里插入图片描述
5.v-model结合select
单选是字符串类型,多选是数组类型。
在这里插入图片描述
7.值绑定
有时候value值会被直接写死,如上图,但是实际开发这里都是可选的,此时动态的把服务器给的数据遍历出来,给用户选择。值绑定的意思就是动态的获取,然后绑定值(实质就是v-bind)。
在这里插入图片描述
8.修饰符
默认情况下v-model输入的值都会转为string类型,加个.number修饰符就可以变为number类型。
在这里插入图片描述

十一.组件化开发

1.组件的原理
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

<script src="../js/vue.js"></script>
<script>
  // 1.创建组件构造器对象
  const cpnC = Vue.extend({
    template: `
      <div>
        <h2>我是标题</h2>
        <p>我是内容, 哈哈哈哈</p>
        <p>我是内容, 呵呵呵呵</p>
      </div>`
  })

  // 2.注册组件(传入两个参数:组件名称、组件构造器)
  Vue.component('my-cpn', cpnC)

  const app = new Vue({
    el: '#app',
    data: {
      message: '你好啊'
    }
  })
</script>

组件的使用要放到vue实例里面
在这里插入图片描述
2.全局组件和局部组件
在这里插入图片描述

<div id="app">
  <cpn></cpn>
</div>

<div id="app2">
  <cpn></cpn>
</div>

<script src="../js/vue.js"></script>
<script>
  // 1.创建组件构造器
  const cpnC = Vue.extend({
    template: `
      <div>
        <h2>我是标题</h2>
        <p>我是内容,哈哈哈哈啊</p>
      </div>
    `
  })

  // 2.注册组件(全局组件, 意味着可以在多个Vue的实例下面使用)
  // Vue.component('cpn', cpnC)

  // 疑问: 怎么注册的组件才是局部组件了?
// 在vue实例中有个components属性,在components属性中进行注册就可以变为局部组件。
  const app = new Vue({
    el: '#app',
    data: {
      message: '你好啊'
    },
    components: {
      // cpn:使用组件时的标签名
      // 这个局部组件只能在id为app的页面中显示,而app2中此组件无法展示
      cpn: cpnC
    }
  })

  const app2 = new Vue({
    el: '#app2'
  })
</script>

3.父组件和子组件
在这里插入图片描述

<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>

4.语法糖(去掉extend)
在这里插入图片描述

<div id="app">
  <cpn1></cpn1> 
  // vue.component注册的是全局组件
  // 不用在下面的vue实例里面声明就可以直接使用cpn1
  
  <cpn2></cpn2>
</div>

<script src="../js/vue.js"></script>
<script>
  // 1.全局组件注册的语法糖
  // 1.创建组件构造器
  // const cpn1 = Vue.extend() 
  // 语法糖: 这里去掉extend这一行

  // 2.注册组件
  // 这里语法糖就是:把之前构造组件的extend代码取消
  // 直接把extend里的对象,写到注册组件的第二个参数
  // 等同于去掉extend,把注册组件时传的第二个参数组件构造器替换成这个对象
  Vue.component('cpn1', {
    template: `
      <div>
        <h2>我是标题1</h2>
        <p>我是内容, 哈哈哈哈</p>
      </div>
    `
  })

  // 2.注册局部组件的语法糖
  // 直接在vue实例里写个components属性,然后声明一下
  // 就等同于局部组件的注册了,也省去了extend构造
  const app = new Vue({
    el: '#app',
    data: {
      message: '你好啊'
    },
    // 写法:components: { '组件名称':{template:`内容`}}
    components: {
      'cpn2': {
        template: `
          <div>
            <h2>我是标题2</h2>
            <p>我是内容, 呵呵呵</p>
          </div>
    `
      }
    }
  })
</script>

5.模板分离写法

<div id="app">
  <cpn></cpn>
  <cpn></cpn>
  <cpn></cpn>
</div>

<!--1.script标签, 注意:类型必须是text/x-template 再加上id-->
<script type="text/x-template" id="cpn">
<div>
<h2>我是标题</h2>
<p>我是内容,哈哈哈</p>
</div>
</script>

<!--2.template标签-->
<template id="cpn">
  <div>
    <h2>我是标题</h2>
    <p>我是内容,呵呵呵</p>
  </div>
</template>

<script src="../js/vue.js"></script>
<script>

  // 1.注册一个全局组件
  Vue.component('cpn', {
  // 取到id为cpn的模板
    template: '#cpn'
  })

  const app = new Vue({
    el: '#app',
    data: {
      message: '你好啊'
    }
    // 全局组件,不用在此处写component属性
  })
</script>

6.组件不可以访问vue实例数据,有自己的数据保存地方
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
举例:
用函数相当于每次动态创造一个新的内存
在这里插入图片描述
在这里插入图片描述
这就是为什么data是个函数,为了组件被多处复用的时候,有各自的数据,相互之间不会产生影响。

7.父子组件的通信
在这里插入图片描述
(1)父传子
在这里插入图片描述

<div id="app">
// 必须用v-bind绑定 取父组件的值
  <!--<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>

在这里插入图片描述

父传子:在子组件定义props,在父组件中的子组件标签写v-bind:子组件的data=“父组件的data”,通过这个把父组件的值传给子组件,子组件拿到父的值后,就可以通过自己需要的样式对值进行渲染。
(注意:组件名称,组件data的值的名称,以及方法的名称,均要小写,并且避免在子组件中修改绑定的值,props的值应该在父组件中修改)
在这里插入图片描述
驼峰标识需写成短横线形式,否则数值获取不到。
在这里插入图片描述
(2)子传父
在这里插入图片描述
子传父:在子组件里有个事件,这个事件里面有个this.$emit(‘子组件事件名称’,参数),在父组件的子组件标签里写@子组件事件名称=“父组件事件名称”

<!--父组件模板-->
<div id="app">
  <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: {
      message: '你好啊'
    },
    components: {
      cpn
    },
    methods: {
      cpnClick(item) {
        console.log('cpnClick', item);
      }
    }
  })
</script>

在这里插入图片描述
(3)案例:修改值
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
(4)父子访问
在这里插入图片描述
$refs用的较多-----父访问子
在这里插入图片描述
在这里插入图片描述

不建议使用parent,因为一旦用了$parent,就代表组件的复用性降低了。
在这里插入图片描述

访问根组件是$root(访问到vue实例),也用的很少,因为vue实例里面一般放的是最重要的东西,比如路由、vuex。
在这里插入图片描述

十二、slot插槽

1.基本使用

为了使组件具备扩展性,每次使用组件都能加不一样的东西。
在这里插入图片描述
在这里插入图片描述
在封装组件的时候,当大体结构一致,而内容有不一样的情况时,就留一个slot插槽。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
设置默认值
在这里插入图片描述
在这里插入图片描述

2.具名插槽

在这里插入图片描述

<body>

    <div id="app">
        <cpn v-show="isShow"><span slot="center">标题</span></cpn>
    </div>
    <template id="cpn">
        <div>
            <slot><span>左边</span></slot>
            <slot name="center"><span>中间</span></slot>
            <slot><span>右边</span></slot>
        </div>
    </template>
    <script>
/**
父组件模板的所有东西都会在父级作用域内编译
子组件模板所有的东西都会在子级作用域编译
*/

        const cpn = {
            template:'#cpn',
            data(){
                return{
                    isShow:true
                }
            }
        }
        var vm = new Vue({
            el: '#app',
            data: {
                isShow:false
            },
            methods: {},
            components:{
                cpn
            }
        });
    </script>
</body>

在这里插入图片描述

3.作用域插槽

在这里插入图片描述

<body>

    <div id="app">
        <cpn></cpn>
        <cpn>
            <br>
            <br>
           <!-- 目的是获取子组件的pLanguage -->
          <template slot-scope="slot">
              <span v-for="item in slot.data">{{item}} - </span>
              <br>
            <span>{{slot.data.join(' - ')}}</span>
          </template>
        </cpn>
    </div>
    <template id="cpn">
        <div>
           <slot :data="pLanguages"><li v-for="item in pLanguages">{{item}}</li></slot>
        </div>
    </template>
    <script>
/**
父组件替换插槽的标签,但是内容是由子组件来提供
*/

        const cpn = {
            template:'#cpn',
            data(){
                return{
                   pLanguages: ['javascript','c++','go','java']
                }
            }
        }
        var vm = new Vue({
            el: '#app',
            data: {
                isShow:false
            },
            methods: {},
            components:{
                cpn
            }
        });
    </script>
</body>

在这里插入图片描述
现在已经用v-slot替换此语法了

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值