vue框架知识总结

目录

vue是什么

MVVM

vue优势

vue的开发目的

vue核心

vue初体验

{{}}是什么?

vue渲染数据

数据驱动分类

指令

v-model

双向绑定的原理

v-show

v-on

v-for

v-bind(使用中最容易忽略的指令)

v-if全家桶

v-if

v-if与v-show的区别

v-else

v-else-if

v-html

v-once

v-text

屏幕闪烁

watch监听

计算属性---computed

为什么要使用计算属性?

什么是计算属性

计算属性与方法的区别

计算属性与watch的区别

vue的事件对象

事件修饰符

案件修饰符

 事件修饰符

过滤器与全局局部

自定义过滤器---filter

全局过滤器---filter

 局部过滤器---filters

扩展--内置过滤器

钩子函数

生命周期的钩子函数

实例创建

模板渲染

数据更新

实例销毁

第一次之行的之后执行那几个钩子

生命周期的钩子函数有什么作用?

DOM渲染在那个钩子中完成

vue-cil脚手架

.vue文件

拿到空项目怎么办?

属性的使用

 为什么data是一个函数而不是对象

一下的和之前本地模式没有任何区别

组件

组建分类

全局组件--component

局部组件--components

组件的本质  就是自定义标签

scoped

父子组件

组件传值

正向传值--props

props验证

逆向传值

实现:

兄弟同胞传值--中央事件总线

什么是中央事件总线

实现

跨组件传值--vuex

vuex使用

modules模块

mutations状态修改

payload 载荷

actions用来触发异步操作

数据请求的闭环操作

slot--槽口/插槽

引子

槽口是什么?

基础用法

具名槽口

路由---router

传统的项目怎么切换跳转页面?

路由基本概念

路由基本创建

vue-cl自动创建

带有路由的空项目怎么办?

手动创建

路由导航

标签方式----声明式导航

声明式导航选中样式类

js的方式--- 编程式导航

404页面

重定向----redirect

路由出口

多级路由/嵌套路由

路由传参/动态路由匹配

方式

params方式

编程式

query方式

query和params的区别

$router与$route区别

路由模式

路由守卫/路有钩子/导航守卫

全局守卫

路由独享守卫

组件内守卫

扩展--懒加载

扩展--路由的更多属性

meta 路由记录/路由元信息

在组件内获取路由全部规则

前后端数据交互

axios

基本使用

数据请求封装与拦截器

数据请求封装

axios拦截器

mockjs 模拟数据

使用

mixins 混入

分类

自定义指令----directives

ref

扩展--$set以及原理

$set的使用

动态组件

keep-alive

引子

出现的原因

keep-alive

属性

钩子函数keep-alive

nextTick

数据修改异步说明

什么是nextTick

扩展---浏览器自动开启与修改端口


vue是什么

vue.js是现今最为主流的MVVM框架

作者:尤雨溪  

MVVM

mvvm是一个编程思想 在这个思想下  更加只专注于业务的开发(功能)让我们的开发变得更加简单

M ----model  模型=数据

V  ----view     视图=界面(就是你写出来让用户看见的内容)

VM ---viewmodel   视图模型   用来传递模型和关联视图的

vue优势

vue的开发目的

vue核心

数据驱动与组件化

vue初体验

获取vue的依赖库  npm install  --save vue

编写如下内容:

<!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>Document</title>
    <!-- 
        1.下载包
        2.引包 -->
    <script src="./node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
    <!-- M    ------model     模型 = 数据

    V    ------ view         视图 = 界面(就是你写出来让用户看见的内容)

    VM    --- viewmodel     视图模型      用来传递模型和关联视图的 -->

    <!-- 3.新建v层 -->
    <div id="demodiv">
        {{text}}
    </div>
    <script>
// <!-- 4.新建vm层    就是vue实例 -->
        new Vue({
            el:"#demodiv",
            // 5.编写m层
            data:{
                text:"你好么么哒!!!!!^_@"
            }
        })
    </script>
</body>
</html>

{{}}是什么?

{{表达式---通过计算返回结果的公式}}

{{}}大括号赋值法/双大括号语法/模板语法

<!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>Document</title>
    <script src="./node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
    <div id="demodiv">
        <h1>双大括号赋值法</h1>
        <h1>{{text}}</h1>
        <h1>{{num+2}}</h1>
        <h1>{{bool?"你好":"你坏"}}</h1>
    </div>
    <script>
        new Vue({
            el:"#demodiv",
            data:{
                text:"字符串",
                num:18,
                bool:false,
                arr:[1111,22222,33333,44444],
                obj:{
                    name:"xixi",
                    age:18
                }
            }
        })
    </script>
</body>
</html>

vue渲染数据

vue.js的核心就是数据驱动 vue的数据驱动就是视图的内容是根据模型data数据的改变而改变的

数据驱动分类

1.声明式渲染 我们只需要告诉程序 想干什么  那么程序就会自动来完成

2.命令式渲染  我们需要一步步的指挥着程序  程序才会按照我们的指令去执行

指令

在vue中 使用v-开头html特殊属性

指令的作用:在vue中 扩展标签的功能

指令的语法:写在html开标签中并且 v-指令="指令值"

v-model

作用:用于在表单元素上完成数据的双向绑定

语法:v-model='值'

双向绑定

用户可以看见的界面中也就是v层视图层 改变了数据 那么data中内容也就会改变 视图变模型变

模型改变了 反之也会让视图发生改变 模型变视图变

<!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>Document</title>
    <script src="./node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
    <div id="demodiv">
        <h1>v-model</h1>
        <!-- 双向绑定
        用户在可以看见的界面中也就是v层视图层   改变了数据 那么data中的内容也就会改变   视图变模型变

        模型改变了   反之也会让视图发生改变   模型变视图变 -->
        <input type="text" v-model="inputval"/>

        <h1>{{inputval}}</h1>
    </div>
    <script>
        new Vue({
            el:"#demodiv",
            data:{
                inputval:""
            }
        })
    </script>
</body>
</html>

双向绑定的原理

双向绑定是通过数据劫持与发布者订阅者模式来实现的

数据劫持:数据(变量)劫持(拦截)就是当数据改变的时候我要拦截到这次改变 通知模型或者视图发生改变

通过一个Object,defindProperty()来监听数据当数据改变时它就会触发 从而通知另外一方(有一个get的方法和set的方法 分别是读取与修改)

也有一个bug

bug详见$set

发布者订阅者模式:就是一个一对多的关系,当发布者改变了起所有的订阅者页随之发生改变

v-show

作用:控制dom元素的显示和隐藏

语法:v-show=“返回值为布尔值的表达式” true 显示 false 隐藏

<!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>Document</title>
    <script src="./node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
    <div id="demodiv">
        <h1>v-show</h1>
        <!-- 如果给一个复选框绑定一个变量  那么这个变量会随着勾选和取消在true和false中切换 -->
        <input type="checkbox" v-model="bool"/>{{bool?"显示了":"隐藏了"}}
        <h1 v-show="bool">我是测试显示和隐藏的元素</h1>
    </div>
    <script>
        new Vue({
            el:"#demodiv",
            data:{
                bool:true
            }
        })
    </script>
</body>
</html>

v-on

作用:就是给dom元素绑定事件的

语法:v-on:事件不加on=“函数” 简写就是@

<!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>Document</title>
    <script src="./node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
    <div id="demodiv">
        <h1>v-on</h1>
        <!-- 绑定事件用v-on -->
        <button v-on:click="fun()">点我绑定事件</button>

        <!-- v-on还有个简写的写法   就是把v-on:  替换成 @ -->
        <button @click="fun()">简写写法</button>
    </div>
    <script>
        new Vue({
            el:"#demodiv",
            data:{
             
            },
            // methods来创建函数
            methods:{
                // 函数名(){
                    
                // }
                fun(){
                    console.error("你好么么哒")
                }
            }
        })
    </script>
</body>
</html>

v-for

作用:遍历展示数据

语法:v-for=“(参数1==遍历出来的值,参数2--遍历出来的下标)in 你要便利的数据”

