Vue学习笔记

本文详细介绍了Vue的核心特性,包括声明式绑定、计算属性、监听属性、组件化编程、事件处理、过渡动画、Vuex状态管理和路由使用。强调了Vue的响应式系统和组件生命周期,还探讨了Vue在实际项目中的最佳实践,如使用Vue脚手架、组件自定义事件、数据持久化和组件间通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Vue核心

特点

  1. 采用组件化模式,提高代码复用率、且让代码更好维护
  2. 声明式编码,让编码人员无需直接操作DOM,提高开发效率
  3. 使用虚拟DOM+优秀的Diff算法,尽量复用DOM节点
  • 想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象
  • root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法
  • root容器里的代码被称为Vue模板

插值语法例子:

<body>
    <div id="root">
        <h1>Hello,{{name}}</h1>
    </div>
    <script type="text/javascript">
        // Vue.config.productionTip = false;
        //创建Vue实例
        new Vue({
            el: '#root', //el用于指定当前Vue实例为那个容器服务,值通常为css选择器字符串
            data: { //data中用于存储数据,数据供el所指定的容器去使用,值暂时先写成一个对象
                name: '陈润z'
            }
        })
    </script>
</body>

每个容器一一对应

指令语法例子:v-开头

  1. 单向绑定(v-bind:)数据只能从data流向页面

  2. 双向绑定(v-model)数据不仅能从data流向页面,还可以从页面流向data

    1. 只能用在表单类元素(输入类元素)上
    2. v-model:value可以简写为v-medel

data与el的2种写法

  1. el有两种写法
    1. new vue时候配置el属性
    2. 先创建vue实例,随后再通过vm.$mount(‘#root’)指定el的值
  2. data有两种写法
    1. 对象式
    2. 函数式
    3. 目前两种都可以用,学到组件时,data必须使用函数式,否则会报错
  3. 一定不要写箭头函数,this只需window而不是vue

事件修饰符

鼠标事件:

  1. prevent:阻止默认事件
  2. stop:阻止事件冒泡
  3. once:事件只触发一次
  4. capture:使用事件的捕获模式
  5. self:只有event.target是当前操作的元素是才出发事件
  6. passive:事件的默认行为立即执行,无需等待事件回调执行完毕

键盘事件:

  1. 回车:enter
  2. 删除:delete
  3. 退出:esc
  4. 空格:space
  5. 换行:tab
  6. 上:up
  7. 下:down
  8. 左:left
  9. 右:right

Vue未提供别名的按键,可以使用按键原始的key值去绑定,但注意要转为kebab-case

系统修饰键:ctrl、alt、shift、meta

配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发
配合keydown使用:正常触发事件

vue中允许链式编程

计算属性

  1. 定义:要用的属性不存在,要通过已有属性计算得来
  2. 原理:底层借助了Objcet.defineproperty方法提供的getter和setter
  3. get函数什么时候执行
    1. 初次读取时会执行一次
    2. 当依赖的数据发生改变时会被再次调用
  4. 优势:与methods实现相比,内部有缓存机制(复用)效率更高,调试方便
  5. 备注:
    1. 计算属性最终会出现在vm上,直接读取使用即可
    2. 如果计算属性要被修改,那必须写set函数去响应修改,切set中要引起计算时依赖的数据发生变化

监视属性watch

  1. 当被监视的属性变化时,回调函数自动调用,进行相关操作
  2. 监视的属性必须存在,才能进行监视!!!
  3. 监视的两种写法
    1. new Vue时传入watch配置
    2. 通过vm.$watch监视

深度监视

  1. Vue中的watch默认不监测对象内部值的改变(一层)
  2. 配置deep:true可以监测对象内部值的改变(多层)
  3. 备注
    1. vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以!
    2. 使用watch时根据的具体结构,决定是否采用深度监视

computed和watch之间的区别:

  1. computed能完成的功能,watch都可以完成
  2. watch能完成的功能,computed不一定能完成,例如watch可以进行异步操作

两个细节:

  1. 所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm或组件实例对象
  2. 所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等),最好写成箭头函数,这样this的指向才是vm或组件实例对象

Vue本身有自带的监测信息是否改变,但是有一个bug,用如下方法Vue开发者工具无法监测到无法监测到

//可以被监测到
this.persons[0].name = 'xxx'
this.persons[0].age = 50
this.persons[0].sex = '男'
//无法被监测到
this.persons[0]={id:'001',name:'xxx',age:'50',sex:'男'} 

Vue监测数据的原理

创建Vue数据时会把变量进行数据代理,Vue给它set get方法,如果不是一开始就创建的,则无法成功代理,也就无法完成响应式操作,一个对象中想用的数据一定要提前配置好.Vue提供了后期添加响应式数据的方法:Vue.set(‘想要给谁添加数据’,‘键’,‘值’) 或者vm.$set(),注意:这个方法只能给data数据里某一个对象里面追加属性,不能直接给data追加属性

Vue无法监测到数组里的的数据,数组对象Vue无法创建set get方法——无法响应式操作
但是在数组中可以调用数组中对应的7个方法,修改完数组后Vue重新编译并在页面展示

  1. Vue会监视data中所有层次的数据
  2. 如何监测对象中的数据
    1. 通过setter实现监视,且要在new Vue时就传入要监测的数据
      1. 对象中追加的属性,Vue默认不做响应式处理
      2. 如需给后添加的属性做响应式,请使用如下API
        1. Vue.set(‘想要给谁添加数据’,‘键’,‘值’)
        2. vm.$set(‘想要给谁添加数据’,‘键’,‘值’)
  3. 如何监测数组中的数据?
    1. 通过包裹数组更新元素的方法实现,本质就是做了两件事:
      1. 通过包裹数组更新元素的方法实现,本质就是做了两件事
        1. 调用原生对应的方法对数组进行更新(7个)
        2. 重新解析模板进而更新页面 同上API
  4. 在Vue修改数组中的某个元素一定要用如下方法
    1. push() pop() shift() unshift() splice() sort() reverse()
    2. Vue.set() 或 vm.$set()
  5. 特别注意:Vue.set() 和vm.$set() 不能给vm或vm的 根数据对象添加属性!!! data和data在data一级的对象

