Vue2-3.0

一、如何引用(使用)vue

<!-- 生产模式 优点:拥有完整的错误提示 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<!-- 上线模式 优点:体积小,没有开发提示 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>

二、去除控制台生产开发提示

Vue.config.productionTip = false;

三、去除控制台favicon.ico 404问题

  1. 由于vue底层会自动到根目录寻找favicon.ico图标,由于项目目录的子级没有找到该图标,所有导致404问题,
  2. 解决方案,下载一个图标,将图标名称改为favicon,并将其放入根目录下面

四、了解基本结构

<html>
    <head>
        <title>网页标题</title>
    </head>
    
    <body>
        <div id="root">
            
        </div>
        
        <script type = "type/javascript">
        	Vue.config.productionTip = false;
        	
        	const vm = new Vue({
        		el:"#root",
        		data:{
        		
        		}
        	});
        </script>
    </body>
</html>
  1. #root:代表 将那个容器委托给vue管理
  2. el:vue要接管的容器,其中不仅仅可以为id选择器,css选择器的其他选择器都可以
  3. data:在vue中自定义的数据,并且可以在vue容器中访问到
  4. vue容器和vue实例是一一对应的
  5. {{xxx}}中的xxx要写js表达式,且xxx可以自动读取data中的所有子级属性,其他通过子级.孙级
  6. 一旦data中的数据发生改变,那么页面中用到该数据的地方也会自动更新

注意区分:js表达式 和 js代码(js语句)

表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方

  1. a
  2. a+b
  3. demo(1) 必须要return
  4. x === y ? ‘a’ : ‘b’

js代码(js语句)

  1. if(){}
  2. for(){}

五、插值语法和指令语法

1、插值语法

功能:用于解析标签体内容

写法:{{xxx}},xxx是js表达式,其可以直接读取到data中的所有子级属性,其他通过子级.孙级

2、指令语法

功能:用于解析标签内容

举例:v-bind:href = “xxx” 简写方式 :href = “xxx” xxx同样要写js表达式

备注:Vue中可以有很多的指令,且形式都是:v-xxx

六、数据绑定

Vue中有两种绑定的方式:

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

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

  1. 双向绑定一般都应用于表单元素上(如:input、select、radio、checkbox等)
  2. v-mode:value 可以简写为v-model,因为v-model默认收集的就是value的值

七、el和data的两种绑定方式

  1. el的两种绑定方式

    el:“[css选择器]”

    vm.$mount(“[css选择器]”);

  2. data的两种绑定方式

    data:{

    }

    //使用组件是不推荐使用es6函数定义方式

    data(){

    ​ return{

    ​ xxx:“”

    ​ }

    }

    如果函数为以上那个形式那么this代表的是vue实例对象

    如果函数为es6函数定义方式,那么this代表的是window

八、MVVM模式

View:视图 用于将数据显示给用户

Model:数据

Vm(ViewMode):用于监听页面数据变化,如页面变化那么vm所管理的数据也会变化(双向绑定)

​ 用于将数据绑定至页面,一旦vm管的数据发生变化,那么页面的数据也随之变化

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

<script type="text/javascript">
	Object,definProperty(person,'age',{
        //value:18  //设置代理属性的值
        //enumerable:true //控制属性是否可以被枚举(遍历获取该属性),默认值为false
        //writable:true //控制属性是否可以被修改,默认为false
        //configurable:true //控制属性是否可以被删除,默认值为false
        //删除对象属性 delete object.xxx
    });
</script>
<script type = "text/javascript">
	let obj = {x:100}
    let obj2 = {y:200}
    
    Ojbect.defineProperty(obj2,'x',{
        get(){
            return obj.x;
        },
        set(value){
            obj.x = value;
        }
    });
</script>
<!-- 
	通过defineProperty方法实现简单的数据代理,让obj2代理obj.
	obj2除了本身的y属性,还有代理的属性x
	通过getter、setter函数,实现obj2和obj的x值同步(相等)
-->

个人理解vue代理:

​ vm.xxx 代理了 vm._data.xxx

​ vm._data 劫持了 代码中自定义的data

​ 最终影响页面的变化

十、事件处理

事件的基本使用

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

十一、事件修饰符

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

阻止冒泡的同时也阻止默认事件

@click.prevent.stop

十二、键盘事件

Vue中常用的按键别名

  1. 回车 => enter
  2. 删除 => delete (捕获“删除”和“退格”键)
  3. 退出 => esc
  4. 空格 => space
  5. 换行 => tab
  6. 上 => up
  7. 下 => down
  8. 左 => left
  9. 右 => right

Vue未提供别名的按键,可以使用按键原始的key值去绑定,但注意要转换为kebab-casecaps-lock(短横线命名)

系统修饰键(用法特殊):ctrl、alt、shift、win、table

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

也可以使用keyCode去指定具体的按键(不推荐)

Vue.config.keyCodes.自定义键名=键码,可以去定制按键别名

