尚硅谷-vue整理

1,800

第一章 :Vue核心

一、简介

1.1内容

image.png

1.2 什么是vue

一套用户构建用户界面的渐进式JavaScript框架 (vue可以自底向上逐层的应用)

  • 简单:只需要一个轻量而小巧的核心库
  • 复杂:可以引入各种各样的vue插件

1.1 特点

  • 1、组件化模式、提高代码复用率、且让代码更好维护
  • 2、声明式编码、无需DOM、提高开发效率

1.2 初始vue

  • 1、想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象
  • 2、root容器中的代码依然要符合html规范,只不过混入了一些特殊的Vue语法
  • 3、root容器里的代码被称为【Vue模板】

image.png

1.3 初识vue细节点

  • 1、注意区分:JS表达式和JS代码

     表达式:一个表达式会生成一个值,可以放在任何一个需要值的地方
            a+b
            x==y?a:b
    
     JS代码:iffor循环
       
    

1.4 模板语法

  • 1、插值语法

     功能:往往用于指定标签体内容
     写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有属性
    
  • 2、指令语法

     功能:用于解析标签(包括:标签属性、标签体内容、绑定事件....)
     备注:Vue中有很多指令,且形式都是v-???
    
  • 3、vue里的两种数据绑定

       v-bind:单向绑定  简写 :
    
       v-model:双向数据绑定
    
       v-model指令只能应用在表单类(输入类)元素,因为用户可以与之进行交互
    

    例如input、textarea

image.png

1.5、el和data的两种写法

data和el都有两种写法

     1、el两种写法
        (1)new Vue时候配置el属性
         (2)先创建Vue实例,随后再通过vm.$mount('#root')指定el的值
     2data的两种写法
        (1)对象式
        (2)函数式
        
        以后在使用组件的时候,data必须使用函数式,否则就会报错
     3、一个重要的原则:
         由Vue管理的函数一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例了

image.png

  • 1.6 MVVM

    Vue在一定程度上遵循MVVM模型

    • M:模型(model):对应data中的数据
    • V:视图(View):模版
    • VM:视图模型(ViewModel):Vue实例对象

    因此在文档中经常会使用 vm (ViewModel 的缩写) 这个变量名表示 Vue 实例。

    注意:1data中的所有属性,最后都出现在了vm身上
         2、vm身上所有的属性以及Vue原型上所有的属性,在Vue模板中都可以直接使用
    

image.png

二、事件代理

2.1 Object.definePrototype

  1. 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
  2. 通过使用defineProperty可以对对象进行高级的限制
  3. Object.defineProperty(obj, prop, descriptor)

image.png

2.2 什么是数据代理

数据代理:通过一个对象代理对另一个对象中的属性的操作(读/写)

image.png

2.3 Vue是如何应用数据代理的

基本原理:

 通过Object.defineProperty()把data对象中所有属性添加到vm上
 为每一个添加到vm上的属性,都指定一个getter/settergetter/setter内部去操作(读/写)data中对应的属性

原理分析 通过vm读name、改name、通过vm读age、改age都是数据代理。 image.png

image.png

数据代理做了什么事?把data中的数据放到vm身上,有了数据代理,我们读取name、address就不需要_data中读取,可以直接通过vm.data、vm.address获取 image.png

三、事件处理

3.1事件基本使用

  1. 使用v-on:xxx或@xxx绑定事件,其中xxx是事件名
  2. 事件回调需要配置在methods对象中,最终会在vm上
  3. methods中配置的函数,不要用箭头函数,否则this就不是vm了
  4. methods中配置的函数,都要被Vue所管理的函数,this的指向是vm或者组件实例对象 5.@click=“demo”和@click($event)效果一样,但是后者可以传参

3.2事件修饰符

image.png

  1. 阻止冒泡 .stop
  2. 阻止默认事件 .prevent
  3. 事件只触发一次 .once

修饰符可以连着用,先阻止冒泡,然后阻止默认事件等等

3.3 键盘事件

image.png

九个常用的别名 image.png

  • 键盘上任何一个键都有自己的编码,例如enter等于13编码

  • 特殊的键,tab必须配合keydown使用才有效

  • 系统修饰键,ctrl\alt\shift\meta这四个也很特殊。

    1. 按下修饰键的同时再按下其他键然后释放那个键才生效
    2. 配合keydown,立即生效
  • 可以通过键码,keydown.13,但是不推荐了,因为不同键盘,键码不统一