绑定样式:

v-bind:class 缩写 :class

  1. class样式
    1. 写法:class=“xxx” xxx可以是字符串、对象、数组
    2. 字符串写法适用于:类名不确定,要动态获取
    3. 对象写法适用于:要绑定多个样式,个数不确定,名字也不确定
    4. 数组写法适用于:要绑定多个样式,个数确定,,名字也确定,但不确定用不用
  2. style样式
    1. :style="{fontSize:xxx}"其中xxx是动态值
    2. :style="{a,b}"其中a、b是样式对象 样式对象必须是Css样式里存在的,而且要符合驼峰命名规则
    3. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-saL7CdhL-1667122915862)(E:\Typora\image-20220927213159237.png)]
<body>
    <div id="root">
        <div class="basic" :class="mood" @click="changeMood">{{name}}</div>
        <div class="basic" :style="styleObj">{{name}}</div>
    </div>

    <script>
        new Vue({
            el: '#root',
            data: {
                name: '陈润喆',
                mood: 'normal',
                styleObj: {
                    fontSize: '40px'
                }
            },

            methods: {
                changeMood() {
                    const arr = ['happy', 'sad', 'normal']
                    const index = Math.floor(Math.random() * 3) //向下取整,取值0 1 2
                    this.mood = arr[index]
                }
            },
        })
    </script>
</body>

条件渲染

v-show v-if

v-if与template的关系

使用template模板时只可以使用v-if,否则会失效

  1. v-if
    1. 写法
      1. v-if=“表达式”
      2. v-else-if=“表达式”
      3. v-else=“表达式”
    2. 适用于:切换频率较低的场景
    3. 特点:不展示DOM元素直接被移除
    4. 注意:v-if可以和:v-else-if、v-else一起使用,但要求结构不能被打断
  2. v-show
    1. 写法:v-show=“表达式”
    2. 适用于:切换频率较高的场景
    3. 特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉
  3. 备注:使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到

列表渲染

v-for指令

  1. 用于展示列表数据
  2. 语法:v-for=“(item,index) in xxx” :key=“yyy”
  3. 可遍历:数组 对象 字符串 指定次数
<body>
    <div id="root">
        <h2>人员列表</h2>
        <ul>
            <li v-for="(p,index) in persons" :key="index">
                {{p.name}}-{{p.age}}-------{{index}}
            </li>
        </ul>
    </div>

    <script>
        new Vue({
            el: '#root',
            data: {
                persons: [
                    { id: '001', name: '张三', age: '18' },
                    { id: '002', name: '李四', age: '19' },
                    { id: '003', name: '王五', age: '20' }
                ]
            }
        })
    </script>
</body>

用id和用key中index做唯一标识的区别,如果数据是从上面插入时,用数据中的id做唯一标识,向下插入用index。

react、vue中的key有什么作用?(key的内部原理)

  1. 虚拟DOM中key的作用:
    1. key是虚拟DOM对象的标识,当状态中的数据发生变化时,Vue会根据【新数据】生成【新的虚拟标识】随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:
  2. 对比规则:
    1. 旧虚拟DOM中找到了新虚拟DOM相同的key:
      1. 若虚拟DOM中内容没变,直接使用之前的真实DOM
      2. 若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM
    2. 旧虚拟DOM中未找到与新虚拟DOM相同的key
      1. 创建新的真实DOM,随后渲染到页面
  3. 用index作为key可能会引发的问题
    1. 若对数据进行更新:逆序添加、逆序删除等破坏
      1. 会产生没必要的真实DOM更新==>界面效果没问题,但效率低
    2. 如果结构中还包含输入类的DOM:
      1. 会产生错误的DOM更新==>界面有问题
  4. 开发中如何选择key?
    1. 最好使用每条数据的唯一标识作为key,比如id、手机号、身份证等
    2. 如果不存在对数据逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key
    3. 简而言之: 用每条数据的唯一标识就完了

收集表单数据

在这里插入图片描述

<body>
    <div id="root">
        <form action="" @submit.prevent="sub">
            <label for="demo">账号</label>
            <input type="text" id="demo" v-model="userInfo.account">
            <br><br>
            <label for="demo1">密码</label>
            <input type="password" id="demo1" v-model.number="userInfo.password">
            <br><br>
            年龄: <input type="number" v-model.number="userInfo.age">
            <br><br>
            性别:
            男<input type="radio" value="male" name="sex" v-model="userInfo.sex"><input type="radio" value="female" name="sex" v-model="userInfo.sex">
            <br><br>
            爱好:
            学习<input type="checkbox" value="study" v-model="userInfo.hobby">
            打游戏<input type="checkbox" value="game" v-model="userInfo.hobby">
            打篮球<input type="checkbox" value="bas" v-model="userInfo.hobby">
            <br><br>
            所属校区
            <select v-model="userInfo.city">
                <option value="">请选择校区</option>
                <option value="beijing">北京</option>
                <option value="shanghai">上海</option>
                <option value="henan">河南</option>
            </select>
            <br><br>
            其他信息:
            <textarea v-model="userInfo.other"></textarea>
            <br><br>
            <input type="checkbox" v-model="userInfo.agree"> 阅读并接受<a href="#">用户协议</a>
            <br><br>
            <button>提交</button>
        </form>
    </div>

    <script>
        new Vue({
            el: '#root',
            data: {
                userInfo: {
                    account: '',
                    password: '',
                    age: '',
                    sex: '',
                    hobby: [],
                    city: 'beijing',
                    other: '',
                    agree: ''
                }
            },
            methods: {
                sub() {
                    console.log(JSON.stringify(this.userInfo));
                    alert('数据已提交')
                }
            },
        })
    </script>
</body>

过滤器(filters)

局部过滤器

写在Vue实例对象内部,只能被当前实例使用

写法{{值 | 过滤器方法}}

全局过滤器

定义在newVue实例之前 filter

内置指令

所有指令里的this都指向window

之前学过的:
v-bind
v-model
v-for
v-on
v-if
v-else
v-show

v-text 向一个数据中添加文本 并且覆盖原来的内容