组合键使用:@keyup.ctrl.y

十三、计算属性

  1. 定义:要用属性的值不存在,要通过已有的属性计算得来

  2. 原理:底层借助了Object.defineproperty()方法提供的getter和setter。

  3. getter函数什么时候执行?

  4. 出自读取时会执行一次

  5. 当依赖的数据发生变化时会被再次调用

  6. 优势:与methods实现相比,计算属性内部有缓存机制(复用),效率更高,调试方便

  7. 备注:

  8. 计算属性最终会出现在vm上,直接读取使用即可

  9. 如果计算属性要被修改,那么必须要写set行数去响应修改,且set中要引起计算时依赖的数据发生改变改变

    修改计算属性 => setter改变依赖的属性 => 依赖属性发生改变 => 页面发生改变 == 调用getter

十四、属性侦听

一、普通侦听
  1. 当被侦听的属性变化时,回调函数自动调用,进行相关操作
  2. 侦听的属性必须存在,才能进行监视,可以监视data中的属性、computed中的计算属性。如果属性不存在也不会报错
  3. 侦听的两种写法
  4. new vue时传入watch配置
  5. 通过vm.$watch监视
<script>
    //new vue时传入watch配置
	const vm = new Vue({
		el: '#root',
         data: {
            firstName:'张',
            lastName: '三'
         },
         computed:{
            fullName(){
                return xxx;
            }
         },
         watch:{
             lastName:{
                 immediate:true,//初始化时让handler调用一下
                 handler(newValue,oldValue){
                     //newValue 代表修改之后的值
                     //oldValue 代表修改之前的值
                 }
             }
         }
	});
    
    //通过vm.$watch监视
    vm.$watch('lastName',{
        immediate:true,//初始化时让handler调用一下
        handler(newValue,oldValue){
             //newValue 代表修改之后的值
             //oldValue 代表修改之前的值
        }
    });
</script>
二、深度侦听
  1. Vue中的watch默认不支持监测对象内部值的改变(一层)
  2. 配置deep:true可以监测对象内部值改变(多层)

​ 备注:

  1. Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以
  2. 使用watch时更具数据的具体结构,决定是否采用深度监视
<script>
	const vm = new Vue({
		el: '#root',
         data: {
            
            person:{name:"张三",age:"男"}
         },
         watch:{
             //监听对象中具体的某个键
             'person.name':{
                 handler(newValue,oldValue){
                     console.log("name改变了");
                 }
             },
             //监听对象中的所有键
             person:{
                 deep:true,
                 handler:(newValue,oldValue){
                 	console.log("person改变了");
             	}
             }
         }
	});
</script>

十五、computed和watch之间的区别

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

两个重要的原则

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

十六、动态绑定样式

一、绑定样式
  1. 写法:class=“xxx” xxx可以是字符串、数组、对象
  2. 字符串写法适用于:类名不确定,要动态获取
  3. 对象写法适用于:要绑定多个央视个数不确定,名字也不确定
  4. 数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用
  5. style样式
  6. :style=“{fontSize : xxx}” 其中xxx是动态值
  7. :style = “[a,b]” 其中a、b是样式对象
二、绑定案例
<html>
    <header>
        <title></title>

        <style>
            .line{
                border:1px solid red;
            }

            .radius{
                border-radius: 20px;
            }

            .bg-color{
                background-color: gold;
            }

            .font{
                font-size: 30px;
                color: gray;
            }
        </style>
    </header>
    <body>
        <div id="root">
            <h1>class绑定</h1>
            <div :class = "strs">字符串绑定样式</div>
            <button @click="changeColor">点我改变样式</button>
            <br><br>
            <div :class = "cls">对象绑定</div>
            <br><br>
            <div :class = "clsArr">数组绑定</div>
            <br><br>
            <h1>style行内样式绑定</h1>
            <div :style="obj">对象绑定</div>
            <br><br>
            <div :style="arr">数组方式绑定</div>
        </div>

        <script type="text/javascript" src="vue.js"></script>
        <script type="text/javascript">
            const vm = new Vue({
                el:"#root",
                data:{
                    strs:"font",
                    cls:{
                        font:true,
                        radius:true,
                        'bg-color':true
                    },
                    clsArr:["radius","bg-color"],
                    obj:{
                        fontSize:"18px",
                        color:"red",
                        backgroundColor:"gray"
                    },
                    arr:[
                        {
                            fontSize:"18px"
                        }
                        ,{
                            color:"gold",
                            backgroundColor:"skyblue",
                            borderRadius:"30px"
                        }
                    ]
                },
                methods:{
                    changeColor(){
                        this.strs = 'bg-Color';
                    }
                }
            });
        </script>
    </body>
</html>
三、注意事项
  1. 动态绑定class,需要事先准备好对应的Css样式,动态绑定style不需要事先准备样式
  2. 如果css原名中带有横线,需要使用小驼峰命名。如( background-color ==> backgroundColor )
  3. 通过数组方式动态绑定class,数组中放的是实现定义好的样式名称字符串,也可以放对象
  4. 通过数组方式动态绑定style,数组中放的样式是对象,对象中的键必须是原生css中存在的