四、计算属性

4.1 插值语法实现姓名案例

image.png

分析: 这种写法没有问题,但是不符合vue模板语法简洁风格,如果我只想要姓中前三位,无论我输入多少位,只需要前三位,那么模板语法就会越来越长。

4.2 methods语法实现姓名案例

image.png

分析:data中的数据,任何一个数据发生改变,如果模板中用到这个数据,vue模板都会重新解析。 模板中自己调用方法,方法也会重新调用,如果我们改变data中的数据会不断的调用.

4.3 computed语法实现姓名案例

计算属性

  • 定义:要用的属性不存在,通过已有的属性计算出来。

  • 原理:底层就是借助了Object.defineprototype方法提供的getter和setter

  • 优势:与methods实现相比那,内部有缓存机制(复用),效率更高,调试方便。

  • get什么时候调用? 1、初次读取fullname的时候,get会被调用。2、所依赖的数据发生(firstname,lastname)变化时

  • set什么时候被调用?当fullname被修改的时候

  • 备注

         计算属性最终会出现在vm上,直接读取使用即可
         如果计算属性要被修改,必须写set函数去响应修改,且set中要引起计算时所依赖的数据去发生变化
    

image.png

image.png

简写

注意:简写的计算属性,表面上虽然是一个函数,但是实际上是执行了函数往wm身上放了一个叫fullname的值(是这个函数执行的结果)

image.png

五、 监视属性

5.1 watch语法实现姓名案例

总结

  1. 当监视属性变化时,回调函数自动调用,进行相关操作

  2. 监视属性必须存在,才能进行监视

  3. 监视有两种写法:

    (1) new Vue传入watch配置 (2) 通过vm.$watch监视

image.png

5.2 深度监视

深度监测

  1. Vue提供的watch默认是不监测对象内部值的改变的(一层)
  2. 配置deep:true可以监测对象内部值的改变(多层)

备注

  1. Vue自身可以监测对象内部值的改变,但是Vue提供的watch默认是不可以的
  2. 使用Watch时根据数据的内部结构,决定是否采取深度监视
  3. 默认不开启深度监视是为了效率

image.png

5.3 监视简写

什么情况写可以简写?

配置中不需要immediate、deep的时候可以简写

第一种new Vue配置的watch简写

image.png

第二种,vm.$watch简写

image.png

5.4 监视(侦听)属性和计算属性的区别

总结

  1. 计算属性里面是不能开启异步任务去维护数据,靠的就是返回值
  2. watch不是靠返回值,watch靠自己亲自去写代

computed能完成的用watch一定能完成,watch能完成的computed不一定能完成,例如异步操作

原则

  1. 所有被vue管理的函数最好写成普通函数(尤其函数内部用到vm的时候),这样this的指向才是vm或者组件实例对象
  2. 所有不被vue所管理的函数(定时器的回调函数、ajax放入回调函数、Promise的回调函数等),最好写成箭头函数,这样this的指向才是vm或者组件实例对象

监听属性实现姓名案例,命令式且重复的。 image.png

六、class和style绑定

class

绑定class样式--字符串,适用于:样式的类名不确定,需要动态绑定的

     :class="mood"

绑定class样式--数组,适用于:要绑定的样式个数不确定、名字也不确定

    :class="classArr"

绑定class样式--对象,适用于:要绑定的样式个数确定、名字也确定,用不用不确定

   :class="classObj"
    classObj:{
        a:false,
        b:false
    }
    

style

  1. 写法1:

     :style="{fontSize:fsize+'px'}"
    
  2. 写法2:

     :style="styleObj"
     styleObj:{
        fontSize:'40px'
     }
     
    
  3. 写法3

    :style="[styleObj1,styleObj2]"
    
     :style="styleArr"
     styleArr:[{color:red},{fontSize:40px}]
    

七、条件渲染

v-if、v-show

  1. v-show的底层实现就是调整display、不展示的DOM没有被移除
  2. v-if为false的时候,结构也不存在了 3.使用v-if的时候,元素可能无法获取到,而使用v-show可以拿到

哪个更好? 频率高的用v-show、频率低的用v-if

v-if、v-else-if、v-else

  1. 逻辑等价于js中的if、else if 、else
  2. v-else-if必须配合v-if,v-if一定是一开始被使用的,不能被断
  3. template只能配合v-if不能配合v-show,template的存在不影响结构