v-html 支持html的编译 
	作用:向指定节点中渲染包含html结构的内容
	与插值语法的区别
		1.v-html会替换掉节点中所有的内容,{{xx}}不会
		2.v-html可以识别html结构
	严重注意:v-html有安全问题
    	1.在网站上动态渲染任意html是非常危险的,容易导致xss攻击
    	2.一定要在可信的内容上使用v-html,永远不要再用户提交的内容上
    	
v-cloak(没有值):
	1.本质是一个特殊的属性,Vue实例创建完毕后接管容器后,会删除v-cloak属性
	2.使用css display:none配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题
	
v-once 所在节点初次动态选然后,就视为静态内容了
		以后数据的改变也不会引起v-once所在结构的更新,可以用于优化性能
v-pre  跳过其所在节点的编译过程,可利用它跳过:没有使用指令语法、没有使用插值语法的特点,会加快编译

自定义指令

<body>
    <!--
    需求1:定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍
    -->
    <div id="root">
        <h2>当前的n值是: <span v-text="n"></span></h2>
        <h2>放大十倍后的n值是: <span v-big="n"></span></h2>
        <button @click="n++">点我n+1</button>
    </div>

    <script>
        new Vue({
            el: '#root',
            data: {
                n: 1
            },
            directives: {
                //两个参数,一个是真实的DOM节点,一个是被绑定的数据,我们需要它的value值即可
                big(element, binding) {
                    console.log(binding);
                    element.innerText = binding.value * 10
                }
            }
        })
    </script>
</body>
<body>
   <!--
   需求2:定义一个v-fbind指令,和v-bind类似,但可以他让其所绑定的input元素默认获取焦点信息 
   -->
   <div id="root">
       <h2>当前的n值是: <span v-text="n"></span></h2>
       <h2>放大十倍后的n值是: <span v-big="n"></span></h2>
       <button @click="n++">点我n+1</button>
       <hr>
       <input type="text" v-fbind:value="n">
   </div>
   <script>
       new Vue({
           el: '#root',
           data: {
               n: 1
           },
           directives: {
               //两个参数,一个是真实的DOM节点,一个是被绑定的数据,我们需要它的value值即可
               fbind: {
                   //指令与元素成功绑定时调用(一上来)
                   bind(element, binding) {
                       //当前节点中的值等于绑定来数据处理过的值
                       element.value = binding.value
                   },
                   //指令所在元素被插入页面时调用
                   inserted(element, binding) {
                       element.focus()
                   },
                   //指令所在模板被重新解析时
                   update(element, binding) {
                       element.value = binding.value
                   },
               }
           }
       })
   </script>
</body>

总结:

  1. 定义语法:

    1. 局部指令

      1. new Vue({
        	directives:{指令名:配置对象}
        })
        
        new Vue({
        	directives:{指令名:回调函数}
        })
        
    2. 全局指令

      1. Vue.directive(指令名,配置对象)
        
        Vue.directive(指令名,回调函数)
        
  2. 配置对象中常用的3个回调

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

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

生命周期:

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

常见的生命周期

在这里插入图片描述

一、创建

beforeCreate

此时无法通过vm访问到data中的数据、methods中的方法,此时浏览器已经初始化完成,但是生命周期、事件、数据代理还没开始

created

进一步初始化,已经开始数据监测、数据代理,此时已经可以通过vm访问到data中的数据、methods中配置的方法

二、挂载

beforeMount

挂载前,Vue开始解析模板,此时生成的是虚拟对象,页面上插值语法的地方还无法显示,这个时候即便对DOM进行操作,最好仍不奏效,最后生成的真实DOM会将其覆盖

mounted

将内存中的虚拟DOM转为真实DOM插入页面,此时vue完成编译,并将最后的结果呈现在页面上,这个时候虽然可以对DOM元素进行操作,但是不推荐(多此一举),在此过程结束后一般进行:开启定时器、发送网络请求、订阅消息、绑定自定义事件、等初始化操作

应用场景:发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】

三、更新

beforeUpdate

此时数据是新的,但页面是旧的,新数据还没有渲染到页面上

updated

新的数据已经渲染到页面上了

四、销毁

beforeDestroy&destroyed

在这两个阶段中,vm所有的data、methods、指令等都处于可用状态,并马上要执行销毁过程:一般在此阶段:关闭定时器、取消订阅消息、解绑自定义事件等收尾操作。总之,一般在这个阶段,就不要在进行数据的操作,都准备销毁了,更新,修改数据也没有用 Ps:需要下面的方法调用

应用场景:清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】

vm.$destroy()

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

在这里插入图片描述

关于销毁Vue实例:

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

五、激活状态(路由器中的生命周期钩子,下同)

必须配合keep-alive router标签才能被触发

activated:当前切换的组件,打开后为激活状态,执行此生命钩子里的代码

六、失活状态

deactivated:离开当前组件,则变为失活状态,执行此钩子里的代码

Vue组件化编程

为什么要组件化:传统的html开发模式,每一个项目引用多个css文件、js文件,容易导致各个文件的依赖关系混乱且不宜维护,代码复用率也不高

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

在这里插入图片描述

模块化:当应用中的js都以模块来编写的,那这个应用就是一个模块化应用

组件化:当应用中的功能都是多组件的方式来编写的,那这个应用就是一个组件化的应用

一、组件的两种书写模式

1.非单文件组件

一个文件中包含有n个组件在这里插入图片描述

2.单文件组件

一个文件中只包含一个组件

二、使用组件的三大步骤

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

  2. 注册组件

  3. 使用组件(写组件标签)

  4. 如何定义一个组件?

    1. 使用Vue。extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样,但 也有区别:具体如下
      1. el不要写,写什么? 最终所有的组件都要经过vm的管理,由vm中的el决定服务哪个容器
      2. data必须写成函数,为什么? —避免组件被复用时,数据存在引用关系
    2. 备注:使用template可以配置组件结构
  5. 如何注册组件?

    1. 局部注册:靠new Vue的时候传入components选项
    2. 全局注册:靠Vue.component(‘组件名’,组件)
  6. 编写组件标签