十七、条件渲染(v-show和v-if)

  1. v-if

写法

  1. v-if = “表达式”

v-else-if = “表达式”

v-else

什么时候用?切换频率较低的场景

特点:不满足条件的dom元素直接移除

注意:v-if可以和v-else-if、v-else一起使用,当要求结构不能打断(if结构中不能添加其他dom)

  1. v-show

写法:v-show=“表达式”

什么时候用:切换频率较高的场景

特点:不展示的dom未被移除,仅仅是使用display样式显示、隐藏

  1. 备注:使用v-if的时,元素可都能无法获取到,而使用v-show一定可以获取到(原因:一个是移除dom,一个是显示隐藏dom)

十八、v-if和template的配合使用

<html>
    <header>
        <titile></titile>
    </header>

    <body>
        <div id="root">

            <h1>使用Template实现</h1>
            <button @click="isShowTemplate=!isShowTemplate">点我隐藏全部</button>
            <template v-if = "isShowTemplate">
                <div>打篮球</div>
                <div>打羽毛球</div>
                <div>踢足球</div>
            </template>

            <br><br>

            <h1>通过改变原有结构实现实现</h1>
            <button @click="isShowStruck=!isShowStruck">点我隐藏全部</button>
            <div v-if = "isShowStruck">
                <div>打篮球</div>
                <div>打羽毛球</div>
                <div>踢足球</div>
            </div>
        </div>

        <script type = "text/javascript" src="vue.js"></script>
        <script type = "text/javascript">
            Vue.config.productionTip = false;
            const vm = new Vue({
                el:"#root",
                data:{
                    isShowTemplate:true,
                    isShowStruck:true
                }
            });
        </script>
    </body>