八、列表渲染

8.1 基本列表

v-for指令,用于展示列表数据

特殊点: 基础列表,key不要漏掉!!key必须是唯一的。 image.png

  1. 可以遍历数组、对象、字符串

    数组最多
    
  2. 还可以遍历指定次数(这种非常罕见)

image.png

8.2 key的作用和原理

1. 用index作为key会有什么问题?

  • 如果对数据进行逆序的添加、删除等破坏顺序操作,产生没有必要的DOM更新,界面效果是没有问题的,但是效率低

  • 如果结构中还包括输入类的DOM:会产生错误的DOM更新,界面有问题

image.png

image.png

分析:新的虚拟DOM和旧的虚拟DOM进行Diff算法对比,key为0的老刘和旧的虚拟DOM张三都是index为0,所以老刘30会转换为真实DOM,但是老刘后面的input和左边一样,直接复用,所以张三的输入框被老刘直接复用了。 image.png 2.用id作为key?

分析:004 老刘和旧的虚拟DOM进行对比,发现不一样,那么直接生成真实DOM image.png

2.没有key会怎么样?

如果没有写key,那么vue会自动把index作为key,vue并不知道哪些是你的vue列表唯一标识。所以没有写key会出问题,因为index作为key不靠谱,尤其是在列表最前面插入数据

3.虚拟DOM中key的作用是?

key是虚拟DOM对象的标识,当数据发生变化时,vue会根据【新数据】生成【新的虚拟DOM】,随后Vue进行【新虚拟DOM】与旧虚拟【DOM】的差异比较,比较规则如下:

4.对比规则?

  1. 旧虚拟DOM中找到了新虚拟DOM相同的key:

      1. 若虚拟DOM中内容没变,直接使用之前的DOM
      1. 若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM
  2. 旧虚拟DOM中没有找到了新虚拟DOM相同的key:

      1. 创建新的真实DOM,随后渲染到页面

5.开发中如何选择key

  • 最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号,学号等

  • 如果不存在数据的逆序添加、删除等破坏结构的顺序,可以使用index

8.3 列表过滤

当computed能实现的时候,我们使用computed

image.png

8.4 列表排序

分析:使用计算属性,我们在上面使用计算属性进行过滤的时候,在这个基础上做排序。 计算属性返回filePerson的时候,不用着急返回,在过滤完以后,进行排序,排完顺序一起返回。

image.png

image.png

排序

sort方法,我们要清楚,sort方法能收到什么?需不需要写返回值?改不改变原数组? image.png

九、Vue技术-数据更新

Vue怎么知道我把Data改了?

我们可以写一个watch配置去监测data中的数据改变,然后做一些动作,这个是Vue留给程序员的配置。Vue还会有一个默认的还会有默认的监视,会监视data,一旦发生变化会更新用到data的地方。底层用到的是一套的监视逻辑。

9.1 Vue监测原理

Vue监测数据变化的原理

  1. vue会监视data中所有层次的数据

  2. 如何监视对象中的数据

     通过select实现监视,且要在new Vue时就传入要监测的数据
     1.对象中后追加的属性,vue默认不做响应式处理
     2.如果给后追加的属性做响应式,请使用如下api
       Vue.set(vm._data.student,'sex','男')
       等同于
       vm.$set(vm._data.student,'sex','男') 
     3.如何监测数组中的数据?
         通过包裹数组更新元素的方法实现,本质就是做了两件事
         重新解释模板,进而更新页面
     4. 在Vue修改数组中的某个元素一定要使用如下方法
         1、使用这些api、pushpopshiftunshiftsplicesortreverse
         2、Vue.set()或者vm.$set()
    

注意:

Vue.set()和vm.$set()不能给vm或vm的根数据对象添加属性!!!!

image.png

9.2 模拟数据监测

image.png

相比于Vue,我们模拟的不完善的地方

  1. vue里面可以直接vm.name,我们模拟的这个需要vm._data.name,因为vue做了数据代理
  2. 我们没有考虑对象里面还有对象,我们只考虑一层,vue考虑了n层,底层写了递归,直到没有对象了 vue监测数据就是靠set!

9.3 Vue.set使用

Vue.set(vm._data.student,'sex','男')
等同于
vm.$set(vm._data.student,'sex','男')
简写(vue内部数据代理了,所以直接通过vm.student)
Vue.set(vm.student,'sex','男')

image.png