<!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>Document</title>
    <script src="./node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
    <div id="demodiv">
        <h1>v-for</h1>
        <ul>
            <li v-for="(v,i) in arr">{{v}}</li>
        </ul>
        <hr>
        <table border="1">
            <tr v-for="(v,i) in obj">

                <td>{{i}}</td>
                <td>{{v.name}}</td>
                <td>{{v.age}}</td>
            </tr>
        </table>
        
    </div>
    <script>
        new Vue({
            el:"#demodiv",
            data:{
                arr:["EZ","Vn","MF","NOC"],
                obj:[
                    {name:"xixi1",age:181},
                    {name:"xixi2",age:182},
                    {name:"xixi3",age:183},
                    {name:"xixi4",age:1845},
                    {name:"xixi5",age:186},
                    {name:"xixi6",age:187}
                ]
            }
        })
    </script>
</body>
</html>

v-bind(使用中最容易忽略的指令)

作用:就是给html的属性插入变量

语法:v-bind:html标签的属性=“变量”简写:

<!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>Document</title>
    <script src="./node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
    <div id="demodiv">
        <h1>v-bind</h1>
        <!-- html的属性插变量使用v-bind -->
        <a v-bind:href="ahref">{{atext}}</a>
        <!-- 简写   v-bind: 替换成   : -->
        <a :href="ahref">{{atext}}</a>
    </div>
    <script>
        new Vue({
            el:"#demodiv",
            data:{
                atext:"点我去百度",
                ahref:"http://www.baidu.com"
            }
        })
    </script>
</body>
</html>

v-if全家桶

v-if

从用户的角度看上去和v-show没有区别

作用:判断当前dom是否加载

语法:v-if=“表达式结果为布尔值” true加载当前dom false溢出当前dom

<!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>Document</title>
    <script src="node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
   <div id="demodiv">
       <h1>v-if</h1>

       <h1 v-if="bool">我是测试v-if</h1>
       <h1 v-show="bool">我是测试v-show</h1>
    </div>
    <script>
        new Vue({
            el:"#demodiv",
            data:{
              bool:true
            },
            methods:{
               
            }
        })
    </script>
</body>
</html>

v-if与v-show的区别

v-if在显示和隐藏的时候是对当前dom进行溢出的添加 v-if在页面初始化的时候性能损耗低 在切换的时候性能损耗高

v-show是对于css的样式设置显示和隐藏 v-show在页面初始化的时候性能损耗高 在切换的时候性能损耗低

v-else

必须配合v-if来使用 当v-if条件不成立的时候执行

<!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>Document</title>
    <script src="node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
   <div id="demodiv">
       <h1>v-else</h1>

       <h1 v-if="false">请登录</h1>
       <!-- v-if与v-else之间不能有第三者 -->
       <h1 v-else>欢迎您尊敬的vip</h1>
     
    </div>
    <script>
        new Vue({
            el:"#demodiv",
            data:{
            
            },
            methods:{
               
            }
        })
      
    </script>
</body>
</html>

v-else-if

多重if选择 当其中一项成立的时候

<!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>Document</title>
    <script src="node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
   <div id="demodiv">
       <h1>v-else-if</h1>



        <select v-model="text">
            <option value="吃饭">吃饭</option>
            <option value="睡觉">睡觉</option>
            <option value="上厕所">上厕所</option>
            <option value="在吃饭">在吃饭</option>
            <option value="在睡觉">在睡觉</option>
        </select>





       <h1 v-if="text=='吃饭'">吃饭</h1>
       <h1 v-else-if="text=='睡觉'">睡觉</h1>
       <h1 v-else-if="text=='上厕所'">上厕所</h1>
       <h1 v-else-if="text=='在吃饭'">在吃饭</h1>
       <h1 v-else-if="text=='在睡觉'">在睡觉</h1>
       <h1 v-else>啥都没干</h1>
     
    </div>
    <script>
        new Vue({
            el:"#demodiv",
            data:{
                text:""
            },
            methods:{
               
            }
        })
      
    </script>
</body>
</html>

v-html

作用:把字符串标签 解析到页面中

语法:v-html=“值”

<!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>Document</title>
    <script src="node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
   <div id="demodiv">
       <h1>v-html</h1>

        <div>
            {{newhtml}}

            <div v-html="newhtml"></div>
        </div>
     
    </div>
    <script>
        new Vue({
            el:"#demodiv",
            data:{
                newhtml:"<em>我是测试的</em>"
            },
            methods:{
               
            }
        })

      
    </script>
</body>
</html>

v-once

作用:一次性插值 数据插入到页面中之后就不会改变了

<!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>Document</title>
    <script src="node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
   <div id="demodiv">
       <h1>v-once</h1>
    <input type="text" v-model="text">
    <h1 v-once>{{text}}</h1>
    <h1>{{text}}</h1>
    <h1>{{text}}</h1>
    <h1>{{text}}</h1>
    <h1>{{text}}</h1>
    <h1>{{text}}</h1>
     
    </div>
    <script>
        new Vue({
            el:"#demodiv",
            data:{
              text:"我是默认值"
            },
            methods:{
               
            }
        })

 
    </script>
</body>
</html>

v-text

作用:就是在页面中插入纯文本{{}}可以理解为和他是一样的功能

<!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>Document</title>
    <script src="node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
   <div id="demodiv">
       <h1>v-text</h1>
       <h1>{{num}}</h1>
       <h1 v-text="num"></h1>

     
    </div>
    <script>
        new Vue({
            el:"#demodiv",
            data:{
                num:"我是默认值"
            },
            methods:{
               
            }
        })


    </script>
</body>
</html>

屏幕闪烁

当用户网络或者设备性能比较低的时候  可能在vue渲染初期会在页面显示没有编译好很多{{}} 当网络通顺或者设备渲染完成之后  突然间显示最终效果  就叫屏幕闪烁

解决:

1.v-text

2.v-cloak指令 该指令是会在vue渲染完毕后自动消失

 <style>
        [v-cloak]{
            display: none;
        }

    </style>
    
    <div id="demodiv" v-cloak>
       <h1>v-text</h1>
       <h1>{{num}}</h1>
       <h1 v-text="num"></h1>

     
    </div>

watch监听

他是vue实例中的一个属性 写在与了data methods等属性同级的位置

用来绑定监听data中创建的数据 当ssata的数据改变的时候,watch就会通知 做出相关的反应

watch在初始化的时候是不会执行的 只有当数据改变的时候才会运行

如果就是想让watch在初始化执行怎么办?

 watch: {
                value: {
                    handler: function (o, n) {
                        this.text="123456"
                     },
                    immediate: true
                }
            },

语法:

watch:{

        newval 就是改变之后的值  oldval就是之前的旧数据

        你要监听的数据(newval,oldval){

}

}

<!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>Document</title>
    <script src="node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
    <div id="demodiv">
        <h1>watch的使用</h1>
        <h1>{{text}}</h1>
        <button @click="fun()">点我改变数据</button>
    </div>
    <script>
        new Vue({
            el:"#demodiv",
            data:{
                text:"我是默认值"
            },
            methods:{
                fun(){
                    this.text="你好么么哒!!"
                }
            },
            watch:{
                text(newval,oldval){//当text改变的时候就会执行
                    console.log(newval);
                    console.log(oldval);
                }
            }
        })
    </script>
</body>
</html>

计算属性---computed

为什么要使用计算属性?

视图层是用来展示数据的 但是我们却在视图层中处理数据  不太合适

<!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>Document</title>
    <script src="node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
    <!-- 视图层是用来展示数据的   但是我们却在视图层中处理数据 -->
    <div id="demodiv">
        <h1>{{text}}</h1>
        <h1>大写展示:{{text.toUpperCase()}}</h1>
        <h1>大写加截取展示:{{text.toUpperCase().substr(1,4)}}</h1>
    </div>
    <script>
        new Vue({
            el:"#demodiv",
            data:{
               text:"abcdefghijk"
            },
            methods:{
              
            },
            watch:{
               
            }
        })
    </script>
</body>
</html>

什么是计算属性

计算属性   他是一个vue实例下的属性  这个属性是一个带有甲酸(data数据的)功能的  他会时时刻刻的盯着data中的数据  当data的数据改变了  他也会知道 重新计算并且在返回出计算之后的结果

一条数据  在不同位置展示不同形态的时候  使用

语法:

computed:{

        你计算之后返回的数据变量(){

                return 你处理数据的逻辑

        }

}

<!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>Document</title>
    <script src="node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
    <div id="demodiv">
        <h1>{{text}}</h1>
        <h1>大写{{upptext}}</h1>
    </div>
    <script>
        new Vue({
            el:"#demodiv",
            data:{
                text:"abcdefghijk"
            },
            methods:{
               
            },
            watch:{
               
            },
            computed:{
                upptext(){
                    return this.text.toUpperCase()
                }
            }
        })
    </script>