</html>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4zg9xCqs-1651027848981)(https://note-photo-1257322974.cos.ap-shanghai.myqcloud.com/Vue/v-if%E5%92%8C%E6%A8%A1%E6%9D%BF%E9%85%8D%E5%90%88%E4%BD%BF%E7%94%A8.jpg?q-sign-algorithm=sha1&q-ak=AKIDGJzRej2oshI1Uha9QSyHgqkOs7Ay7gKn&q-sign-time=1638148900;172800001638148900&q-key-time=1638148900;172800001638148900&q-header-list=&q-url-param-list=&q-signature=055b852ac5de7acf1c7a57054f54ecd7506c3b9f)]

十九、列表渲染

  1. v-for指令

    1. 用于展示列表数据
    2. 语法:v-for = “(item,index) in xxx” :key=“yyy”(一般为xxx.id)
    3. 可遍历:数组、对象、(字符串、指定次数)[用的很少]

二十、深度了解Key

  1. key有什么作用(key的内部原理)
  1. 虚拟Dom中key的作用
  2. key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的xuniDOM】
  3. 随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较
  4. 对比规则
  5. 旧虚拟DOM中找到了与新虚拟DOM相同的key:
    1. 若虚拟DOM中内容没变,直接使用之前的真实DOM
    2. 若虚拟DOM中内容变了,则生成新的真实DOM,随后替换页面中之前的真实DOM
  6. 旧虚拟DOM中未找到与新虚拟DOM相同的key
    1. 创建新的真实DOM,随后渲染到页面
  7. 用Index作为key可能会引发的问题
  8. 若数据进行:逆序添加、逆序删除等破环顺序操作
    1. 会产生没有必要的真实DOM更新 ==> 界面效果没问题,但效率低(真实DOM没有重用)
  9. 如果结构中还包含输入类的DOM(input、textare等)
    1. 会产生错误DOM更新 ==> 界面有问题
  10. 开发中如何选择key?
  11. 最好使用每条数据的标识作为key,如id、手机号码、身份证等唯一标识
  12. 如果不存在数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index座位key是没有问题的
  13. 逆序:不在对象数组后面追加,而是在开始部分或中间部分追加数据,导致数据顺序发生变化

二十一、Vue监视数据原理

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

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

    通过setter实现监视,且要在new Vue时就传入要监测的数据

    ​ (1)、对象中后面追加的属性,vue默认不做响应式处理

    ​ (2)、如需给后添加的属性做响应式,使用以下api

    Vue.set(target,propertyName/index,value);
    vm.$set(target,propertyName/index,value);
    
  3. 如何监测数组中的数据

    通过包裹(封装)数组更新元素的方法实现,本质上就是做了两件事

    ​ (1)、调用原生对应的方法对数组进行更新

    ​ (2)、重新解析模板,进而更新页面数据

  4. 在Vue修改数组中的某个元素一定要用如下方法

    1. 使用这些API:push()、pop()、 shift()、 unshift()、 splice()、 sort()、 reverse()
    2. Vue.set() 和 vm.$set()

特别注意:不能给vm 或 vm的根数据(vm、_data)对象添加属性

二十二、收集表单数据

若:则v-model收集的是value值,用户输入的就是value值

若:则v-model收集的是value值,且要给标签配置value

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

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

lazy:控件失去焦点之后开始收集数据

number:输入字符串转为有效数组

trim:去除首尾的空字符串

二十三、过滤器

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

语法:

  1. 注册过滤器:Vue.filter(name,callback); 或 new Vue(filters:{})
  2. 使用过滤器:{{xxx | 过滤器名称}} 或 v-bind:属性=“xxx | 过滤器名称”

备注:

  1. 过滤器也可以接受额外参数,多个过滤器也可以串联
  2. 并没有改变原有的数据,是产生新的对应的数据

二十四、内置指令

1、v-html指令

  1. 作用:向指定节点中渲染包含html结构的内容
  2. 与插值语法的区别
  3. v-html 会替换掉节点中的所有内容,{xx}则不会
  4. v-html可以识别html
  5. 严重注意:v-html有安全性问题
  6. 在网站上动态渲染任意html是非常危险的,容易导致xss攻击
  7. 一定要在可信的内容上使用v-html,永不要用在用户提交的内容上

2、v-cloak(没有值)

  1. 本质就是一个特殊属性,Vue实例创建完毕并接管容器后,会删除v-cloak属性
  2. 使用css配合v-cloak可以解决网速慢时页面展示{{xxx}}的问题

3、v-once

  1. v-once所在节点在初次动态选然后,就是为静态内容了
  2. 以后数据的改变就不会引起v-once所在结构的更新,可以用于优化性能

4、v-pre指令

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

5、自定义指令

  1. 定义语法
  1. 局部指令
 ```javascript
 new Vue({
     directives:{指令名:配置对象}
 })
 ```
 new Vue({
     directives(){
     }
     })
  1. 配置对象中常用的3个回调
  1. bind:指令与元素成功绑定时调用
  2. inserted:指令所在元素被插入页面时调用
  3. update:指令所在模板结构被重新解析时调用
  1. 备注
  1. 指令名定义时不要加v-,但调用时要加v-
  2. 指令名如果是多个单词,要使用xxx-xxx(横杠隔开)命名方式,不要用xxXxx(驼峰)命名

二十五、什么是Vue的生命周期

  1. 又名:生命周期回调函数、生命周期函数、生命周期钩子
  2. 是什么:Vue在关键时刻帮我们调用一些特殊名称的函数
  3. 生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的
  4. 生命周期函数中的this指向的是vm 或 组件实例对象
  1. 常用的生命周期狗子
  2. mounted:发送ajax请求,启动定时器,绑定自定义事件,订阅消息等(初始化操作)
  3. beforeDestroy:清除定时器、解绑自定义事件,取消订阅消息等(收尾工作)
  4. 关于销毁Vue实例
  5. 销毁后借助Vue开发者工具看不到任何消息
  6. 销毁后自定义事件会失效,但原生dom事件依然有效
  7. 一般不会再beforeDestroy操作数据,因为即便操作事件,也不会触发更新流程了

二十六、初认组件

  1. Vue使用组件的三大步骤
    1. 定义组件
    2. 注册主键
    3. 使用组件
  2. 如何定义一个组件
    1. 使用Vue.extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样但也有点区别
  3. 区别如下
    1. el不要写,为什么?----- 最终所有的组件都要经过一个vm的管理,由vm中的el决定服务那个容器
    2. data必须写成函数,为什么?----- 避免组件被复用时,数据存在应用关系(数据相互影响)
  4. 备注:使用template可以配置组件结构
  5. 如何注册组件
    1. 局部注册:靠new Vue的时候传入components选项
    2. 全局注册:靠Vue.component(‘组件名’,组件)
  6. 如何使用组件
    1. <组件名></组件名>

二十七、组件的几个注意点

  1. 关于组件名

  2. 一个单词组成:

    1. 首字母小写:school
    2. 首字母大写:School
  3. 多个单词组成

    1. kebab-case命名:my-school
    2. CamelCase命名:MySchool(需要脚手架支持)
  4. 备注

    1. 组件名尽可能回避HTML中已有的元素名称,例如:H2、h2都不行
    2. 可以使用name配置之项指定组件在开发者工具中呈现的名字
  5. 关于组件标签

  6. <!-- 成双成对 -->
    <school></school> 
    
  7. <!-- 自闭和 不使用脚手架会导致后续组件不能渲染-->
    <school/> 
    
  8. 创建组建的简写方式

const school = Vue.extend(options); //const school = Vue.extend({})

const school = options; //const school = {}

二十八、关于VueComponent

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

二十九、关于不同版本的vue

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

三十、ref属性

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

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

  3. 使用方式

  4. 设置标识:

    <h1 ref = "xxx"></h1>
    <School ref="xxx"></School>
    
  5. 获取标识

    this.$refs.xxx
    

三十一、配置项props

功能:让组件接受外部传过来的数据

  1. 传递数据
<Demo name="xxx"></Demo>
  1. 接收数据

  2. 简单接收

    props:['name']
    
  3. 限制类型

    props:{
        name:String
    }
    
  4. 限制类型,限制必要性,指定默认值

    props:{
        name:{
            type:String,   //类型限制
            required:true, //必要性,不能不传递
            default:'老王' //默认值
        }
    }
    

备注:

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

export default{
	name:"xxxComp",
	data:{
		tempName:this.name
	},
	props:['name'],
	methods:{
		updateName(){
			this.tempName = this.name;
		}
	}
}

三十二、mixin(混合\混入)

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

使用方式如下

  1. 第一步定义混合
{
    data(){},
    methods:{},
    .......
}
  1. 第二步使用混合
//引入
import {'x1','x2'} from '../mixin'

//全局混合
Vue.mixin(x1)
Vue.mixin(xx)
//局部混合
new Vue({
   mixins:['x1','x2'] 
});

三十三、使用插件

功能:用于增强Vue

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

定义插件

对象.install = function(){
    //添加全局过滤器
    Vue.filter()
    
    //添加全局指令
    Vue.directive()
    
    //配置全局混入
    Vue.mixin()
 
    //......
}

也可以是

export default {
    install(){
         //添加全局过滤器
    	Vue.filter()
    
   	 	//添加全局指令
   		 Vue.directive()
    
    	//配置全局混入
    	Vue.mixin()
 
   		//......
    }
}

使用插件

//必须在vm创建前使用插件
//一、引用插件
import plugins from './plugins'
//二、使用
Vue.use(plugins);

new vm({
    
});

三十四、TodoList案例总结

  1. 组件化编码流程
  2. 拆分静态组件:组件要按照功能点拆分,命名不要与html元素冲突
  3. 实现动态组件:考虑好数据的存放位置,数据是一个组件在用,还是一些组件再用
    1. 一个组件在用:放在组件自身即可
    2. 一些组件在用:放在它们共同的父组件上(状态提升)
  4. 实现交互:从绑定事件开始
  5. props适用于
  6. 父组件 ==> 子组件 通信
  7. 子组件 ==> 父组件 通信(要求父组件先给子组件传递一个要操作的函数)
  8. 使用v-model时要切记:v-model绑定的值不能是props传过来的值,因为props是不可以修改的!
  9. props传过来的若是对象类型的值,修改对象中的属性是Vue不会报错,当时不推荐这么做

三十五、组建的自定义事件

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

  2. 使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件回调在A中定义)

  3. 绑定自定义事件

  4. 第一种方式

    <Demo @atguigu="test"/>
    //或者
    <Demo v-on:atguigu="test"/>    
    
  5. 第二种方式

    <Demo ref="demo"/>
    
    //js
    mounted(){
    	//test回调函数必须先配置好
    	this.$regs.demo.$on('atguigu',this.test);
    }
    
  6. 若想让自定义事件只能触发一次,可以使用once修饰符,或者$once方法

  7. 触发自定义事件