注意:我们不能在data的根下面直接加一个属性,如果想要添加公司名称,我们可以定义一个对象,往对象里面加。

image.png

image.png

9.4 数组监测

只要你调用数组的这几个变更方法,能够被vue监测到,会促发视图更新 image.png

还可以通过以下方法

Vue.set(vm.student.hobby,1,'羽毛球')来改变hobby数组中第二个元素

9.5 大练习

 <div id="root">
      <button @click="student.age++">年龄+1</button>
      <button @click="addSex">添加性别属性,默认值男</button>
      <button  @click="modSex">修改性别</button>
      <button @click="addFriend">在列表首位添加以为朋友</button>
      <button @click="modFriend">修改列表首位</button>
      <button @click="addhobby">添加一个爱好</button>
      <button  @click="modhobby">修改第一个爱好</button>
        <h2>学生姓名:{{student.name}}</h2>
        <h2>学生年龄:{{student.age}}</h2>
        <h2 v-if="student.sex">学生性别:{{student.sex}}</h2>
        <!-- 遍历对象 -->
        <h2>朋友们</h2>
        <ul>
          <li v-for="(f,index) in student.friends" :key="index">
               {{f.name}}--{{f.age}}
          </li>
        </ul>
       <!-- 遍历数组 -->
        <h2>爱好</h2>
        <ul>
          <li v-for="(f,index) of student.hobby" :key="index">
               {{f}}
          </li>
        </ul>
    </div>
    <script type="text/javascript">
      Vue.config.productionTip = false; //阻止vue在启动生产生产提示
     const vm=  new Vue({
        el: "#root",
        data: {
            student:{
              name:'tom',
              age:18,
              hobby:['羽毛球','棒球','篮球'],
              friends:[
                {name:'Jerry',age:25},
                {name:'Tony',age:36}
              ],
          }
        },
        methods: {
          addSex(){
            // this就是vm
            // Vue.set(this.student,'sex','男')
             this.$set(this.student,'sex','男')
          },
          modSex(){
            this.student.sex='女'
          },
          addFriend(){
            // 使用了unshift,是vue支持的七种之一
            this.student.friends.unshift({name:'vina',age:18})
          },
          modFriend(){
            // this.student.friends[0]='xxx'  //这种修改方式是无效的,原因是数组的第0项没有set\get
            this.student.friends[0].name='kkk'  //这种方式是奏效的,原因是第0项中的name是有set和get的
          },
          addhobby(){
            this.student.hobby.push('学习')
          },
          modhobby(){
            // this.student.hobby.splice(0,1,'开车')
            // Vue.set(this.student.hobby,0,'开车')
            this.$set(this.student.hobby,0,'开车')
          }

        },
        
      });
    </script>

十、收集表单数据

  1. 收集表单数据:

    若:<input type="text">则v-model收集的就是value的值,用户输入的就是value值

    <input type="radio"> ,则v-model收集的是value值,且要给标签配置value值

    <input type="checkbox">,

       1、没有配置input的value属性,那么收集的就是checked(勾选或者未勾选,是布尔值)
       2、配置input的value属性
          (1)v-model的初始值是非数组,那么收集的就是checked(勾选或者未勾选,是布尔值)
          (2)v-model的初始值是数组,那么收集的就是value组成的数组
          
    

备注(v-model的三个修饰符):

    lazy、number、trim
 

十一、过滤器