</body>
</html>

计算属性与方法的区别

<!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>Document</title>
    <script src="node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
    <div id="demodiv">
        <h1>{{text}}</h1>
        <h1>大写{{upptext}}</h1>
        <hr>
        <h1>{{fun()}}</h1>
        
    </div>
    <script>
        new Vue({
            el:"#demodiv",
            data:{
                text:"abcdefghijk"
            },
            methods:{
                fun(){
                    console.log("我是方法")
                    return this.text.toUpperCase()
                }
            },
            watch:{
               
            },
            computed:{
                upptext(){
                    console.log("我是计算属性")
                    return this.text.toUpperCase()
                }
            }
        })
    </script>
</body>
</html>

计算属性 是依赖与缓存的 也就是说计算属性处理的数据 在第一次处理好之后就会把结果存储在内存中 只要处理的数据不变 那么无论我们调用多少次 他的数据都是从缓存中读取出来的

方法:方法只要被调用就会执行 方法比较消耗性能

计算属性与watch的区别

watch监听一个data数据 当这个data数据改变的时候 watch就会出发一个函数完成一些指定的功能(异步操作 开销较大的逻辑)

计算属性 依赖一个data的数据 当这个数据变了他会重新计算这个数据返回结果

vue的事件对象

$event来描述事件对象

<!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>Document</title>
    <script src="node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
    <div id="demodiv">
        <h1>事件对象的使用</h1>
        <button @click="fun($event)">点我得到事件对象</button>
    </div>
    <script>
        new Vue({
            el:"#demodiv",
            data:{
               
            },
            methods:{
                fun(xiaoming){
                    console.log(xiaoming.target);
                }
            },
            watch:{
             
            }
        })
    </script>
</body>
</html>

事件修饰符

就是帮助我们来修饰一些在触发事件过程中的一些细节

修饰符:@事件.修饰符

案件修饰符

帮助我们在出发一些事件的时候  指定键盘按钮

.up .down .ctrl .enter .space等 按键修饰符

  <input type="text" @keydown.enter="changeb($event)">

 事件修饰符

.prevent  阻止事件默认行为

.stop       阻止冒泡

.captrue  设置当前为捕获事件

.once      当前事件只会触发一次

.self        只会触发自身的事件  不包含子元素

过滤器与全局局部

全局与局部

全局就是在所以uvue实例中都可以使用

局部就是只能在当千实例中使用

自定义过滤器---filter

在不改变原始数据的情况下  格式化展示内容

全局过滤器---filter

写在创建vue实例之前

Vue.filter(“过滤器的名字”,(你要过滤的数据)=>){

        return  你过滤的逻辑

 })

<!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>Document</title>
    <script src="./node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
    <div id="demodiva"> {{text}}</div>

    <div id="demodivb">{{text}} </div>
    <script>
        // 写在实例之前
        Vue.filter("xiaoming",(val)=>{
            return "<<"+val+">>"
        })


        new Vue({
            el:"#demodiva",
            data:{
               text:"红楼梦"
            }
        })
        new Vue({
            el:"#demodivb",
            data:{
               text:"西游记"
            }
        })
    </script>
</body>
</html>

使用:

|  管道符来进行使用  数据|过滤器的名字

 <div id="demodiva"> {{text|xiaoming}}</div>

 局部过滤器---filters

写咋像是这个过滤器的实例中  与el data methods watch computed同级

filters:{

        过滤器的名字(val 你要过滤的数据会自动传入){

                return 你过滤的逻辑

        }

}

<!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>Document</title>
    <script src="./node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
    <div id="demodiva">{{text|xiaoming}} </div>

    <div id="demodivb"> {{text|xiaoming}} </div>
    <script>
        new Vue({
            el:"#demodiva",
            data:{
                text:"我是第1个"
            },
            filters:{//局部过滤器
                xiaoming(val){
                    return "<<"+val+">>"
                }
            }
        })
        new Vue({
            el:"#demodivb",
            data:{
                text:"我是第2个"
            }
        })
    </script>
</body>
</html>

扩展--内置过滤器

在vue2x之后  内置过滤器已经移除了  所以在vue2.0之后就没有内置过滤器了

钩子函数

在特定阶段内被自定义执行的函数  就叫做钩子函数

生命周期的钩子函数

被自动执行的函数

就可以让程序在特定阶段自动执行某些操作

钩子函数就是几个vue预先定义好的自动执行的函数  所以我们如果要写  写在data  el  methods等同级位置

实例创建

实例创建之前---beforeCreate  在这个钩子中数据观测与事件还没有开始

实例创建完毕---created数据的观测  实例的其他属性 以及事件等 都已经准备好了

模板渲染

模板渲染之前--befireMount 已经准备开始挂载页面了  次是页面还诶有开始渲染

模板渲染之后--mounted  el属性已经挂载完成  dom也已经渲染加载完毕了

数据更新

数据更新之前--beforeUpdate 准备开始更新 猜这个时候还没有更新进行数据的状态修改

数据更新之后--updata 数据页面Dom都已经修改完毕了

实例销毁

实例销毁之前 -- beforeDestory 小胡胡之前 但是此时实例还可以使用

实例销毁之后 -- destoryed  实例已经不存在了和vue相关的左右内容都不能使用

第一次之行的之后执行那几个钩子

实例创建前后  模板渲染前后

生命周期的钩子函数有什么作用?

vue预先定义好的自动致新个函数 实在vue实例从创建到销毁的过程中自动执行某些特定过得业务函数

DOM渲染在那个钩子中完成

nounted

vue-cil脚手架

1.电脑上必须有node

2.全局下载vue-cli(除非你重新装电脑了或者重装node了,否则只要下载一次就好了 )npm install -g @vue/cil

3.测试下载是否成功 vue --version

4.把cmd cd到执行下载项目的文件夹下

5.新建项目 vue create项目名

会出现选择  那么在第一项  我们选择第三个自定义 剩下的  眼睛一闭 回车到底

6 把cms cd到你下载的项目之下

7 启动  npm run serve

.vue文件

.vue文件---》单文件组件

组成:

1.template --》把你的html写进去

2.script --》把你的js写进去

3.style  --》把你的css写进去

拿到空项目怎么办?

1.删除src下的components文件夹下的Helloword.vue

2.在新建一个属于我们自己的.vue文件并写入如下内容

<template>
  <div>
      <h1>你好么么哒</h1>
  </div>
</template>

<script>
export default {

}
</script>

<style>

</style>

3.来到app.vue中(app.vue是全部组件的老大)修改原来里面helloword相关内容成我们自己的

<template>
  <div id="app">
    <!-- 4图片删除引用 -->
    <!-- <img alt="Vue logo" src="./assets/logo.png"> -->
    <!-- 3.使用 -->
    <Home/>
  </div>
</template>

<script>
// 1.引用
import Home from './components/home.vue'

export default {
  name: 'App',
  components: {
    // 2.调用
    Home
  }
}
</script>

<style>
/* 5删除原有样式 */
/* #app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
} */
</style>

属性的使用

data

语法:

data(){
        return {
            
        }
    }

 为什么data是一个函数而不是对象

因为对象是引用数据类型 如果data是对象的方式创建的  那么这个组件被多次调用的时候  data都指向的是统一的内存空间

函数的话  每一次调用都返回一个新的对象

一下的和之前本地模式没有任何区别

methods

watch

computed

filters

8个生命周期的钩子函数

组件

组件把一个页面拆成多个细小的小功能个区域  分别来创建就可以让这一个个的小模块方便重复的进行调用 减少了代码量降低了后期维护难度

组建分类

全局组件--component

局部组件--components

创建组件其实就是新建一个.vue文件 并且写入如下内容

<template>
  <div>
      我是一个组件么么哒
  </div>
</template>

<script>
export default {

}
</script>

<style>

</style>

使用组件

在你想使用的地方

引用

// 1.引用
import Demo from "./components/demo.vue"

 调用

components用来描述局部组件 写在与data methods watch等同级的位置

语法:

components:{

        给你引用的组件起个名字:你引用的组件

}

components:{
    Demo
  }
  使用

组件的本质  就是自定义标签

标签有单标签和双标签  单标签 <关键字/> 双标签 <关键字></关键字>

<你的组件名/>

scoped

当前样式仅对当前组件生效

父子组件