<body>
    <div id="root">
        <!-- 3.编写组件标签 -->
        <school></school>
        <hr>
        <student></student>
    </div>

    <script>
        //1.创建school组件
        const school = Vue.extend({
            template: `
            <div>
                <h2>学校名称:{{schoolName}}</h2>
                <h2>学校地址:{{address}}</h2>
                <button @click='look'>点我查看学校名称</button>   
            </div>
            `,
            data() {
                return {
                    schoolName: '河南科技学院',
                    address: '河南',
                }
            },
            methods: {
                look() {
                    alert(this.schoolName)
                }
            },
        })
        //创建学生组件
        const student = Vue.extend({
            template: `
            <div>
                <h2>学生姓名:{{studentName}}</h2>
                <h2>学生年龄:{{age}}</h2>   
            </div>
            `,
            data() {
                return {
                    studentName: '陈润喆',
                    age: 20
                }
            },
        })
        //创建vm
        new Vue({
            el: '#root',
            //2.注册组件
            components: {
                school: school,
                student: student
            }
        })
    </script>
</body>

三、组件的嵌套

<body>
    <div id="root">

    </div>

    <script>
        //定义student组件
        const student = Vue.extend({
            template: `
            <div> 
                <h2>学生姓名:{{studentName}}</h2>
                <h2>学生年龄:{{age}}</h2>   
            </div>
            `,
            data() {
                return {
                    studentName: '陈润喆',
                    age: 20
                }
            },
        })
        //定义school组件
        const school = Vue.extend({
            //将学生的标签名写在这个模板中
            template: `
            <div>
                <h2>学校名称:{{schoolName}}</h2>
                <h2>学校地址:{{address}}</h2> 
                <student></student>
            </div>
            `,
            data() {
                return {
                    schoolName: '河南科技学院',
                    address: '河南',
                }
            },
            //在学校组件中注册学生组件,将学生嵌套在老师中
            components: {
                student: student
            }
        })
        const app = Vue.extend({
            template: `<school></school>`,
            components: {
                school: school
            }
        })
        //创建vm
        new Vue({
            el: '#root',
            template: `<app></app>`,
            //2.注册组件
            components: {
                app: app
            }
        })
    </script>
</body>

四、VueComponent:

  1. school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的
  2. 我们只需要写或者,Vue解析时会帮我们创建school组件的实例对象,即Vue帮我们执行的:new VueComponent(options)
  3. 特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent!!!
  4. 关于this指向:
    1. 组件配置中:
      1. data函数 methods中的函数 watch中的函数 computed中的函数 他们的this均是VueComponent实例对象
    2. new Vue()配置中
      1. data函数 methods中的函数 watch中的函数 computed中的函数 他们的this均是Vue实例对象
  5. VueComponent 的实例对象,以后简称vc也可称之为组件实例对象.
    Vue的实例对象,以后简称vm vm管理着一堆vc

原型对象

prototype 显示原型属性
__proto__隐式原型属性  二者共同属于原型对象
程序员可以通过这两个属性操作原型对象

一个重要的内置关系:VueComponent.prototype.__proto__ === Vue.prototype
为什么要有这个关系:让组件实例对象(vc)可以访问到Vue原型上的属性、方法

在这里插入图片描述

五、单文件组件

js代码块暴露的三种方式

1.分别暴露  注意:引入school时要用 {}包住   import {school} from ‘文件’
export const school = Vue.extend({
  data() {
    return {
      schoolName: "河南科技学院",
      address: "河南",
    };
  },
});
2.统一暴露
const school = Vue.extend({
  data() {
    return {
      schoolName: "河南科技学院",
      address: "河南",
    };
  }
});
export {school}
3.默认暴露
const school = Vue.extend({
  data() {
    return {
      schoolName: "河南科技学院",
      address: "河南",
    };
  }
});
export default school

4.项目中常用写法
<script>
export default {
  name: "School",
  data() {
    return {
      schoolName: "河南科技学院",
      address: "河南",
    };
  },
  methods: {
    look() {
      alert(this.schoolName);
    },
  },
};
</script>

六、模块化开发流程

  1. 写单文件组件 .vue结尾的文件–>需要Vetur插件 以School.vue文件为例

    1. <template>
        <div class="demo">
          <h2>学校名称:{{ schoolName }}</h2>
          <h2>学校地址:{{ address }}</h2>
          <button @click="look">点我查看学校名称</button>
        </div>
      </template>
      
      <script>
      export default {
        name: "School",
        data() {
          return {
            schoolName: "河南科技学院",
            address: "河南",
          };
        },
        methods: {
          look() {
            alert(this.schoolName);
          },
        },
      };
      </script>
      
      <style>
      .demo {
        background-color: orange;
      }
      </style>
      
  2. 单文件组件写完之后,写一个最大的App组件,并将所有的组件引入

    1. <template>
        <div>
          <School />
        </div>
      </template>
      
      <script>
      //引入组件
      import School from "./School.vue";
      export default {
        components: { School },
        name: "App",
        comments: {
          School,
        },
      };
      </script>
      
      <style>
      </style>
      
  3. 写main.js文件,将App.vue引入,并准备执行

    1. import App from '.App.vue'
      
      new Vue({
          el:'#root',
          components:{
              App
          }
      })
      
  4. 写html页面,引入vue.js文件和App.vue进行页面显示-----需要脚手架才可以成功运行

    1. <!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>测试一下</title>
      </head>
      
      <body>
          <div id="root">
              <App></App>
          </div>
      
          <script src="../js/vue.js"></script>
          <script src="./main.js"></script>
      </body>
      
      </html>
      

七、组件自定义事件

  1. 一种组件间通信的方式,适用于: 子组件===>父组件

  2. 使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(在B实例对象中添加了一个自定义事件)在B组件中可以调用(事件的回调在A中,并且参数是从B传过来的)

  3. 绑定自定义事件:

    1. 第一种方式,在父组件中@自定义组件名=“”

    2. 第二种

      1. <Student ref="student" /> 
        mounted() {
            //将self事件绑定在Student实例对象上  this.getStudentName是从this.$emit("自定义事件名",发送给父类的数据)
            this.$refs.student.$on("self", this.getStudentName);
          },
        
    3. 若想让自定义事件只能触发一次,可以使用once修饰符或$once方法

  4. 触发自定义事件:this.$emit(“自定义事件名”,发送给父类的数据)

  5. 解绑自定义事件:this.$off(“自定义事件名”)

  6. 组件上也可以绑定原生DOM事件,需要使用native修饰符

  7. 通过this. r e f s . x x x . refs.xxx. refs.xxx.on(“自定义事件”,回调)绑定自定义事件时,回调要么配置在methods中,要么用箭头函数,否则this指向出问题