过滤器:

  1. 定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)

  2. 语法:

     1、注册过滤器
          Vue.filter(name,callback)
          new Vue({filters:{})
     2、使用过滤器
          {{xxx | 过滤器}}
          v-bind="xxx | 过滤器"
    
  3. 过滤器也可以接受额外的参数,多个过滤器可以串联

  4. 过滤器并没有改变原本数据,是产生对应的新的数据

image.png

全局过滤器

 Vue.filter('mySlice',function(value){
        return value.slice(0,4)
      })

过滤器有两种用法:插值语法中使用以及v-bind中使用

<h4 :x="msg | mySlice">v-bind方式使用过滤器</h4>

十二、vue内置指令

  • v-bind:单项绑定解析表达式,可以简写为 :xxx
  • v-model:双向数据绑定
  • v-for:遍历数组/对象/字符串
  • v-on: 绑定时间监听,可以简写为@
  • v-if: 条件渲染(动态控制节点是否存在)
  • v-else
  • v-show
  1. v-text

    作用:向其所在的节点中渲染文本内容
    与插值语法区别:v-text灰替换掉节点中的内容,{{xxx}}不会、
    
  2. v-html

    相比于v-text,v-html可以解析dom结构
    安全性问题:   
        v-html有安全性问题,在网站上动态渲染任意html是非常危险的,容易导致XSS攻击
        一定要在可信的内容上使用v-html,永远不要用在用户提交的内容上
        
        
    
  3. v-clock

    没有值的直接使用

    1. 本质上是一个特殊的属性,Vue实例创建完毕后并接管容器后,会删掉v-cloak属性
    2. 使用css配合v-cloak可以解决网速慢时页面展示出插值语法未经解析的问题

    <h2 v-cloak>{{name}}</h2>

    配合标签选择器
    `[v-cloak]{
         display: none;
     }`
     
     vue工作的时候会删掉v-cloak
    

4.v-once

 v-once没有值的直接使用,所在的节点在初次动态渲染以后,就被视为静态内容了
 以后数据的改变不会引起v-once所在的结构的更新,可以用于优化性能
 

5.v-pre

  1.可以让vue跳过气所在节点的编译过程
  2.可以利用它跳过:没有使用指令语法,没有使用插值语法的节点,会加快编译

6.自定义指令

注意:

    1.指令命名的时候,多个单词需要用-连接
      v-big-number
    2.

自定义指令何时调用?

  1. 语法

      局部指令   
    
        new Vue({
            directives:{指令名:配置对象}
        })
    
         new Vue({
            directives:{指令名:回调函数}
        })
    
    全局指令
    
         Vue.directive(指令名,配置对象)
         Vue.directive(指令名,回调函数)
    
    
  2. 配置对象中常用的3个回调函数

    1. bind:指令与元素成功绑定时调用     
    2. inserted:指令所在元素被插入页面时调用  
    3. update:指令所在模板结构被重新解析时调用
    

备注:

   1.指令定义是不加v-,使用时需要加v-
   2.指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名

需求1:定义v-big指令,和v-text功能类似。但灰绑定的数值放大10倍

 回调函数式的:
 1.指令与元素成功绑定时(一上来)
 2.指令所在的模板被重新解析时,都会引起自定义指令调用

image.png

全局写法

image.png

需求2:定义v-fbind,和正常v-bind功能一样,但是可以让其绑定的input默认获取焦点

image.png

全局写法

image.png

十三、生命周期

13.1 生命周期

  1. 又名:生命周期回调函数、生命周期函数、生命周期钩子
  2. 是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数
  3. 生命周期函数的名字不可更改,但是函数的具体内容是由程序员来编写的
  4. 生命周期函数的this指向是vm或者组件实例对象

image.png

image.png

更新流程

只要修改data,就会进入更新流程

销毁流程

vm.$destroy() 完全销毁一个实例,清理它与其他实例的连接,解绑它全部指令以及事件监听器。

当我们页面不需要vm了,我们就把vm销毁了,但是销毁vm之前的模板还会在的,vm没了,但是它的工作成果还在,再更新data就不起作用了。

1、beforeDestroy
   
   能访问到数据,但是所有对数据的修改都不会触发更新,因为已经进入了销毁流程中了
   在此阶段:关闭定时器、取消订阅消息,解绑自定义事件等收尾工作
   

13.2 生命周期总结

四对生命周期钩子函数

  1. beforeCreate

    指的是数据检测、数据代理创建之前,(指的不是vm创建之前)
    

2.created

   创建完毕

3.beforeMount

4.mounted

  做一些初始化的事情,发送ajax请求,启动定时器,绑定自定义事件,订阅消息等初始化操作
 

5.beforeUpdate

6.updated

7.beforeDestroy

 收尾性工作,清除定时器、解绑自定义事件、取消订阅消息等收尾工作

8.destroyed

关于销毁Vue实例

 1、销毁后借助Vue开发者工具看不到任何信息
 2、销毁后自定义事件会失效,但是原生的DOM事件依然有效
 3、一般不会在beforeDestroy操作数据,即便操作数据也不会触发更新
       

第二章 :组件化编程

为什么要用组件?

 传统方式编写应用存在问题:1、依赖关系混乱,不好维护 2、代码复用率不高
 

组件的定义?

   实现应用中局部功能代码和资源的集合
   

模块?

   复用JS,简化js的编写,提高js的运行效率
   

组件

   复用编码,简化项目编码,提高运行效率
   

模块化

组件化

非单文件组件

   一个文件中包含有n个组件,
   
   

单文件组件

    一个文件中只包含有1个组件  (a.vue),一个.vue一个组件

一、非单文件组件

1.1 步骤

1、定义组件(创建组件)

image.png

2、注册组件

 全局注册

image.png

 局部注册

image.png

1.2 如何定义一个组件

使用Vue.extend(options)创建,其中options和new Vue(options)时传入的options几乎一样,但是也是有点区别的:

区别如下:

   1、el不需要写,因为最终所有的组件都要经过一个vm管理,由vm决定服务于哪个容器
   2data必须写成啊还是农户,避免组件被敷用时。数据存在引用关系

1.3 如何注册组件

 1、局部注册:靠new Vue的时候传入components选项
 2、全局注册:靠Vue.component('组件名',组件)
 
 

1.4 关于组件名

一个单词组成的:
     第一种:纯小写 school
     第二种:首字母大写 School
多个单词组成:
     第一种(kebab-case):my-school
     第二种(CamelCase):MySchool(需要Vue脚手架支持)
备注:
     组件名尽可能回避HTML中已经有的元素名称,例如h2、H2都不行
     可以使用name配置置顶组件在开发者工具中呈现的名字(大型开发、组件库会这么做)
     
关于组件标签
      第一种写法<school></school>
      第二种写法<school/>
      不使用脚手架时,<school/>会导致后续组件不能渲染
一个简写方式
      const school=Vue.extend(options)可以简写为:const school=options
      简写表面没有调用Vue.extend,实际上还是调用了Vue.extend

1.5组件嵌套


      const student=Vue.extend({
           name:'student',
           template:`<div>
                <h2>学生姓名:{{name}}</h2>
                <h2>学生年纪:{{age}}</h2>
                <h2></h2>
           </div>`,
           data(){
            return {
                name:'vina',
                age:18
            }
        }
      })
      const school=Vue.extend({
           name:'school',
           template:`<div>
                <h2>学校名称:{{name}}</h2>
                <h2>学校地址:{{address}}</h2>
                <student></student>
                <h2></h2>
           </div>`,
           data(){
            return {
                name:'zenlayer',
                address:'上海'
            }
        },
        // 局部注册组件,嵌套
          components:{
            student
          }
      })
      new Vue({
          el:"#root",
          components:{
            school
          }
      })

1.6 VueComponent构造函数

  1. school组件本质上是一个名为VueComponent的构造函数,且不算程序员定义的,是Vue.extend生成的。

  2. <school></school>或者<school/>。Vue解析时会帮我们创建school组件的实例对象。即Vue会帮我们执行:new VueComponent(option)

  3. 特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent!!! 4.关于this指向:

    (1)组件配置中:data函数、methods中的函数,watch中的函数,computed中的函数,他们的this均是【VueComponent实例对象】 (2)new Vue()配置中:data函数、methods中的函数,watch中的函数、computed中的函数,他们的this均是【Vue实例对象】

image.png

1.7 Vue实例和组件实例

    VueComponent实例对象,以后坚持vc,也可以称为组件实例对象
    Vue实例对象,以后简称为vm 
    vc有的vm都有,但是vm有的el,vc没有,el是根实例特有的

因为组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项,例如 datacomputedwatchmethods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项。

1.8 一个重要的内置关系

VueComponent.prototype.proto===Vue.prototype

为什么有这个关系?

 让组件实例对象(vc)可以访问到Vue原型上的属性和方法

Vue原型上有很多方法,如果没有VueComponent.prototype.proto===Vue.prototype这个关系,那么vue原型上的东西只有vm能用,vc不能用,利用原型链,使得vc可以使用vue原型上的方法。

image.png

必须要有原型的基础

1.9 data必须是一个函数

  大白话:防止一个组件被多次使用的时候存在数据的引用关系
  官方:每个实例可以维护一份被返回对象的独立的拷贝

二、单文件组件

2.1 编写单文件组件的步骤

1. 第一步:写组件

image.png

2. 第二步:汇总所有组件的App

image.png

3. 第三步:main.js去创建vue实例,并且指明为哪个容器服务

image.png

4. 第四步:页面展示 image.png

第三章 Vue脚手架

一、认识脚手架

1.1 关于不同版本的Vue

1、vue.js与vue.runtime.xxx.js区别

    vue.js是完整版的Vue,包含:核心功能+模板解析器
    vue.runtime.xxx.js是运行版的Vue,只包含:核心功能,没有模板解析器
    

2、因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,需要使用render函数接受到的createElement函数去指定具体的内容

1.2 vue inspect > output.js

Vue脚手架隐藏了所有webpack相关的配置,若想查看具体的webpack配置,执行vue inspect > output.js可以显示,这么做就是防止程序员去破坏配置。

1.3 vue.config.js

使用vue.config.js配置文件可以怼脚手架进行个性化定制,详情见:cli.vuejs.org/zh/config/#…

下面五个名字默认的配置文件不能改,如果我们想改,vue也提供了渠道,让我们可以修改默认的配置。 image.png

如果我们想要自定义入口文件,可以使用如下办法: image.png

image.png

二、组件相关知识点

2.1 ref属性

  1. 被用来给元素会这子组件注册引用信息(id的替代者)

  2. 应用在html标签上获取真实的DOM元素,应用在组件标签上是组件实例对象(vc)

  3. 使用方法:

    • 打标识:<h1 v-text="msg" ref="title"></h1>
    • 获取:this.$refs.title

2.2 props属性

image.png

注意点:不可以传key、ref等作为props命名

如何修改Props的值?

props是只读的,vue底层会检测到你对props的修改,如果发生修改,就会发出警告,若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data的数据。

image.png

2.3 mixin混入

  1. 功能:可以把多个组件共用的配置提取成一个混入对象

  2. 使用方法:

    第一步:定义混入,例如:

image.png

第二步:使用混入

1)全局:Vue.mixin(xxx)
     (2) 局部:mixins:['xxx']