其实就是在一个组件中引用另外一个组件

引用

调用

使用

组件传值

我在父组件中有个数据  我能在子组件中直接使用吗?不能

我在子组件中有个数据  我能在父组件中直接使用吗?不能

结论:

组件与组件之间是完全独立的个体  无论组件是什么关系都不能直接相互使用数据

正向传值--props

父组件把数据给子组件使用

1.子组件需要使用props来创建接受传递过来数据的变量

props写在与data methods等同级的位置

语法:

props:[变量1,变量2,......,变量n]

<template>
  <div>
      {{xiaoming}}
  </div>
</template>

<script>
export default {
    props:["xiaoming"]
}
</script>

2.父组件要给他传递数据

在子组件在被调用的时候  把子组件的props当做一个属性来进行传值

 <div class="bottombar">
 
      <Zi xiaoming="数据1"/>
      <Zi xiaoming="你好"/>
      <Zi xiaoming="购物车1"/>
      <Zi xiaoming="购物车2"/>
      <Zi xiaoming="购物车3"/>
  </div>

props验证

就是在现有的正向传值之上 对父组件传递给子组件的数据进行数据格式或者累心上的验证

1.子组件接收的时候需要设置接收数据的验证

props:{

        你接收数据的变量:数据类型

        你接收数据的变量:[ 数据类型1,数据类型2 ]

        你接收数据的变量:{

        type:你要验证的数据类型,

        default:默认值

}

}

 props:{
        //text:String 只验证一种类型
        text:[String,Number]
    }

默认值语法

props:{
        //text:String 只验证一种类型
        // text:[String,Number]
        text:{
            type:String,
            // 默认值
            default:"你好我是默认值"
        }
    }

逆向传值

子组件把数据给父组件

逆向传值默认是不被允许的 如果想逆向传值的话那么我们必须要通过自定义事件来完成

逆向传值必须要通过一个事件来触发自定义事件的创建

实现:

1.在子组件中必须要用一个事件来触发
 

<template>
  <div>
      zizzizizizizizi
      <button v-on:click="fun()">点我进行逆向传值</button>
  </div>
</template>

<script>
export default {
    methods:{
        fun(){
            
        }
    }
}
</script>

<style>

</style>

2.自定义事件  使用this.$emit()来实现自定义事件

语法:this.$emit(“自定义事件名”,“数据”)

<template>
  <div>
      zizzizizizizizi
      <button v-on:click="fun()">点我进行逆向传值</button>
  </div>
</template>

<script>
export default {
    methods:{
        fun(){
            // 创建自定义事件
            this.$emit("xiaoming","我是子组件的数据^_*!")
        }
    }
}
</script>

<style>

</style>

3.父组件接受这个自定义事件

<template>
  <div>
      fufuffufufufufufufu
      <!-- 父组件函数不加()
      父组件函数不加()
      父组件函数不加()
      父组件函数不加()
      父组件函数不加() 
      因为加了函数就自动调用了
      -->
      <Nz @xiaoming="demo"/>
  </div>
</template>

<script>
import Nz from "./nizi.vue"
export default {
    methods:{
        // 这个形参就是子组件传递的数据会自动传给形参
        demo(val){
            console.log(val);
        }
    },
    components:{
        Nz
    }
}
</script>

<style>
    div{
        font-size: 0.2rem;
    }
</style>

 逆向传值默认不被允许  所以我们通过事件触发一个自定义事件的抛出  在父组件中使用@绑定这个自定义事件  从而得到子组件的数据

兄弟同胞传值--中央事件总线

相同父组件的两个子组件之间相互传值

默认情况下兄弟组件要进行传值

什么是中央事件总线

eventBus---中央事件总线  就是凌驾在两兄弟组件之上的一个空的vue实例(中央事件总线eventBus)通过这个空的vue实例 就在两个兄弟组件之上建立了数据通信的桥梁

实现

1.新建文件夹eventbus与文件用来存放这个中央事件总线的空实例

2.创建空实例

import Vue from "vue"
//创建空实例并且暴漏
export default new Vue

3.需要传递的组件中 引用中央事件总线  并且 使用事件来触发  给中央事件总线之上绑定一个自定义事件

<template>
  <div>
      <!-- 2.事件来触发一个函数 -->
      zia <button @click="fun()">点我把数据给zib</button>
  </div>
</template>

<script>
// 1.引用中央事件总线
import EventBus from "@/eventbus/index.js"
export default {
    methods:{
        fun(){
            // 3.给中央事件总线之上绑定一个自定义事件
            EventBus.$emit("zia","我是zia的数据呵呵!!!!")
        }
    }
}
</script>

<style>

</style>

4.在需要数据的组件之上 先引用中央事件总线  使用$on()来监听实例上的自定义事件

<template>
  <div>
      zib
  </div>
</template>

<script>
// 1.引用
import EventBus from "@/eventbus/index.js"
export default {
// 2.就可以使用$on来监听实例上的自定义事件
// $on( 你要监听得自定义事件名,(你传递过来的数据)=>{} ) 
    mounted(){
        EventBus.$on("zia",(val)=>{
            console.log(val);
        })
    }
}
</script>

<style>

</style>

跨组件传值--vuex

组件与组件之间有多个层级关系的时候传值

vuex状态(数据)管理工具 给仙姑提供了一个集中保存数据的地方 把项目的数据都放在这个仓库中 无论哪个组件想使用某条数据 那么直接来仓库去取出即可 免去了传统组件与组件之间传递数据的复杂性

vue是单项数据流 那么组件与组件之间在传递的时候 如果是兄弟或者跨组件又或者逆向传值  我们就可以使用vuex来集中的管理我们的数据

vuex使用

state存放数据的地方

定义state实在vuex在文件中的state中进行定义

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {//就是这个仓库中存放数据的地方

    name:"xixi"

  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
})

使用方式1

直接在你想使用的地方用  this.$store.state.xxx 来直接读取

<template>
  <div class="about">
    <h1>This is an about page{{this.$store.state.name}}</h1>
  </div>
</template>

使用方式2

在计算属性中进行调用

<template>
  <div class="about">
    <h1>This is an about page{{this.$store.state.name}}</h1>

    <h1>计算属性方式取值--{{newname}}</h1>
  </div>
</template>
<script>
export default {
  // 方式2在计算属性中进行读取
  computed:{
    newname(){
      return this.$store.state.name
    }
  }
}
</script>

总结:

1.vuex是一个仓库  里面有很多个对象 其中state就是用来保存数据的地方 相对与vue的data作用

2.state里面的数据时响应式的  vue的组件从store中读取数据如果store中的state改变了  那么对应引用的视图也会随之发生改变

modules模块

传统写法上 我们把所有的vuex操作都在一个文件中继续编写太麻烦了 后期也不好维护

1.在store下新建文件夹  用来存放我们拆分的模块文件

2.在文件中新建对象并且把vuiex的属性放置进去

let aboutm={
    state: {//就是这个仓库中存放数据的地方

        name:"我是about的数据",
      
       
    
      },
      mutations: {
      },
      actions: {
      },
}

export default aboutm

3.在vuex的文件中引用模块  调用模块

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

// 1.引用模块
import Aboutm from "./modules/aboutm.js"
import Homem from "./modules/homem.js"

export default new Vuex.Store({
  
  modules: {//2.模块的调用
    Aboutm,Homem
  }
})

4.在使用模块之后  页面使用数据  就必须是this.$store.state.模块名.xxxx

 <h1>This is an about page{{this.$store.state.aboutm.name}}</h1>

mutations状态修改

在vuex中如果想要修改数据  不能直接修改  而是要通过mutations来进行修改  mutations是一个属性  其中有n和方法就是一个修改的动作

let homem={
    state: {//就是这个仓库中存放数据的地方

        name:"我是home的数据",
      
       
    
      },
    //   在vuex中如果想要修改数据   不能直接修改  
    //   而是要通过 mutations来进行修改  
    //   mutations 是一个属性  
    //   其中有n个方法  每个方法就是一个修改的动作
      mutations: {
        //   state 形参就是上面的state数据源
        // payload 提交载荷  后续调用的时候传递进来的参数 
          upname(state){
            state.name="呵呵!!!!"
          }
      },
      actions: {
      },
}

export default homem

在组建中触发这个修改  commit(“你要触发的mutations的名字”)

在组件中使用函数  来调用this.$store.commit()修改

 <button @click="fun()">点我修改</button>
  
  
  methods:{
    fun(){
      // 使用commit()调用mutations 修改state
      this.$store.commit("upname")
    }
  }