八、全局事件总线

  • 任意组件间通信
    在这里插入图片描述

外部x组件中间传递方的要求

  1. 所有组件都能调用他,从而进行参数的传递/接收vm

  2. 可以绑定事件 :

    $on  $off $emit 这个都在vue的原型对象vm上 所以vc可以调用的到
    

安装全局事件总线

new Vue({
    el: '#app',
    render: h => h(App),
    beforeCreate() {
        //安装全局事件总线
        Vue.prototype.$bus = this
    }
})

使用:
先接收数据,A组件想接收数据,则在A组件中 给$bus绑定自定义事件,事件的回调留在A组件自身

  data() {
    return {
      name: "crz",
      age: "20",
    };
  },
  methods: {
    sendStudentName() {
      // 调用x组件触发hello事件,将student中的数据传给school
      this.$bus.$emit("hello", this.age);
    },
//用完之后进行解绑,yang'cheng
    beforeDestroy() {
      this.$bus.$off("hello");
    },
  },

提供数据

  mounted() {  
    this.$bus.$on("hello", (data) => {   // data是从上面传过来的数据
      console.log("我是school组件,收到了数据", data);
    });
  },

使用Vue脚手架

Vue官方提供的标准化开发工具(开发平台)

一、安装步骤

  1. 全局安装 配置npm淘宝镜像命令: npm config set registry https://registry.npm.taobao.org
    1. 安装之前一定要先安装node.js
    2. 配置完淘宝镜像命令后进行全局安装: npm install -g @vue/cli
  2. 切换到要创建的项目目录,然后使用黑窗口命令创建项目
    1. vue create xxxx
  3. 启动项目
    1. npm run serve

Vue脚手架隐藏了所有的webpack配置,若想要查看具体的webpack配置,请执行:vue inspect > output.js

二、render函数

关于不同版本的Vue:

  1. vue.js与vue.runtime.xxx.js的区别:
    1. vue.js是完整版的Vue,包含:核心功能+模板解析器
    2. vue.runtime.xxx.js是运行版的vue,只包含:核心功能,没有模板解析器
  2. 因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,需要使用render函数接收到的createElement函数去指定具体的内容

三、ref属性

通过this.$refs.(ref)获取当前的DOM节点

<template>
  <div>
    <h1 v-text="msg" ref="title"></h1>
    <button @click="showdom" ref="btn">点我输出上面的元素</button>
    <School ref="sch" />
  </div>
</template>

<script>
import School from "./components/School.vue";
export default {
  name: "App",
  data() {
    return {
      msg: "欢迎到来",
    };
  },
  methods: {
    showdom() {
      console.log(this.$refs.title); //真实的don元素
      console.log(this.$refs.btn);//真实dom元素
      console.log(this.$refs.sch);//School组件的实例对象
    },
  },
  components: {
    School,
  },
};
</script>

四、props属性

  • 设置属性——提高模块的复用率,一些属性不在data中配置,而是写标签后在标签中设置外部属性
<template>
  <div class="school">
    <h2>座右铭:{{ msg }}</h2>
    <h2>学校名称:{{ name }}</h2>
    <h2>学校地址:{{ address }}</h2>
    <h2>学校年龄:{{ age1 }}</h2>
    <button @click="age1++">点击增加学校年龄</button>
  </div>
</template>

<script>
export default {
  name: "School",
  data() {
    return {
      msg: "有新校区的河科院",
      age1: this.age,
    };
  },
  props: {
    name: {
      type: String, //name类型是字符串
      required: true, //name是必要的
    },
    age: {
      type: Number,
      default: 50, //默认值,不填默认50
    },
    address: {
      type: String,
      default: "新乡",
    },
  },
};
</script>

<style>
.school {
  background-color: orange;
}
</style>
<template>
  <div>
    <h1 v-text="msg" ref="title"></h1>
    <button @click="showdom" ref="btn">点我输出上面的元素</button>
    <School name="河南科技学院" address="新乡市" ref="sch" /> //在这里配置属性
    <School name="新乡医学院" address="红旗区"  />
  </div>
</template>

<script>
import School from "./components/School.vue";
export default {
  name: "App",
  data() {
    return {
      msg: "欢迎到来",
    };
  },
  methods: {
    showdom() {
      console.log(this.$refs.title); //真实的don元素
      console.log(this.$refs.btn); //真实dom元素
      console.log(this.$refs.sch); //School组件的实例对象
    },
  },
  components: {
    School,
  },
};
</script>

五、mixin混入

将vue文件中重复的配置项单独写出来然后分别引入

//为了方便其他模块的引入,一定要暴露-->分别暴露
export const  mixin = {
    methods: {
        showName() {
            alert(this.name);
        },
    },
}
<template>
  <div class="school">
    <h2>座右铭:{{ msg }}</h2>
    <h2>学校名称:{{ name }}</h2>
    <h2>学校地址:{{ address }}</h2>
    <h2>学校年龄:{{ age1 }}</h2>
    <button @click="age1++">点击增加学校年龄</button>
    <button @click="showName">点击显示学校名</button>
  </div>
</template>

<script>
//分别暴露 引入时要用{}将文件名包住
import {mixin} from "./mixin.js";
export default {
  name: "School",
  data() {
    return {
      msg: "有新校区的河科院",
      age1: this.age,
    };
  },
  mixins: [mixin],//注意这里要用数组的形式
};
</script>

<style>
.school {
  background-color: orange;
}
</style>

六、plugins插件

相当于大号的mixin,可以将许多重复项放进来,给Vue原型添加方法、过滤器、mixin、自定义指令都可以写进来,然后在引入,使用Vue.use(plugins.js)即可用vm、vc对象进行调用

七、scoped属性

  • 让当前代码作用域限制在这一个文件夹中

引入多个vue文件模块化会出现css样式类名冲突的情况,为了避免这种情况可以给style标签添加scoped属性避免冲突

Todo-list案例

一、组件间通信