2.4 插件

Vue里面的插件,本质上就是一个对象,但是必须包含install

Vue给我们提供api,用来应用(使用)插件 image.png

  1. 功能:用于增强Vue

  2. 本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件的使用者传递的数据

  3. 定义插件:

    对象.install=function(Vue,options){
      //1.添加全局过滤器
      Vue.filter(...)
      //2.添加全局指令
      Vue.directive(...)
      //3.配置全局混入
      Vue.mixin(...)
      //4.添加实例方法
      Vue.prototype.$myMathod=function(){....}
      Vue.protitype.$myProperty=xxx
    }
    

4.使用插件:Vue.use()

2.5 todo-list案例

  1. 组件化编码流程(通用)

     1. 拆分静态组件:组件要按照功能点拆分,命名不要与html元素冲突
     2. 实现动态组件:考虑好数据的存放位置,数据是一个组件在用还是一些组件在用:
         1)一个组件在用:放在组件自身即可
         2)一些组件在用:放在他们共同的父组件上(状态提升)
    
     3. 实现交互:从绑定事件开始
    
  2. props适用于

    (1)父组件==》子组件通信
    (2)子组件==》父组件通信(要求父先给子一个函数)
    
  3. 使用v-model要切记:v-model绑定的值,因为props是不可以修改的

  4. props传过来的若是对象类型的值,修改对象中的属性时Vue不会报错,但不推荐这样做