总结  在vuex中使用commit调用mutations 来修改state的数据

payload 载荷

就是用来接收调用mutations的时候传递进来的数据

 homedata(state,payload){
            state.name=payload.text
  }

在组件中使用conmmit的时候传递第二个参数

fun(){
      // commit中传递了第二个参数   那么这个参数会被mutations的payload接收
        this.$store.commit("homedata",{text:"我是paylad接收的数据"})
    }

actions用来触发异步操作

action也是vuex的一个属性  作用就是用来在vuex中触发异步操作  它里面也是有n个方法 每个方法就是一个触发异步操作的动作

1.创建actions并且写入触发的动作

actions: {
        //   创建触发异步的动作
        // context就是代表$store
        // payload 载荷接收外部的数据
        demolink(){
            // 调用异步操作
            console.log("我触发了异步操作");
        }
      },

2.在页面触发数据请求 dispatch(“actions的名字”)

funb(){
      this.$store.dispatch("demolink")
    }

数据请求的闭环操作

1.需要模拟数据就新建mockjs  写好数据请求与拦截器

2.我们需要在组件页面通过dispath()来处罚一个vuex的actions来调用一个请求

<template>
  <div>
    <h1>数据请求的闭环操作</h1>
  </div>
</template>

<script>
export default {
  // 1.在页面加载完毕后自动使用生命周期的钩子调用 dispatch 来触发vuex的调用异步操作
  mounted(){
    this.$store.dispatch("demoaxios")
  }
}
</script>

<style>

</style>

3.来到vuex中创建对应的modules并且在vuex文件中引用调用  方可使用模块

创建模块

let aboutm={
    state: {
    },
    mutations: {
    },
    actions: {
    }
}
export default aboutm

使用模块

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)
// 2.引用创建的vuex模块
import aboutm from "./modules/aboutm.js"
export default new Vuex.Store({
  state: {
  },
  mutations: {
  },
  actions: {
  },
  modules: {
    // 3.调用模块
    aboutm
  }
})

4.在vuex的actions中创建对应的异步触发方法

let aboutm={
    state: {
    },
    mutations: {
    },
    actions: {
        // 4创建 异步触发的任务动作
        demoaxios(){
           
        }
    }
}
export default aboutm

5.在模块中引用  使用我们封装好的异步请求 进行数据请求

// 5.先引用数据请求封装
import getlink from "@/api/getapi.js"
let aboutm={
    state: {
    },
    mutations: {
    },
    actions: {
        // 4创建 异步触发的任务动作
        demoaxios(){
            // 6 调用封装的请求  进行数据请求
            getlink("/data/mock/userlist").then((ok)=>{
                console.log(ok.data)
            })

        }
    }
}
export default aboutm

6.把请求来的数据 通过commit传递到mutations上

// 5.先引用数据请求封装
import getlink from "@/api/getapi.js"
let aboutm={
    state: {
    },
    mutations: {
    },
    actions: {
        // 4创建 异步触发的任务动作
        // 7.创建context形参
        demoaxios(context){
            // 6 调用封装的请求  进行数据请求
            getlink("/data/mock/userlist").then((ok)=>{
                console.log(ok.data)

                // 8把请求来的数据交给mutations来修改state
                context.commit("uparr",{data:ok.data})
            })

        }
    }
}
export default aboutm

7.在mutations中进行state的修改  并且在state中也创建数据

// 5.先引用数据请求封装
import getlink from "@/api/getapi.js"
let aboutm={
    state: {
        // 11.新建状态数据
        arr:[]

    },
    mutations: {
        // 9.新建mutations
        uparr(state,payload){
            // 10修改state的数据  根据payload的值(payload的值就是请求来的数据)
            state.arr=payload.data
        }
    },
    actions: {
        // 4创建 异步触发的任务动作
        // 7.创建context形参
        demoaxios(context){
            // 6 调用封装的请求  进行数据请求
            getlink("/data/mock/userlist").then((ok)=>{
                console.log(ok.data)

                // 8把请求来的数据交给mutations来修改state
                context.commit("uparr",{data:ok.data})
            })

        }
    }
}
export default aboutm

8.在组件中读取请求过来的state数据

<template>
  <div>
    <h1>数据请求的闭环操作</h1>
    <!-- 13.展示 -->
    {{newarr}}
  </div>
</template>

<script>
export default {
  // 1.在页面加载完毕后自动使用生命周期的钩子调用 dispatch 来触发vuex的调用异步操作
  mounted(){
    this.$store.dispatch("demoaxios")
  },
  // 12.读取state的数据
  computed:{
    newarr(){
      return this.$store.state.aboutm.arr
    }
  }
}
</script>

<style>

</style>

slot--槽口/插槽

引子

组件在被调用的时候 我们知道组件的本质是自定义标签   标签是可以在内部插内容的  组件可以

默认情况下不可以

槽口是什么?

用来混合父组件与子组件自己的模板(就是可以在组件被调用的时候 向其内部插入新的dom节点)槽口也是组件提高复用的技术之一 props如果是只能向组件内部插入数据的话 那么槽口就是可以向组件内容部插入新的dom节点

基础用法

默认情况在组件是一个自定义标签 但是在组件被调用的时候不能直接插入dom节点 所以在这个时候需要给组件内部设置一个插槽 来接收外部插入的数据

语法

<slot></slot>

 <div>
      zizizizizziizziz
       <slot></slot>
  </div>

上面这种写法 后期插入的内容多个就不好维护了 所以在开发的时候使用的很少

具名槽口

带有名字的槽口  给槽口在定义的时候起个名字

语法:

在定义的时候     <slot name="给槽口起个名字随便写"></slot>

在插入内容的时候:

​                            <组件>

​                                        <p slot="你要插入的slot的namne"></p>

​                            </组件>

子组件

<template>
  <div>
      zizizizizziizziz
      <div class="red">
           <slot name="xiaoming"></slot>
      </div>
      
       <hr>
       <div class="yellow">
            <slot name="xiaohong"></slot>
       </div>
      
  </div>
</template>

<script>
export default {

}
</script>

<style scoped>
    .red>h1{
        color:red;
    }
    .yellow>h1{
        color:yellow;
    }
</style>

父组件

<template>
  <div>
      fufufufuffufufu
      <Sz>
          <h1 slot="xiaohong">插入内容1</h1>
          <h1>插入内容2</h1>
          <h1>插入内容3</h1>
          <h1>插入内容4</h1>
          <h1 slot="xiaoming">插入内容5</h1>
          <h1>插入内容6</h1>
          <h1>插入内容7</h1>
          <h1>插入内容8</h1>
          <h1 slot="xiaoming">插入内容9</h1>
          <h1>插入内容0</h1>
      </Sz>
    
  </div>
</template>

<script>
import Sz from "./slotzi.vue"
export default {
    components:{
        Sz
    }
}
</script>

<style>

</style>

路由---router

传统的项目怎么切换跳转页面?

1.新建很多的html文件

2.使用 标签的方式进行跳转(a标签) 或者使用js的方式进行跳转(window.location.href )

传统的项目称之为 多页面项目

路由基本概念

根据url的不同来渲染不同的组件页面

SPA -- 单页面应用 在用户切换页面的时候 没有那种传统页面的白屏问题 提高了用户的体验

路由基本创建

vue-cl自动创建

在创建脚手架的时候 选择自定义 在选择Router 即可

在创建完项目之后 会在src中多了两个文件夹

router ---》 当前文件夹就是配置路由的文件夹

views ---》 当前文件夹就是来写路由页面组件的

带有路由的空项目怎么办?

1.删除components里面的helloword.vue 与views里面的home.vue about.vue文件

2.views下新建你所需要的组件页面

3.需要配置路由规则 去router下的index.js中配置

(3-1)引用你所想要的页面 到index.js下 import from

(3-2) 在index.js的数组对象中 进行规则的配置

// 引用vue
import Vue from 'vue'
// 引用vue的路由功能模块
import VueRouter from 'vue-router'
// 引用你要配置的路由页面
// @ 只要在路径中出现  无论是在那个层级  只要写@就指向src
import Home from "@/views/home.vue"
import Jingxi from "@/views/jingxi.vue"
import Phone from "@/views/phone.vue"
import Shop from "@/views/shop.vue"
import User from "@/views/user.vue"
// 在vue中 使用  vue路由
Vue.use(VueRouter)