1.父亲给儿子

案例中例如App(父)共享数据给List(子)
将需要共享的数据(todos)写在App中,然后在List标签中添加:todos=“todos” 将数据与todos进行绑定,然后在List中添加属性(props)todos即完成了父类数据传给了儿子,进行遍历和操作等等操作…

//-----------------------------Vue--------------------
<template>
  <div id="root">
    <div class="todo-container">
      <div class="todo-wrap">
        <MyHeader :addTodo="addTodo" />
        <MyList
          :todos="todos"
          :checkTodo="checkTodo"
          :deleteTodo="deleteTodo"
        />
        <MyFooter
          :todos="todos"
          :checkAllTodo="checkAllTodo"
          :clearAllTodo="clearAllTodo"
        />
      </div>
    </div>
  </div>
</template>

<script>
import MyHeader from "./components/MyHeader.vue";
import MyFooter from "./components/MyFooter.vue";
import MyList from "./components/MyList.vue";

export default {
  name: "App",
  data() {
    return {
      //父类存数据
      todos: [
        { id: "001", title: "吃饭", done: true },
        { id: "002", title: "睡觉", done: false },
        { id: "003", title: "打游戏", done: true },
      ],
    };
  },
  methods: {
    addTodo(todoObj) {
      //操作上面的数据中的todos,添加进去后,在List中遍历渲染
      this.todos.unshift(todoObj);
      console.log(this);
    },
  },
  components: {
    MyHeader,
    MyFooter,
    MyList,
  },
};
</script>
-------------------------List----------------------
<template>
  <ul class="todo-main">
    <!-- todos遍历出来每一个对象todoObj赋值给todo,在MyItem中进行参数接收然后操作,遍历出来值 -->
    <MyItem
      v-for="todoObj in todos"
      :key="todoObj.id"
      :todo="todoObj"
      :checkTodo="checkTodo"
      :deleteTodo="deleteTodo"
    />
  </ul>
</template>

<script>
import MyItem from "./MyItem";
export default {
  name: "MyList",
  components: { MyItem },
  //子类获取
  props:['todos']
};
</script>

2.儿子给父亲

在父类中写好方法进行参数接收,并将方法进行事件绑定,然后在子类中引入属性,进行方法的调用,将想要传递的值作为参数放入方法中 .经过事件绑定,此时的方法已经是vc的方法,在子类中用this即可调用,相当于子类去调用父类方法然后将数据传入.

这种方法可以实现兄弟与兄弟直接数据的传递,但是需要一个中间量放在共同父类中,操作这个中间量进而实现共享,本案例中,父类存储的每一条代办事项对象就是中间量,修改完后再给List进行遍历渲染,从而实现Header和LIst直接的数据共享

------------------------子类Header------------------父类Vue同上---------------------
<template>
  <div class="todo-header">
    <input
      type="text"
      placeholder="请输入你的任务名称,按回车键确认"
      v-model="title"
      @keyup.enter="add"
    />
  </div>
</template>

<script>
import { nanoid } from "nanoid";
export default {
  name: "MyHeader",
  props: ["addTodo"],
  data() {
    return {
      title: "",
    };
  },
  methods: {
    add() {
        //校验数据是否为空
      if (!this.title.trim()) return alert("输入不能为空");
      //将用户的输入包装成一个todo对象
      const todoObj = { id: nanoid(), title: this.title, done: false };
      //走父类App的addTodo方法,将这个新todo对象塞到list表单中
      this.addTodo(todoObj); 
      this.title = "";
    },
  },
};
</script>

3.兄弟给兄弟()

二、localStorage + 深度监视

进行本地存储时,前面的是否完成项容易不被系统存储,勾选复选框时刷新页面仍然会丢失数据,如果使用深度监视即可避免刷新后数据丢失的情况

 watch: {
    todos: {
      deep: true,
      handler(value) {
        localStorage.setItem("todos", JSON.stringify(value));
      },
    },
  },

消息订阅与发布

原理:数据接收者(订阅方)数据发送者(发布方)订阅方写一个回调函数,发布方调用后将数据发送过去

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

借用第三发库实现pubsub-js

使用步骤:

  1. 安装pubsub :npm i pubsub-js

  2. 引入pubsub:import pubsub from‘pubsub-js’

  3. 接收数据:A组件想要接收数据,则在A组件中订阅消息,订阅的回调留在A组件自身

    methods(){
    	demo(data){....}
    }
    mounted(){
    	this.pid = pubsub.subscribe('xxx',this.demo)
    }
    //或者直接写在勾子里  要用箭头函数  第一个参数是订阅名字,第二个是传输的数据
      mounted() {
        pubsub.subscribe("hello", (msgName, data) => {
          console.log("有人发布了hello消息,hello消息的回调执行了", msgName, data);
        });
      },
    
  4. 提供数据:pubsub.publish(‘xxx’,数据)

     methods: {
        sendStudentName() {
          pubsub.publish("hello", 666);
        },
     }
    
  5. 最好在beforeDestroy钩子中,用pubsub.unsubscribe(pid)去取消订阅

$nextTick

里面写的函数能够在DOM节点更新完之后执行

过渡与动画

  1. 作用:再插入、更新或移除DOM元素时,再合适的时候给元素添加样式类名
  2. 图示:
    在这里插入图片描述
  3. 写法:
    1. 准备好样式
      1. 元素进入的样式
        1. v-enter:进入的起点
        2. v-enter-active:进入过程中
        3. v-enter-to:进入的终点
      2. 元素离开的样式
        1. v-leave:离开的起点
        2. v-leave-active:离开过程中
        3. v-leave-to:离开的终点
    2. 使用包裹要过渡的动画是,并配置name属性 appear属性:刷新页面时开始启动动画
    3. 若有多个元素需要过渡,则需要使用,且每个元素要有指定的key值

Vue中应用axios

使用脚手架配置代理服务器

  1. 方式一:在vue.config配置项中配置
module.exports = {
  devServer: {
    proxy: 'http://localhost:xxxx' 另一台服务器的端口号
  }
}
  1. 方式二:
module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: '<url>', //请求外部服务器的路径和上面一样的格式  http://localhost:xxxx
        pathRewrite:{'^/api':''}  //将配置路径清空
        ws: true,  //用于支持 web
        changeOrigin: true
      },
    }
  }
}