this.$emit('atguigu',数据)
  1. 解绑自定义事件
this.$off('atguigu')

//多个
this.$off(['atguigu','other'])
  1. 组件上也可以绑定原生DOM事件,需要使用native修饰符

  2. 注意:通过this. r e f s . x x x . refs.xxx. refs.xxx.on(‘atguigu’,回调)绑定自定义事件时,回调要么在methods中,要么用箭头函数,否者this指向会有问题

三十六、全局事件总线

  1. 一种组件通信的方式,使用于任意组件间通信

  2. 安装全局事件总线

new Vue({
    ......
    beforeCreate(){
        Vue.prototype.$bus = this //安装全局事件总线,$bus就是当前应用的vm
    }
})
  1. 使用事件总线

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

    methods(){
        demo(data){}
    }
    ......
    mounted(){
        this.$bus.$on('xxx',this.demo);
    }
    
  3. 提供数据:

    this.$bus.$emit('xxx',data);
    
  4. 最好在beforeDestroy钩子中,用$off去解绑当前组件中所用到的自定义事件

三十七、消息订阅与发布

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

  2. 使用步骤

  3. 安装pubsub:

    npm i pubsub-js
    
  4. 引入:

    import pubsub from 'pubsub-js'
    
  5. 接收数据:A组件想接收数据,则在A组件中订阅消息,订阅的回调留在A组件自身

    methods(){
    	demo(msgName,data){......}
    }
    
    mounted(){
    	this.pid = pubsub.subscribe('xxx',this.demo); //订阅消息
    }
    
  6. 提供消息

    pubsub.publish('xxx',data)
    
  7. 最好在beforeDestroy钩子中,用pubsub.unsubscribe(pid)去取消订阅

三十八、nextTick

  1. 语法
this.$nextTick(回调函数);
  1. 作用:在下一次DOM更新结束后执行器指定的回调

  2. 什么时候用:当改变数据后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行