2.6 浏览器的本地存储

localStorage和sessionStorge统称为webStorage

1.存储内容大小一般支持5M组呕呕 2.浏览器听过window.localStorage和window.sessionStorage属性来实现本地存储机制 3.相关api

image.png

image.png

4.备注

1.sessionStorage存储的内容会随着浏览器窗口关闭而消失 2.LocalStorage存储的内容,需要手动清除才会消失 3.xxxxxStorage.getItem(xxx)如果xxx对应的value获取不到,那么getItem的返回值时null 4.JSON.parse(null)结果依然是null

2.7 绑定自定义事件实现子给父传递事件

子给父传递事件两种写法:

第一:通过父组件给子组件传递函数类型的props实现:子给父传递数据

APP(父)

<School :getSchoolName="getSchoolName"></School>
 
 getSchoolName(name){
        console.log("收到了学校名称:",name)
    },

school(子)

 props:['getSchoolName'],
 this.getSchoolName(this.name)
 

第二:通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(v-on)

APP(父)

  <Student v-on:zidingyi="getStudent"></Student>
  getStudent(name){
        console.log("getStudent被调用了!!",name)
    }

student(子)

   // 触发student组件实例对象上的
    this.$emit('zidingyi',this.name)

 

第三:通过父组件给子组件绑定一个自定义事件实现:子给父传递数据 (ref)
这种方法灵活性很强