插槽

作用:让父组件可以向子组件位置插入HTML结构,也是一种组件间通信的方式,适用于父组件===>子组件

1.默认插槽

需求:三个一样的组件,但是其中两个需要放图片和视频,产生了需求不统一。在不破坏组件结构的情况下使用插槽来完善需求
在自定义标签中写标签

---------------------------------------------Vue组件------------------------- 
<div class="container">
    <Category title="美食">
      <img src="http://s3.ax1x.com/2021/01/16/srJlq0.jpg" alt="" />
    </Category>
    <Category title="游戏">
      <ul>
        <li v-for="(g, index) in games" :key="index">{{ g }}</li>
      </ul></Category
    >
    <Category title="电影">
      <video
        controls
        src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"
      ></video>
    </Category>
    
---------------------------------------Category组件--------------------------------------
<template>
  <div class="category">
    <h3>{{ title }}分类</h3>
    <!-- 定义了一个插槽,自定义标签名字里的标签内容插入到这里 -->
    <slot></slot>
  </div>
</template>
<script>
export default {
  name: "Category",
  props: [ "title"],
};
</script>

2.具名插槽 具有名字的插槽

要添加多个插槽的情况下,给slot添加name属性,然后在标签引入的时候将对应的名字添加上,让对应内容添加到对应的插槽中

3.作用域插槽

  1. 理解:数据在组件的自身,但是据根据生成的结构需要组件的使用者来决定

  2. 编码:

    父组件中:
    <Category>
    	<template scope="xxx">
    		<ul>
    			<li v-for="g in xxx.games">{{g}}</li>
    		</ul>
    	</template>
    </Category>
    
    子组件:
    <template>
    	<div>
        	<slot :games="games"></slot>
        </div>
    </template>
    <script>
    	export default {
            nameL'Category',
            props:['title'],
            data(){
            	return{
                    games:['英雄联盟','红色警戒','泡泡堂']
                }       
            }
        }
    </script>
    

Vuex插件

  1. 概念:专门在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中的多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信
  2. 什么时候使用:
    1. 多个组件依赖于同一状态
    2. 来自不同组件的行为需要变更同一状态

原理图:
在这里插入图片描述

Vuex的使用

安装:npm i @vuex3
创建一个store文件,内置index.js文件,引入vuex.防止vuex无法被调用,在index.js中将vuex引入

index.js
//创建vuex中最为核心的store
//引入Vue
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
Vue.use(Vuex)
//actions——用于相应组件中的动作
const actions = {}
//mutations——用于操作数据(state)
const mutations = {}
//state——用于存储数据
const state = {}
//创建并暴露store
export default new Vuex.Store({
    actions,
    mutations,
    state
})

main.js引入

//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
//引入store
import store from './store/index'
//关闭Vue的生产提示
Vue.config.productionTip = false
//创建vm
new Vue({
	el: '#app',
	render: h => h(App),
	store,
	beforeCreate() {
		Vue.prototype.$bus = this
	},
})

四个map方法

帮助程序员生成State、Getters、Actions、Mutation方法

路由

1.相关理解:

1.vue-router的理解

Vue的一个插件库,专门用来实现SPA应用 npm i vue-router 进行库的安装

2.对SPA应用的理解

  1. 单页Web应用
  2. 整个应用只有一个完整的页面(index.html)
  3. 点击页面中的导航链接不会刷新页面,只会做页面的局部更新 切换时进行组件的切换来显示
  4. 数据需要通过ajax请求获取

2.路由的理解

  1. 一个路由就是一组映射(key-value)
  2. key为路径,value可能是function或component
路由的分类
  1. 后端路由
    1. 理解:value是function,用于处理客户端提交的请求
    2. 工作过程:服务器接收到一个请求时,根据请求路径找到匹配的函数来处理请求,返回相应数据
  2. 前端路由
    1. 理解:value是component,用于展示页面的内容
    2. 工作流程:当浏览器的路径改变时,对应的组件就会显示

3.路由的使用

  1. 安装vue-router,命令:npm i vue-router

  2. 应用插件:

    main.js
    //引入Vue
    import Vue from 'vue'
    //引入App
    import App from './App.vue'
    //引入VueRouter
    import VueRouter from 'vue-router'
    //引入路由器
    import router from './router'
    
    //关闭Vue的生产提示
    Vue.config.productionTip = false
    //应用插件
    Vue.use(VueRouter)
    
    //创建vm
    new Vue({
    	el: '#app',
    	render: h => h(App),
    	router: router
    })
    
  3. 编写router配置项

    //用于创建整个应用的路由器
    import VueRouter from 'vue-router'
    //引入组件
    import About from '../components/About'
    import Home from '../components/Home'
    
    //创建并暴露一个路由器
    export default new VueRouter({
        routes: [
            {
                //如果路径是about,则显示About这个组件
                path: '/about',
                component: About
            },
            {
                path: '/home',
                component: Home
            }
        ]
    })
    
  4. 实现切换 借助路由库提供的router-link标签,内置active-calss标签控制选择时切换的样式

    <router-link class="list-group-item" active-class="active" to="/about">About</router-link>
    <router-link class="list-group-item" active-class="active"
    to="/about">Home</router-link>
    
  5. 指定展示的位置,类似插槽<router-view></router-view>

注意点:

  1. 路由组件通常存放在pages文件夹,一般组件通常存放在components文件夹

  2. 通过切换"隐藏"了的路由组件,默认是被销毁的,需要的时候再去重新挂载

  3. 每个组件都有自己的$route属性,里面存储着自己的路由信息

  4. 整个应用只有一个router,可以通过组件的$router属性获取到

4.多级路由

  1. 配置路由规则,使用children配置项

     routes: [
            {
                //如果路径是about,则显示About这个组件
                path: '/about',
                component: About
            },
            {
                path: '/home',
                component: Home,
                children: [  //通过children来配置子级路由
                    {
                        // 这里底层代码会给路径前添加/不需要手动添加
                        path: 'news',
                        component: News
                    },
                    {
                        path: 'message',
                        component: Message
                    }
                ]
            }
        ]
    
  2. 跳转
    <router-link class="" active-class="" to="" >Message</router-link>