三十九、Vue封装的过度和动画

  1. 作用:再插入、更新或移除DOM元素时,再合适的时候给元素添加样式类名

  2. 图示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5SyYa2mf-1651027848982)(https://note-photo-1257322974.cos.ap-shanghai.myqcloud.com/Vue/%E5%8A%A8%E7%94%BB%E5%92%8C%E8%BF%87%E6%B8%A1.png?q-sign-algorithm=sha1&q-ak=AKIDGJzRej2oshI1Uha9QSyHgqkOs7Ay7gKn&q-sign-time=1649919012;86401649832612&q-key-time=1649919012;86401649832612&q-header-list=&q-url-param-list=&q-signature=63ad051eca81d36c611119e825d85162f41e8fa9)]

  1. 写法

  2. 准备好样式

    1. 元素进入的样式
      1. v-enter:进入的起点
      2. v-enter-active:进入过程中
      3. v-enter-to:进入的终点
    2. 元素离开的样式
      1. v-leave:离开的七点
      2. v-leave-active:离开过程中
      3. v-leave-to:离开的终点
  3. 使用transition包裹要过度的元素,并配置name属性

    <transtion name="hello">
    	<h1 v-show="isShow">你好啊</h1>
    </transtion>
    
  4. 备注:若有多个元素需要过度,则需要使用:<transition-group>,且每个元素都要指定key值

  5. 其他补充

    1. 如果transition没有声明name属性 那么使用v-xxx,反之用 name-xxx

    2. 如何使用animation.css

    3. 安装animation.css

      npm install animation.css
      
    4. 引用animation.css

      import 'animation.css'
      
    5. 使用animation.css

      <transition appear name="animate_animated animate_bounce" enter-active-class="xxxx" leave-active-class="">
      
      </transition>
      <!-- 
      	appear:代表一开始就应用动画或过渡样式
      	name:(动画、过渡)名称
      	enter-active-class:动画进入样式
      	enter-leave-class:动画离开样式
      --!>
      

四十、Vue脚手架配置代理(解决跨域问题)

  1. 简单配置
devServer:{
    proxy:"http://localhost:5000"
}

说明

  1. 优点:配置简单,请求资源时直接发给前端(8080)即可
  2. 缺点:不能配置多个代理,不能灵活的控制请求是否走代理
  3. 工作方式:若按照上述配置代理,当请求了前端不存在的资源时,那么请求会转发给服务器(优先匹配前端资源)
  1. 配置多个代理
module.exports = {
  devServer: {
    proxy: {
      '/api': { //匹配所有以 'api'开头的请求路径
        target: '<url>', //代理目标的基础路径
        ws: true, //是否支持websocket
        changeOrigin: true, //是否对服务器隐瞒自己的真实请求端口
        pathRewrite: {'^/api',''} //将请求地址中的api替换为空字符
      },
      '/foo': { //匹配所有以 'api'开头的请求路径
        target: '<url>', //代理目标的基础路径
        ws: true, //是否支持websocket
        changeOrigin: true, //是否对服务器隐瞒自己的真实请求端口
        pathRewrite: {'^/api',''} //将请求地址中的api替换为空字符
      }
    }
  }
}

说明

  1. 优点:可以配置多个代理,且可以灵活的控制请求是否走代理
  2. 缺点:配置略微繁琐,请求资源是必须加前缀

四十一、插槽

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

  2. 分类:默认插槽、具名插槽、作用域插槽

  3. 使用方式

  4. 默认插槽

<!-- 父组件中 -->
<Category>
	<div>
        html结构一
    </div>
</Category>

<!-- 子组件中 -->
<template>
	<div>
        <!-- 定义插槽 -->
        <slot>插槽默认内容...</slot>
    </div>
</template>
  1. 具名插槽
<!-- 父组件中 -->
<Category>
	<template slot="center">
    	<div>
            html结构1
        </div>
    </template>

    <!-- v-slot属性只能用与template标签上,其他标签无法使用 -->
    <template v-slot:footer>
    	<div>
            html结构2
        </div>
    </template>
</Category>

<!-- 子组件中 -->
<template>
	<div>
        <!-- 定义插槽 -->
        <slot name="center">插槽默认内容...</slot>
        <slot name="footer">插槽默认内容...</slot>
    </div>
</template>
  1. 作用域插槽

  2. 理解:数据在组建的自身,但根据数据生成的结构需要组建的使用者来决定。(games数据在Category组件中,但使用数据所遍历里出来的结构由App组件决定)

  3. 具体编码

    <!-- 在父组件中 -->
    
  • {{g}}
 <Category>
 	<template slot-scope="scopeData">
     	<h4 v-for="g in scopeDate.games" :key="g"></h4>
     </template>
 </Category>

 <!-- 在子组件中 -->
 <template>
 	<div>
         <slot :games="games"></slot>
     </div>
 </template>

 <script>
 	export default {
         name:'Category',
         props:['title'],
         data(){
             return {
                 games:['红色警戒','穿越火线','劲舞团','超级玛丽']
             }
         }
     }
 </script>
 ```
  1. 注意:scope="{games}"接收的就是子组件转递的参数,而slot-scope或scope接收到的是一个对象,该对象中包含子组件传递过来的参数,区别如下

    <!-- 子组件 -->
    <template>
        <div>
            <slot :games="games" msg="你好"></slot>
        </div>
    </template>
    
    export default {
        name:'StudentComp',
        data(){
            return {
                games:['穿越火线','QQ飞车','地下城与勇士']
            }
        }
    }
    
 <!-- 父组件(使用者) -->

 <!-- scope这个属性可以使用但已经过时 作用域属性必须定义在template标签上-->
 <StudentComp >
     <!-- {games} 代表一个对象games 如果要获取子组件的games 那么games.games --> 
 	<template scope="games">
  	 <ul>
    		 <li v-for="(item) in games.games" :key="item">{{item}}</li>
  	  </ul>
 	</template>
 </StudentComp>

 <StudentComp >
     <!-- {games} 代表一个对象games 如果要获取子组件的games 那么games.games --> 
 	<template slot-scope="games">
       <ol>
          <li v-for="(item) in games.games" :key="item">{{item}}</li>
       </ol>
     </template>
 </StudentComp>
 <StudentComp >
    <!-- {games} 代表着子组件中的games --> 
    <template slot-scope="{games}">
       <h4 v-for="(item) in games" :key="item">{{item}}</h4>
    </template>
 </StudentComp>

 ```

四十二、Vuex

  1. 概念

在vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组建的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信

  1. 何时使用

多个组件需要共享数据时

  1. 搭建Vuex环境
  2. 创建文件:src/store/index.js

//引入Vue核心库
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex);