// 配置路由规则的地方
const routes = [
  // 配置路由规则
  {
    path: '/home', //url的路径
    name: 'home',//给这个规则起个名字
    component: Home //根据上后面的path路径 所渲染的组件页面
  },
  {
    path: '/jingxi', //url的路径
    name: 'jingxi',//给这个规则起个名字
    component: Jingxi //根据上后面的path路径 所渲染的组件页面
  },
  {
    path: '/phone', //url的路径
    name: 'phone',//给这个规则起个名字
    component: Phone //根据上后面的path路径 所渲染的组件页面
  },
  {
    path: '/user', //url的路径
    name: 'user',//给这个规则起个名字
    component: User //根据上后面的path路径 所渲染的组件页面
  },
  {
    path: '/shop', //url的路径
    name: 'shop',//给这个规则起个名字
    component: Shop //根据上后面的path路径 所渲染的组件页面
  },
 
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

手动创建

路由导航

标签方式----声明式导航

使用 router-link这个标签来完成页面的跳转 其中有个to属性就是 你要去哪里的路径

<template>
  <div class="bar">
      <!-- 声明式导航 -->
      <router-link to="/home">首页 </router-link>
      <router-link to="/jingxi">惊喜 </router-link>
      <router-link to="/phone">手机 </router-link>
      <router-link to="/shop">购物 </router-link>
      <router-link to="/user">我的 </router-link>
  </div>
</template>

声明式导航选中样式类

每当我们选中那个声明式导航之后 vue会自动给这个导航添加一个router-link-active的类名 那么我们就可以根据这个动态的类名添加样式

js的方式--- 编程式导航

1.跳转 this.$router.push("/去哪里的路径")

2.替换 this.$router.replace("/替换的路径")

fun(){
            this.$router.push("/home")
        }

3.前进与后退 this.$router.go() 正数 前进 负数 后退

404页面

就是当路径没有匹配页面的时候 需要给用户一个错误页面的提示

 // 404页面是一个错误提示页面  我们必须把路由规则配置放在最后
  {
    path: '*',
    name: 'Err',
    component: Err
  },

路由规则也是由优先级的 配置越靠前 优先级越高  

重定向----redirect

重(重新)定(定位)向(方向路径)

在用户第一次进入的时候  我们需要把用户的路径重新定位到 首页

在路由规则中进行重定向的设置

const routes = [

  {
    path: '/home',
    name: 'Home',
    component: Home
  },
  {
    path: '/shop',
    name: 'Shop',
    component: Shop
  },
  {
    path: '/user',
    name: 'User',
    component: User
  },

  // 重定向 /默认路径
  {path:"/",redirect:"/home"},


  // 404页面是一个错误提示页面  我们必须把路由规则配置放在最后
  {
    path: '*',
    name: 'Err',
    component: Err
  }
  ]

路由出口

router-view 来设置路由出口 就是根据路由的规则 显示规则所匹配的路由组件页面 显示的位置

多级路由/嵌套路由

在应用开发的过程中通常会出现在一个页面中嵌套另外一个局部页面进行局部跳转的时候

1.新建二级路由页面

2.在router下的index.js中先引用二级路由

3.配置二级路由的规则

(3-1)要配置规则先要确定规则写在那 二级路由的规则写在一级路由的规则内 使用children来标识

path可以是 /二级路由

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/home.vue'
import Shop from '../views/shop.vue'
import User from '../views/user.vue'
import Err from '../views/err.vue'

// 二级路由
import Era from "@/views/er/era.vue"
import Erc from "@/views/er/erc.vue"
import Erd from "@/views/er/erd.vue"

Vue.use(VueRouter)

const routes = [

  {
    path: '/home',
    name: 'Home',
    component: Home
  },
  {
    path: '/shop',
    name: 'Shop',
    component: Shop
  },
  {
    path: '/user',
    name: 'User',
    component: User,
    // 设置二级路由
    children:[
      {
        path: '/era',
        name: 'era',
        component:Era
      },
      {
        path: '/erc',
        name: 'erc',
        component:Erc
      },
      {
        path: '/erd',
        name: 'erd',
        component:Erd
      },
    ]
  },

  // 重定向 /默认路径
  {path:"/",redirect:"/home"},


  // 404页面是一个错误提示页面  我们必须把路由规则配置放在最后
  {
    path: '*',
    name: 'Err',
    component: Err
  }


  // {
  //   path: '/about',
  //   name: 'About',
  //   // route level code-splitting
  //   // this generates a separate chunk (about.[hash].js) for this route
  //   // which is lazy-loaded when the route is visited.
  //   component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  // }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

path也可以是 不带/

{
    path: '/user',
    name: 'User',
    component: User,
    // 设置二级路由
    // path不带/
    children:[
      {
        path: 'era',  // path不带/
        name: 'era',
        component:Era
      },
      {
        path: 'erc',  // path不带/
        name: 'erc',
        component:Erc
      },
      {
        path: 'erd',  // path不带/
        name: 'erd',
        component:Erd
      },
    ]
  },

4.设置二级路由的路由出口 在对应的一级路由页面中进行设置 使用router-view

 <div>
      <router-view></router-view>
     user
  </div>

5.设置二级路由的导航

方式1 在设置二级路由规则的时候 path带/来设置的时候 二级路由的路径是 /二级路由

 <div>
         <router-link to="/era">era</router-link>
         <router-link to="/erc">erc</router-link>
         <router-link to="/erd">erd</router-link>
     </div>

方式2 在设置二级路由规则的时候 path不不不不不不不不不不不不不不带/来设置的时候

二级路由的路径是 /一级路由/二级路由

 		 <router-link to="/user/era">era</router-link>
         <router-link to="/user/erc">erc</router-link>
         <router-link to="/user/erd">erd</router-link>

路由传参/动态路由匹配

在vue中需要把数据从一个页面传递到另外一个页面的时候

方式

params方式

1.在需要接收数据的路由规则中设置接收参数

 {
    path: '/shop/:xiaoming',//设置接收参数
    name: 'Shop',
    component: Shop
  },

2.发送

声明式

<router-link :to="{name:'你要去的路由的name',params:{设置的接收参数:'传递的数据'}}"></router-link>

<template>
  <div>
      home
      <!-- <router-link :to="{name:'你要去的路由的name',params:{设置的接收参数:'传递的数据'}}">点我把数据使用声明式方式传递到shop中</router-link> -->
      <router-link :to="{name:'Shop',params:{xiaoming:'呵呵我是传递的额数据'}}">点我把数据使用声明式方式传递到shop中</router-link>
  </div>
</template>

编程式

methods:{
        fun(){
            this.$router.push({name:'Shop',params:{xiaoming:'1111呵呵我是传递的额数据'}})
        }
    }

3.接收

直接使用this.$route.params.xxxx

<div>
   shop----{{this.$route.params.xiaoming}}
  </div>

query方式

1.发送

语法:

 <!-- query传参可以使用name 或者 path -->
        <router-link :to="{name:'Shop',query:{xiaoming:'我是数据'}}">点我声明式传参query</router-link>
        <router-link :to="{path:'/shop',query:{xiaoming:'我是数据'}}">点我声明式传参query2222</router-link>

query和params的区别

语法上区别

 query方式传参分为两步 发送数据的时候可以使用name还可以使用path来进行  接收的时候使用this.$route.query.xxxxxx

params 传参需要三步    并且在发送数据的时候只能是name   接收的时候使用this.$route.params.xxxx

url展示上    params在url上面只展示数据    相对来说传参安全一点      queryurl  有key还有val 相对来说不安全

$router与$route区别

$router对象: 是vue路由的对象 他是路由实例 他是一个路由全局对象 包含了与路由相关的关键属性

$route对象 : 是跳转到指定路由的局部对象 一个路由页面就有一个$route对象

路由模式

在vue中路由模式使用 mode来进行指定

1.hash模式 默认模式 你不写就是hash模式

2.history模式

区别hashhistory
url展示上url带#url不带#
浏览器兼容性兼容性好html5新特性所以对ie兼容性不好
浏览器刷新刷新之后正常显示上线之后刷新页面丢失

路由守卫/路有钩子/导航守卫

就是在路由跳转的时候触发的钩子函数

全局守卫

全局前置

在路由跳转的时候 进入下一个路由之前触发

beforeeach

to     去哪里
from   从哪里来
next    下一步  必须有

router.beforeEach((to,from,next)=>{
  console.log(to)
  console.log(from)
  next()
})

全局后置

在路由跳转的时候 进入下一个路由后触发

aftereach()

路由独享守卫

仅仅只会对一个路由生效

beforeRouterEnter()

to 去哪里

from 从哪来

next 下一步

{
    path: '/user',
    name: 'user',
    component: () => import('../views/user.vue'),
    // d当前路由生效
    beforeEnter(to,from,next){
      console.log(to)
      console.log(from)
      next()
    }

组件内守卫

beforeRouteEnter() 进入当前组件的时候调用

beforeRouteLeave() 离开当前组件的时候调用

<template>
  <div>
  shop
  </div>
</template>

<script>
export default {
    // 组件内守卫
    beforeRouteEnter(to,from,next){
        console.log("进来了");
        console.log(to);
        console.log(from);
        next()
    },
    beforeRouteLeave(to,from,next){
        console.log(to);
        console.log(from);
        if(confirm("您确定离开吗")){
            next()
        }else{
            next(false)//下一步我什么都不干
        }
     }
}
</script>

<style>

</style>

扩展--懒加载

路由懒加载 路由页面按需加载

因为在传统的vue项目中如果使用了路由可能会出现 首页白屏问题 也会造成很大的性能问题

1.import导入

component: () => import('你要显示路由的页面路径')

 2.异步组件

 component: (resolve) => require(['你要显示的路由页面路径即可'], resolve),

扩展--路由的更多属性

meta 路由记录/路由元信息

我们给路由的规则中添加一个meta的对象 那么就可以在其中存储一些信息 在页面进行使用

{
    path: '/phone',
    name: 'phone',
    component: () => import('../views/phone.vue'),
    // meta元信息
    meta:{
      text:"我是路由中的meta信息"
    }

在当前页面中使用这个meta信息

this.$route.meta.xxx

<template>
  <div>
      phone---{{this.$route.meta.text}}
  </div>
</template>

<script>
export default {

}
</script>

<style>

</style>

在组件内获取路由全部规则

this.$router.options.routes

前后端数据交互

数据请求在vue中有多种方式

1.原生或者jquery的ajax

2.vue-resource vue官方出品 vue2x之后已经停止更新了

3.axios 是一个第三方的数据请求 他是基于XHr对象的 但是在XHR对象之上使用promise进行了封装 让他更符合当下的主流语法规范

4.fetch请求 是es最新的规范

axios

因为是第三方的所有需要先下载 npm install --save axios

基本使用

axios.get() axios.post()

axios()

<template>
  <div>
    <h1>基本axios的使用</h1>
    <button @click="fun()">点我发送请求</button>
  </div>
</template>

<script>
import axios from "axios"
export default {
  methods:{
    fun(){
      // 开始请求数据
      axios({
        url:"http://api.artgoer.cn:8084/artgoer/api/v1/user/324380/v3/topic/topicHomeByLabel?pageIndex=1&token=b544cd63-6d42-46fe-a96c-3cf96bae3113&topicId=62187",
        // 注意单词
        method:"GET"
      }).then((ok)=>{
        console.log(ok)
      }).catch((err)=>{
        console.log(err);
      })
    }
  }
}
</script>

<style>

</style>

数据请求封装与拦截器

数据请求封装

公司中就不一定是按照咱们所学的方式进行封装了  因为有的公司可能在封装的时候就是单纯的把请求提取出来

有一些可能使用promise来进行封装   有一些公司可能是用async 来进行封装 

我们需要认识一个文件夹    **api  这个文件夹通常百分之90都是用来存放数据请求的**

使用promise来进行封装(提高了复用性  让自己写的代码叼一点)

api文件夹中进行封装

import axios from "axios"
// 在其中进行请求的封装
let getlink=(url)=>{
    // resolve成功数据会交给then来接收     reject失败的数据会交给catch来接收
  return new Promise((resolve,reject)=>{
        // 就来写你的异步操作
        axios({
            url,
            method:"GET"
        }).then((ok)=>{
            resolve(ok)
        }).catch((err)=>{
            reject(err)
        })
    })
}
// 千万不要忘了
export default getlink

在组件中引用使用

<template>
  <div>
      <h1>使用封装来进行请求</h1>
  </div>
</template>

<script>
import getlink from "@/api/getapi.js"
export default {
    created(){
  getlink("http://api.artgoer.cn:8084/artgoer/api/v1/user/324380/v3/topic/topicHomeByLabel?pageIndex=1&token=b544cd63-6d42-46fe-a96c-3cf96bae3113&topicId=62187").then((ok)=>{
            console.log(ok)
        }).catch((err)=>{
            console.log(err)
        })
    }
}
</script>

<style>

</style>

axios拦截器

如果需要编写拦截器 我们需要创建一个util文件夹工具文件夹(与项目业务无关的一些代码 但是有了这些代码可以提高效率)

什么是拦截器?

拦截请求的一个技术

有些情况下 我们需要在每次请求的时候都要携带一个参数(比如:用户的登录状态信息) 那么我们就可以放到拦截器中 因为每次请求拦截器都会先拦截到 让后才去发送请求 那么我们就可以在拦截器中吧这些参数信息进行统一的添加 不需要每次请求都写一遍

1.请求拦截 我们在发送请求的时候 他会拦截

2.相应拦截 服务器把数据给我们的时候先被拦截器所拦截

// 就是用来存放拦截器的
// 引用axios
import axios from "axios"
// 1创建axios实例并且交给一个变量方便使用\
const service = axios.create()

// 2.创建请求与相应拦截
// 添加请求拦截器
service.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么
    return config;
  }, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
  });

// 添加响应拦截器
service.interceptors.response.use(function (response) {
    // 对响应数据做点什么
    return response;
  }, function (error) {
    // 对响应错误做点什么
    return Promise.reject(error);
  });


// 千万不要忘了暴露
export default service

请求封装调用拦截器

// 数据封装于拦截器
import service from "@/util/service.js"
let getblink=(url)=>{
    return new Promise((resolve,reject)=>{
        // 使用request请求
        service.request({
            url,
            method:"GET"
        }).then((ok)=>{
            resolve(ok)
        }).catch((err)=>{
            reject(err)
        })
    })
}

export default getblink

mockjs 模拟数据

在前后端分离开发的过程中 有的时候后台数据在我们编写前台的时候还没有写好 我们可以在后台没有准备好的时候 先试用模拟数据创建数据 然后用请求请求我们的模拟数据进行展示、

数据json json是键值对 但是后台在创建数据的时候 这个key起什么名字 后台可能会问你咱俩一起对下接口数据吧(理想派 我们可以把我们的模拟数据的key来进行和他沟通) 他自己默默的把后台数据写好了 然后给你了(沉默派 你不知道数据里面的东西代表什么 你的嘴要甜一点 发信息说 哥 我刚来公司 咱们公司的流程可能不太熟 您看 某某key是个什么意思 你可以问题要接口文档 你也可以过去问他)

使用

1.mockjs是一个第三方的模拟数据的库

npm install --save mockjs (注意单词没有点)

2.新建一个mock文件夹 这个文件夹今后在工作中通常就是写模拟数据的 在其中创建一个存放模拟数据的文件夹 与编写代码的index.js

3.新建模拟数据 是以.json结尾的文件

4.在index.js来编写 mockjs的代码

let Mock=require("mockjs")
// Mock.mock("随便写一个请求的接口地址","请求方式",require("你的模拟数据路径"))
Mock.mock("/data/list","GET",require("./data/demo.json"))

5.在main.js中引用mock

import Vue from 'vue'
import App from './App.vue'
import router from './router'

// 引用mock
require("./mock")



Vue.config.productionTip = false

new Vue({
  router,
  render: h => h(App)
}).$mount('#app')

注意 一定要重启项目

mixins 混入

多个组件中都要使用一些相同的方法

混入就是vue组件中一个提高组件复用性的一个技术 他可以让多个组件中重复使用的方法 等内容进行提取出来然后在想使用的地方直接使用

分类

1.全局混入

慎用 因为会污染整个项目

1.文件夹mixins与文件的创建 并且全局混入的文件写法和局部混入相同

2.引用调用的时候需要在main.js中引用调用 剩下在任何组件中就可以直接使用混入的内容了

// 1.混入引用
import xiaoming from "./mixins/xiaoming.js"
// 2.调用
Vue.mixin(xiaoming)

2.局部混入

1.新建文件夹mixins文件 来存放我们提取出来的内容 创建js文件来进行存放

2.在js中创建一个对象写入你想复用的内容

let xiaoming={
    // 提取出想复用的方法
    methods:{
        fun(){
          console.log("你好");
        }
      }
}

export default xiaoming

3.在想使用的组件中引用调用使用

<template>
  <div>
    <h1>混入的使用</h1>
    <!-- 3.直接使用混入的方法 -->
    <button @click="fun()">点我调用函数</button>
    <button @click="funb()">点我调用函数</button>
  </div>
</template>

<script>
// 1.引用
import xiaoming from "@/mixins/xiaoming.js"
export default {
//  2.调用  使用mixins来进行调用   mixins是一个数组
  mixins:[xiaoming]
}
</script>

<style scoped>
  div{
    font-size:0.2rem;
  }
</style>

混入中除了函数 生命周期 计算属性等也可以 data也可以

自定义指令----directives

在现有指令不够的情况下我们可以创建自定义指令

指令就是html的属性 属性就是给html添加特殊的功能

写在与data methods等同级的位置

语法:

direactives:{
	自定义指令的名字:{
		自定义指令的钩子函数(形参就是你绑定这个自定义指令的当前dom元素){
			你的逻辑
		}
	},
	自定义指令的名字:{
	
	},
}
<template>
  <div>
      自定义自定义指令
      <input type="text">
      <input type="text" v-xiaoming>
      <input type="text">
      <input type="text">
      <input type="text">
      <input type="text">
      <input type="text">
      <input type="text" v-xiaohong>
  </div>
</template>

<script>
export default {
    directives:{
        xiaoming:{
            // 自定义指令的钩子函数
            // bind 指令绑定到元素之上只执行一次
            // inserted 是我们百分之90以上使用的  绑定的这个指令的元素 在页面展示的时候调用
            // update 当组件节点更新的时候调用
            // componentUpdated 指令所在的组件节点以及所有的子节点更新完毕之后调用
            // unbind 当前dom被移除的时候调用
            inserted(el){
                el.focus()
            }
            
        },
        xiaohong:{
            inserted(el){
                el.style.backgroundColor="red";
            }
        }
    }
}
</script>

<style scoped>
    div{
        font-size: 0.2rem;;
    }
</style>

ref

在vue中默认是没有dom操纵的 有些时候我们就是需要使用dom的操纵 那么就可以使用vue提供的ref来进行

基本使用

<template>
  <div>
      <h1>ref的基本使用</h1>
      <!-- 1.给你要操作的dom起个名字    ref="你起的名字" -->
      <input type="text" ref="demoinput">
      <button @click="fun()">点我得到输入框的值</button>
  </div>
</template>

<script>
export default {
    methods:{
        fun(){
            // 2.找到ref对应的内容进行操纵
            console.log(this.$refs.demoinput.value)
        }
    }
}
</script>

<style scoped>
    div{
        font-size:0.2rem;
    }
</style>

扩展--$set以及原理

你在开发中有没有遇见过数据改变了但是视图没有改变的问题 你是怎么解决的?

<template>
<div>
    <h1>$set</h1>
    <h1>{{obj.name}}</h1>
    <button @click="obj.name='haha'">点我修改</button>
    <h1>--------------------------------</h1>
    <h1>age:{{obj.age}}</h1>
    <button @click="fun()">点我添加一个age</button>
</div>
</template>

<script>
export default {
    data(){
        return {
            obj:{
                name:"xixi"
            }
        }
    },
    methods:{
        fun(){
            this.obj.age=18
            console.log(this.obj.age);
        }
    }
}
</script>

<style scoped>
div{
    font-size: 0.2rem;
}
</style>

出现的场景是 如果我们在vue中向data定义的数组获取对象中添加新的属性的时候 就会出现数据变了但是视图没有发生改变

原因 :因为双向绑定中 依赖数据劫持(object.defineProperty()) 数据劫持有一个非常大的bug 他只会劫持初始化的时候data有的数据 但是当程序运行之后 在给data的属性插入新的内容的时候 由于数据劫持劫持不到 就没有双向绑定了 没有双向绑定了 当然数据变了视图不会发生改变

$set的使用

所以我们为了解决这种数据变视图不发生改变的问题 我们使用$set来解决

语法: this.$set( 你要操纵的数据,新增的key,新增的val )

  fun(){
            // this.obj.age=18
            // $set来进行添加新属性
            this.$set(this.obj,"age",666)
            console.log(this.obj.age);
        }

动态组件

多个组件使用同一个挂载点(component)并且动态组件

挂载点这个挂载点放在页面的那个地方 那么动态切换的内容就在哪里展示:

<component :is="当前挂载点需要显示那个组件"></component>

1.新建多个组件

2.在需要动态显示这多个组件的位置使用 来设置挂载点 并且引用调用 你要使用的组件到当前页面中

<component :is="当前挂载点需要显示那个组件"></component>

3.创建变量 在变量中设置多个组件初始化显示的内容

  data(){
    return{
      com:"你要初始化显示的组件名"
    }
  },

4.把这个变量插入到挂载点的is上

<component :is="你创建的变量"></component>

5.想动态切换 只需要 改变 你保存显示组件的那个变量即可

keep-alive

引子

我们新建的路由页面 用户在路由页面中填写内容之后 在进行路由的切换 会发现数据不见了

同样的我们在使用动态组件进行切换的时候 会和路由一样 数据丢失

出现的原因

因为路由或者动态组件 在切换的时候 vue会在每次切换的过程中 对切换的组件进行实例的重新创

keep-alive

keep-alive 使用他可以把组件中的状态保留在内存中 防止组件重复dom渲染 减少了在切换的时候性能上面损耗 提高用户体验

语法 :

<keep-alive>
    你要保存状态的组件放进去
<kepp-alive>

属性

在vue2.1之后 kepp-alive加入了新的特性 引进了两个属性

incloude 你要缓存谁

      <keep-alive include="Da,Dc">
        <component :is="com"></component>
      </keep-alive>

excloude 你不缓存谁

  <keep-alive exclude="Da">
        <component :is="com"></component>
  </keep-alive>

incloude 与 excloude 同时都写了听谁的?

excloude的优先级高

钩子函数keep-alive

这两个钩子函数需要写在被keep-alive管理的组件之内 以data methods等同级

activated 进入被keep-alive管理的组件时候调用

deactivated 离开被keep-alive管理的组件时候调用

nextTick

vue的响应式 不是在 数据变化了之后 DOM立即改变 而是按照一定的策略进行dom的更新。

<template>
  <div>
      <!-- 数据变了   页面的dom不是立即改变 -->
      <h1 ref="demoh">{{text}}</h1>
    <button @click="fun()">点我修改</button>
  </div>
</template>

<script>
export default {
    data(){
        return {
            text:"你好么么哒!!!"
        }
    },
    methods:{
        fun(){
            this.text="我变了!!!"
            // 我在数据修改之后 直接读取dom看看变了没有变就知道了
            console.log(this.$refs.demoh.innerText)
        }
    }
}
</script>

<style>

</style>

数据修改异步说明

简单来说 vue在数据修改之后 视图是不会立即更新 而是等同一事件循环中的所有数据都变化了 之后 在同一进行页面视图的更新

原理:

1 vue先进行数据的修改 是一个同步任务 同一事件循环上的所有同步任务 进行一个个的执行 但是这个时候 还没有涉及到dom的任何操作

2.vue开启一个异步列队 把在上面事件循环中的数据变化进行异步的缓冲

3 同步任务执行完毕 开始执行异步的列队任务 , 更新dom

什么是nextTick

会在dom加载完毕之后 立即执行的一个方法

<template>
  <div>
      <h1>nextTick</h1>
      <h1 ref="demoh">{{text}}</h1>
  </div>
</template>

<script>
export default {
    created(){
        // console.log(this.$refs.demoh.innerText);
        this.$nextTick(()=>{
            console.log(this.$refs.demoh.innerText);
        })
    },
    data(){
        return {
            text:"你好!!!!!"
        }
    }
}
</script>

<style>

</style>

扩展---浏览器自动开启与修改端口

在根路径下创建vue.config.js 写入open 自动开启

module.exports={
    devServer:{
        open:true,//自动开启浏览器
    }
}

修改端口

module.exports={
    devServer:{
        open:true,//自动开启浏览器
        port:8888 //修改端口
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值