5.路由的query参数

  1. 传递参数

    <!-- 跳转路由并携带query参数,to的字符串写法 -->
    <li v-for="m in messageList" :key="m.id">
    <router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`">{{m.title}}</router-link>
    
    <!-- 跳转路由并携带query参数,to的对象写法 -->
            <router-link
              :to="{
                path: '/home/message/detail',
                query: {
                  id: m.id,
                  title: m.title,
                },
              }"
            >
              {{ m.title }}
            </router-link>
    </li>
    
  2. 接收参数

    <template>
    	<ul>
    		<li>消息编号:{{$route.query.id}}</li>
    		<li>消息标题:{{$route.query.title}}</li>
    	</ul>
    </template>
    
    <script>
    	export default {
    		name:'Detail',
    		mounted() {
    			console.log(this.$route)
    		},
    	}
    </script>
    

6.路由器自带的方法

在这里插入图片描述

back:浏览器上面的返回上一级
forward:下一级
push:浏览时向栈中加入,可以通过上一级返回
replace:直接将次栈覆盖掉,无法再通过上一级返回
go:里面放数字参数,正数前进x页,负数后退

编程式路由导航

一种高效的路由切换方式,不用router-link标签标注,而是在组件中通过调用router的方法进行路由切换
主要方法如上所示

具体编码API

<template>
  <div class="home">
    <el-input
      class="put"
      v-model="username"
      placeholder="请输入用户名"
    ></el-input>
    <el-input
      class="put"
      placeholder="请输入密码"
      v-model="password"
      show-password
    ></el-input>

    <el-button type="primary" class="right" @click="clearAll()">重置</el-button>

    <el-button type="primary" class="right" @click="isLogin()">确定</el-button>
  </div>
</template>

<script>
export default {
  name: "Login",
  data() {
    return {
      username: "",
      password: "",
    };
  },
  methods: {
    clearAll() {
      this.username = "";
      this.password = "";
    },
    isLogin() {
      let userObjs = JSON.parse(localStorage.getItem("userObjs"));
      console.log(userObjs);
      //判断是否登录成功
      let isLogin = true;
      for (let i = 0; i < userObjs.length; i++) {
        if (
          this.username === userObjs[i].username &&
          this.password === userObjs[i].password
        ) {
          isLogin = true;
          break;
        } else {
          isLogin = false;
        }
      }
      console.log(this.username, this.password);
      console.log(isLogin);
      if (isLogin === true) {
        alert("登录成功");
        this.$router.push({
          path: "/todolist",
          query: {
            username: this.username,
          },
        });
      } else {
        alert("登录失败,用户名或密码不正确");
        this.username = "";
        this.password = "";
      }

      /* if (this.password !== password) {
        alert("用户名密码不正确");
      } */
    },
  },
};
</script>

<style scoped>
.put {
  margin-bottom: 15px;
}
.right {
  float: right;
  margin-left: 15px;
}
</style>

7.缓存路由组件

  1. 作用:让不展示的路由组件保持挂载,不被销毁

  2. 具体编码:

    <keep-alive include = "News">  //include后面引号内容是组件名字!!!
    	<router-view></router-view>
    </kepp-alive>
    
    缓存一个:直接写字符串,缓存多个,写数组形式
    <keep-alive include = "['News','Message']">
    

8.路由守卫

控制路由的权限,场景:用户信息显示,是不是该用户登陆。在路由器中去查找localstory中用户的信息是否

  1. 前置路由守卫

在组件展示之前通过守卫控制权限

router.beforeEach((to,from,next) => {
    console.log('@');
})
to:组件来自哪里
from:要去哪里
next():控制是否放行的权限,结合if判断语句

//给组件配置是否需要经过路由,可以通过meta{}里面配置自己想要的属性,值为true则会通过守卫权限判断
  1. 后置路由守卫

    afterEach((to,from)=>{
    	//next()执行之前会走到后置路由守卫中
    })
    
  2. 独享守卫:
    写在想要拦截的组件里API:befroeEnter()参数和前置路由一样,里面过滤代码一样,并且可以公用后置守卫

  3. 组件内路由守卫(API写在vue组件内不是index.js文件中)
    beforeRouteEnter通过路由规则时被调用
    beforeRouteLeave通过路由规则离开时被调用

执行顺序–>

在这里插入图片描述

全局守卫>独享守卫>组件内路由守卫

全局前置和后置在启用组件时

考核复盘

Vuex的几个主要模块

状态自管理应用

单页面的状态管理:

  1. state:数据源(data)
  2. view:以声明的方式映射到视图(html展示的东西)
  3. actions:响应在view上的用户输入导致的状态变化(methods,操纵数据的变化)

多页面状态管理(vuex)

  1. state:数据源
  2. mutation:状态更新 需要commit提交后更新
  3. action:代替mutation进行异步操作

生命周期

4对:

  • 创建
  • 挂载
  • 更新
  • 销毁

计算属性和方法的性能问题

计算属性自带缓存,只有相关依赖发生改变时才会重新取值。methods方法会在每次渲染页面的时候呗调用执行

cookie

不超过4kb的小型文本文件,可以保存用户在浏览器中的数据——用户登录数据

v-if和v-for的优先级

vue2:v-for优先级大于v-if
vue3:v-if优先级大于v-for

两个指令避免出现在一起

子组件给父组件传值

  1. 全局事件总线
    1. 通过给vm实例添加一个新的属性$bus,将想要传的数据挂在$bus上,利用$bus.on绑定,然后用$emit使用绑定数据,达到父组件共享子组件数据
  2. slot插槽
    1. 子组件通过slot name=''定义插槽,内放入子组件数据,通过父组件slot标签将数据拿过来使用
  3. $emit方法
    1. 父类自定义方法名,在子组件用$emit将想要传的值给父类定义的那个方法名,然后在父类接收并且使用
  4. $ref自定义事件名
    1. 通过this.$refs.hello.数据获取当前的DOM节点,后面加上这个获取当前节点里的数据即可提取到里面的数据

全局API

Vue.extend()创建一个子类

Vue.use() 使用插件

Vue.filter() 注册或获取全局过滤器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值