APP(父)

 <student ref="student"></student>

 mounted() {
    this.$refs.student.$on('zidingyi',this.getStudent)
},

student(子)

  // 触发student组件实例对象上的
    this.$emit('zidingyi',this.name)

分析两种方法

  1. 必须都得在父组件中配置回调
  2. 通过props,在子组件中必须亲自去调用。通过自定义事件,在子组件中通过$emit触发这个事件

解绑事件

 // 解绑一个自定义事件
 this.$off('zidingyi')  //解绑一个
 this.$off(['zidingyi','demo'])//解绑多个
 this.$off()  //解绑所有

自定义事件总结

1.一种组件见通信方式,适用于:子组件--》父组件 2.使用场景:A是父组件,B是子组件,B想给A传递数据,那么就要在A中给B绑定自定义事件(事件的回调在A中) 3.绑定自定义事件:

1:第一种方式:在父组件中:<Demo @zidingyi="test"/>或者<Demo v-on:zidingyi="test"/>

2:第二种方式,在父组件中

` <student ref="student"></student>
   
   mounted() {
    this.$refs.student.$on('zidingyi',this.getStudent)
  },
`
3:若想让自定义事件只触发一次,可以使用once修饰符,或者$once方法

4. 触发自定义事件: this.emit(zidingyi,数据)5.解绑自定义事件:this.emit('zidingyi',数据) 5. 解绑自定义事件: this.off('zidingyi') 6. 组件也可以绑定原生的DOM事件,需要使用native修饰符 7.注意:通过 this.refs.xxx.refs.xxx.on('zidingyi',回调)绑定的自定义事件,回调要么配置在methods中,要么是箭头函数,否则this指向会出现问题

2.8 全局事件总线

实现任意组件间的通信,但是父子之前没必要麻烦事件总线,

  1. x必须让所有的组件都能找到

     Vue.prototype.P={a:1,b:2}
     
    
  2. 保证x可以调用到on,on,off,$emit

image.png

实践

main.js(安装全局事件总线)

  在创建vm的时候,在beforeCreate中安装全局事件总线,为什么要在vm中安装呢,因为这个傀儡必须具有$on$emit熟悉,我们要么定义一个vc,要么就在vm中安装

image.png

school

在school中,给傀儡$bus绑定事件,回调留在school中,但是我们用完了一定要把$bus上面的hello事件解绑了,因为vc消失,傀儡依旧在

image.png

Student

 在school中,

image.png

本质:

全局事件总线的本质就是自定义事件,只不过是绑定在vm身上

2.9 消息订阅与发布

 报纸的订阅与发布‘
   1.订阅报纸:住址
   2.邮递员送报纸:报纸
   
 消息的订阅与发布
   1.订阅消息:消息名(手机号)
   2.发布消息:消息内容
  • 需要数据的人订阅消息,订阅的名字很重要。提供数据的人发布数据。
  • 原生的JS没办法轻松实现订阅与发布,借助第三方库(推荐pubsub-js)

image.png

实践

是一种组件间的通信方式,适用于任意组件间的通信

 第一步:安装
      
      npm i pubsub-js
      
 第二步:引入+订阅
      import pubsub from 'pubsub-js'
     
      mounted() {
        pubsub.subscribe('hello',function(value,data){
           console.log("有人发布了hello消息,hello消息的回调执行了",value,data)
    })
},

第三步:引入+发布
      
      import pubsub from 'pubsub-js'
      
      methods: {
        sendStudentName(){
            // this.$bus.$emit('hello',666)
            pubsub.publish('hello',666)
        }
},  

第四步:取消订阅

 beforeDestroy() {
    // this.$bus.$off('hello')
    pubsub.unsubscribe(this.pubId)

},

2.10 nextTick

  1. 语法 this.$nextTick( callback )

  2. 作用:在下一次DOM更新结束后执行其指定的回调

  3. 什么时候用?

     当改变数据后,要基于更新后的DOM进行某些操作是,要在nextTick所指定的回调函数中执行
    

三、过渡与动画

3.1案例对比

CSS3实现动画,需要手动的切换类名 image.png

image.png

Vue实现动画,两个类名一个动画,transition包裹发生动画的DOM,无需手动切换类名 image.png

image.png

3.2 知识点

1.transition这个标签里面有个布尔值的appear属性, :appear="true"或者appear,设置节点在初始渲染的过渡