//准备actions对象 ==> 响应组件中用户的动作
const actions = {}
//准备mutations对象 ==> 修改state中的数据
const mutations = {}
//准备state对象 ==> 保存具体的数据(状态)
const state = {}

//创建并暴露store
export default new Vuex.Store({
    actions,
    mutations,
    state
})
 2. 在```main.js```中创建vm时传入```store```配置项
//引入store.js 如果文件名称为index.js 那么脚手架会去该目录下寻找 index.js
import store from './store'

//创建vm
new Vue({
   el:'el',
   reder: h => h(App),
   store    //如果key和value重名,写一个就行
})
  1. 基本使用
  2. 初始化数据配置actions、配置mutations,操作文件store.js

//引入Vue核心库
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex);

//准备actions对象 ==> 响应组件中用户的动作
const actions = {
   jia(minStore,value){
       minStore.commit('JIA',value);
   }
}
//准备mutations对象 ==> 修改state中的数据
const mutations = {
   JIA(state,value){
       state.sum += value;
   }
}
//准备state对象 ==> 保存具体的数据(状态)
const state = {
   sum:0
}

//创建并暴露store
export default new Vuex.Store({
   actions,
   mutations,
   state
})
  1. 组件中读取vuex中的数据:$store.state.sum

  2. 组件中修改vuex中的数据:$store.dispatch('actions中的方法名称',数据)$store.commit('mutations中的方法名称',数据)

  3. 备注

    若没有网络请求或其他业务逻辑,组件中也可以越过actions,即不写dispatch,直接编写commit

  4. getters的使用
  5. 概念:当state中的数据需要经过加工后在使用,可以使用getters加工

  6. store.js中追加getters配置

    const getters = {
        bigSum(state){
            return state.sum*10;
        }
    }
    
    //创建并暴露store
    export default new Vuex.Store({
        .....
        getters,
    })
    
  7. 四个map方法的使用
  8. mapState方法:用于帮助我们映射state中的数据为计算属性

    import {mapState} from vuex
    computed:{
        //借助mapState生成计算属性:sum、school、subject(对象写法)
        ...mapState({sum:'sum',school:'school',subject:'subject'})
    
         //借助mapState生成计算属性:sum、school、subject(数组写法)
        ...mapState(['sum','school','subject'])
    }
    
  9. mapGetters方法:用于帮助我们映射getters中的数据为计算属性

    import {mapGetters} from vuex
    computed:{
        //借助mapGetters生成计算属性:bigSum(对象写法)
        ...mapGetters({bigSum:'bigSum'})
    
         //借助mapGetters生成计算属性:bigSum(数组写法)
        ...mapGetters(['bigSum'])
    }
    
  10. mapActions方法:用于帮助我们生成与actions对话的方法,即:包含$store.dispatch(xxx)函数

    import {mapActions} from vuex
    methods:{
        //靠mapActions生成:incrementOdd、incrementWait(对象形式)
        ...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
    
        // //靠mapActions生成:incrementOdd、incrementWait(数组形式)
        ...mapActions(['jiaOdd','jiaWait'])
    }
    
  11. mapMutations方法:用于帮助我们生成与mutations对话的方法,即:包含$store.commit(xxx)的函数

    import {mapMutations} from vuex
    methods:{
        //靠mapMutations生成:incrementOdd、incrementWait(对象形式)
        ...mapMutations({incrementOdd:'JIA',incrementWait:'JIAN'})
    
        // //靠mapActions生成:JIA、JIAN(数组形式)
        ...mapMutations(['JIA','JIA'])
    }
    
  12. 模块化+命名空间
    1. 目的:让代码更好维护,让多种数据分类更加明确

    2. 修改store.js

      const countAbout = {
          namespaced:true, //开启命名空间
          state:{x:1},
          mutations:{....},
          actions:{....},
          getters:{
              bigSum(state){
                  return state.sum * 10
              }
          }
      }
      
      const personAbout = {
          namespaced:true, //开启命名空间
          state:{x:1},
          mutations:{....},
          actions:{....},
          getters:{
              bigSum(state){
                  return state.sum * 10
              }
          }
      }
      
      const store = new Vuex.Store({
          modules:{
              countAbout, // 不简写 ==> countAbout:countAbout
              personAbout // 不简写 ==> personAbout:personAbout
          }
      })
      
    3. 开启命名空间后,组件中读取state数据

      //方式一,自己直接读取
      this.$store.state.personAbout.list
      //方式二,借助mapState读取
      ...mapState('countAbout',['sum','school','subject'])
      
    4. 开启命名空间后,组件中读取getters数据

      //方式一,自己直接读取
      this.$store.getters['personAbout/firstPersonName']
      //方式二,借助mapGetters读取
      ...mapGetters("countAbout",['bigSum'])
      
    5. 开启命名空间后,组件中调用dispatchactions

      //方式一,自己直接读取
      this.$store.dispatch['personAbout/addPersonWang']
      //方式二,借助mapActions读取
      ...mapActions("countAbout",{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
      //方式三、名称一致的情况下可以使用以下这种方式
      

    …mapActions(“countAbout”,[‘jiaOdd’,‘jiaWait’])

    
    6. 开启命名空间后,组件中调用```commit```即 ```mutations```
    
    ```js
    //方式一,自己直接读取
    this.$store.commit['personAbout/ADD_PERSON',person]
    //方式二,借助mapMutations读取
    ...mapMutations("countAbout",{increment:'JIA',decrementWait:'JIAN'})
    

四十三、Vue-Router(路由)

一、基本使用
  1. 安装vue-router,命令npm i vue-router

  2. 应用插件:Vue.use(VueRouter)

  3. 编写router配置项

//引入VueRouter
import VueRouter from 'vue-router'
//引入路由组件
import About from '../components/About'
import Home from '../components/Home'

//创建router实例对象,去管理一组一组的路由规则
const router = new VueRouter({
  	routers:[
        {
            path:'/about',
            component:About
        },
        {
            path:'/home',
            component:Home
        }
    ]  
})
  1. 实现切换(active-class可配置高亮样式)
<router-link active-class='active' to='/about'>About</router-link>
  1. 指定展示位置
<router-view></router-view>
二、几个注意点
  1. 路由组件通常放在pages文件夹,一般组件通常放在components文件夹

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

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

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

    ```js
    //方式一,自己直接读取
    this.$store.dispatch['personAbout/addPersonWang']
    //方式二,借助mapActions读取
    ...mapActions("countAbout",{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
    //方式三、名称一致的情况下可以使用以下这种方式
    

    …mapActions(“countAbout”,[‘jiaOdd’,‘jiaWait’])
    ```

    1. 开启命名空间后,组件中调用commitmutations

      //方式一,自己直接读取
      this.$store.commit['personAbout/ADD_PERSON',person]
      //方式二,借助mapMutations读取
      ...mapMutations("countAbout",{increment:'JIA',decrementWait:'JIAN'})
      

四十三、Vue-Router(路由)

一、基本使用
  1. 安装vue-router,命令npm i vue-router

  2. 应用插件:Vue.use(VueRouter)

  3. 编写router配置项

//引入VueRouter
import VueRouter from 'vue-router'
//引入路由组件
import About from '../components/About'
import Home from '../components/Home'

//创建router实例对象,去管理一组一组的路由规则
const router = new VueRouter({
  	routers:[
        {
            path:'/about',
            component:About
        },
        {
            path:'/home',
            component:Home
        }
    ]  
})
  1. 实现切换(active-class可配置高亮样式)
<router-link active-class='active' to='/about'>About</router-link>
  1. 指定展示位置
<router-view></router-view>
二、几个注意点
  1. 路由组件通常放在pages文件夹,一般组件通常放在components文件夹
  2. 通过切换,“隐藏”了的路由组件,默认是被销毁了,需要的时候再去挂载
  3. 每个组件都有自己的$route属性,里面存储着自己的路由信息
  4. 整个应用只有一个router,可以通过组件的$router属性获得
  5. 所有路由组件的$route属性是不同的,而$router是一样的
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值