vue基础知识点

前端与后端是什么?

前端:数据展示

后端:数据处理

依赖包从哪里来?

npm管理

npm 的服务器是在国外的 国内下载很慢

淘宝镜像: npm i -g cnpm --registry=https://registry.npm.taobao.org

jquery :

1.cd 到你要下载的文件夹下

2.初始化 npm init -y

3.下载 npm install --save jquery

4.修改下载版本

4-1 在下载的时候直接指定版本 npm install --save jquery@版本号

4-2 可以在项目的package.json文件进行修改 在项目下使用 npm install 进行重新下载

框架是什么?

与业务无关的代码块

业务:就是项目的功能

框架优缺点

简化了项目的复杂度 提高了项目的价值

缺点:你要学习一套新的语法

html属性是什么?

扩展html标签的功能

语法:

属性写在html的 开标签中 属性=“属性值 ” 多个属性用空格隔开

npm 的镜像源切换成淘宝镜像

npm config set registry https://registry.npm.taobao.org

promise

三大状态

等待 pending

成功 resolve-----------then()

失败 reject-------------catch()

promise.all

如果我相同时执行100个异步操作怎么办?

使用promise.all()

promise是用来解决异步回调地狱问题的解决方案 他可以把难以阅读的异步代码 变成可读性更强的代码

promise.all() 把多个相同业务异步操作 包装成一个

Promise.all可以将多个Promise实例包装成一个新的Promise实例。同时,成功和失败的返回值是不同的,成功的时候返回的是一个结果数组而失败的时候则返回最先被reject失败状态的值(不管是那个失败了一个成功都不会返回 只会返回第一个失败的内容)。

<!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>
</head>
<body>
    <script>
        let p1=Promise.resolve("1");
        let p2=Promise.reject("2");
        let p3=Promise.reject("3");
​
        // Promise.all([第一个,第二个,......n]).then((ok)=>{
        //     console.log(ok);
        // })
​
        Promise.all([p1,p2,p3]).then((ok)=>{
            console.log(ok);
        }).catch((err)=>{
            console.log(err)
        })
    </script>
</body>
</html>

postman

接口测试工具

async与await

是什么?

async 异步的意思 await就是async 与wait的简写 等待异步完成

用法要求

await 必须在async中使用 不能单独使用

async是什么?

async包装一个函数那么这个函数就会返回换一个promise对象(async就是promise的语法糖----用简单的语法来简化之前复杂的内容)

 async function fun(){
            return "你好"
        }
                    
        console.log(fun())

async包装的函数可以返回一个promise对象 所以我们可以使用then来得到结果

<!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>
</head>
<body>
    <script>
       async function fun(){
            return "你好"
        }
​
        // function fun(){
        //     return new Promise((resolve)=>{
        //         resolve("你好")
        //     })
        // }
​
​
​
        fun().then((ok)=>{
            console.log(ok)
        })
    </script>    
</body>
</html>

await 是什么?

await 就是等待异步 await就是等待一个表达式 这个表达式的结果就是promise的成功内容(awati拿到的东西就是async包装函数的promise成功返回值 await的作用就是替代.then)

  function getlink(url){
            return new Promise((resolve,reject)=>{
                service.request({
                    url,
                    method:"GET",
​
                }).then((ok)=>{
                    resolve(ok)
                }).catch((err)=>{
                    reject(err)
                })
            })
        }
       async function getlink(){
             return await service.request({
                    url,
                    method:"GET",
​
                })
        }

优势

async 与 await 可以理解为异步操作的终极解决方案 相比于promise来说 优势就是在处理then的时候 进行了大大的简化 可以更加清晰的来描述一段代码 因为then过多是一个很烦人的事件 并且还可以用精简的语法简化了异步回调地狱

事件循环

事件循环引子

js在设计的初期 是一个单线程的 但是在处理一些等待事件教程或者是突发情况的时候 使用异步这个操作机制

事件循环分类

同步任务 正常的执行代码

异步任务 宏任务 (定时器) 微任务(优先级高 promise)

先执行同步代码 遇到异步操作就会把异步操作放到异步列队中 等同步执行完 在去异步列队中把所有的微任务取出来执行 最后执行宏任务

vue与react有啥区别?

不同点:

1.模板与jsx react使用jsx来描述页面 而vue使用template模板来描述 在vue中就可以使用标签的属性(指令)来完成一些操作

2.状态管理与对象属性 状态是react中最核心的概念 state在程序中是不能直接修改的而是使用setState来更新 但是在vue中使用data属性来描述数据

3.react Native vue没有 react有一个分支叫Native这个是用react的语法来写原生app的 但是vue没有

相同点:

1.都是js框架 他们都是专注于数据层面的框架

2.都有虚拟dom

3.都是组件话

4.都有props概念

vue

什么是vue

vue.js是现今最为主流的 前端 MVVM 框架 (更简单的来展示数据)

MVVM是什么?

M Model 模型-----》数据

V View 视图-----》用户可以看见的界面

Vm ViewModel 视图模型-----》数据与展示相分离 视图于模型之间的桥梁 用来关联

vue的核心

数据驱动与组件化

helloword

1.下载vue依赖

npm install --save vue

2.编写代码

<!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.js"></script>
</head>
<body>
    <!-- M 模型
    V 视图
    VM 视图模型 -->
​
        <!-- 1.创建v层 -->
        <div id="demoDiv">
            {{text}}
        </div>
​
        <script>
            // 2.vm层  就是vue实例
            new Vue({
                // 3.创建m层
                data:{
                    text:"你好么么哒"
                },
                el:"#demoDiv"
            })
​
        </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.js"></script>
</head>
<body>
    <div id="demoDiv">
        <h1>{{name}}</h1>
        <h1>{{age+2}}</h1>
        <h1>{{sex?"你好":"你坏"}}</h1>
        <h1>{{arr[2]}}</h1>
        <h1>{{love.userb}}</h1>
        <h1>{{text}}</h1>
        <h1>{{text.toUpperCase()}}</h1>
        <h1>{{text.toUpperCase().substr(1,4)}}</h1>
    </div>
    <script>
        new Vue({
            data:{
                name:"xixi",
                age:18,
                sex:false,
                arr:[1111,22222,33333,44444],
                love:{
                    usera:"aaaa",
                    userb:"bbbbb"
                },
                text:"abcdefghijk"
            },
            el:"#demoDiv"
        })
    </script>
</body>
</html>

渲染分类

vue 的核心就是可以使用简单简洁的模板语法来声明式的对数据进行展示。

原生js :命令式渲染 我们需要去命令我们的程序 你应该一步一步怎么走

vue框架 :声明式渲染 我们只需要告诉程序你要干什么 他就自己完成了

指令

指令概念

就是用v- 前缀的html特殊属性

指令的作用是什么?

在vue中 扩展html标签的功能

指令的语法

写在html的开标签中 并且 v-指令=“指令值” 多个指令用空格隔开

v-show

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

使用css的display来进行css的设置

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.js"></script>
</head>
<body>
​
    <div id="demoDiv">
        <h1>v-show</h1>
        <!-- 作用:控制元素的显示和隐藏
​
        使用css的display来进行css的设置
​
        true   显示       false  隐藏 -->
        <h1 v-show="bool">看我的显示和隐藏</h1>
    </div>
    <script>
        new Vue({
            data:{
                bool:true
            },
            el:"#demoDiv"
        })
    </script>
</body>
</html>

v-model

用于在表单元素上进行数据的双向绑定

<!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.js"></script>
</head>
<body>
​
    <div id="demoDiv">
       <h1>v-model</h1>
       <!-- 表单元素上双向绑定 -->
       <!-- 双向绑定  模型变视图变  视图变模型也会变-->
       <!-- 1.模型数据绑定到了视图之上 -->
       <!-- 2.视图的数据改变了 模型也会跟着变 -->
       <input type="text" v-model="text"/>
       <p>{{text}}</p>
    </div>
    <script>
        new Vue({
            data:{
               text:"你好么么哒"
            },
            el:"#demoDiv"
        })
    </script>
</body>
</html>

双向绑定的原理

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

双向绑定的原理

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

数据劫持:数据拦截 数据阻断 就是vm层会时时刻刻的监听者模型和视图中的数据当其中一个改变了 vm层就会收到通知(vm怎么收到的通知 通过数据劫持 Object.defineProperty() 他可以拦截 所绑定的对象数据 然后通过其中是的getter和setter方法来实现 读取与修改)

发布者订阅者 就是一个一对多的关系

v-on

就是在vue中绑定事件的指令 (在vue中不能直接使用事件 必须使用v-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.js"></script>
</head>
<body>
​
    <div id="demoDiv">
        <h1>v-on</h1>
        <button v-on:click="fun()">点我打印你好</button>
        <!-- 简写 -->
        <button @click="fun()">简写方式绑定事件</button>
      
    </div>
    <script>
        new Vue({
            data:{
             
            },
            el:"#demoDiv",
            // 函数需要写在与el  data同级的位置 使用methods来表示
            methods:{
              fun(){
                console.error("你好")
              }
            }
        })
    </script>
</body>
</html>

v-for

便利data数据 并且进行页面数据展示

语法:

v-for=" (v,i) in 你要便利的数据 "

v 就是便利出来的值

i 就是便利出来的下标

<!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.js"></script>
</head>
<body>
​
    <div id="demoDiv">
        <h1>v-for</h1>
        <ul>
            <li v-for="(item,index) in arr">{{item}}------{{index}}</li>
        </ul>
     
    </div>
    <script>
        new Vue({
            data:{
              arr:["VN","EZ","NOC","MF"]
            },
            el:"#demoDiv"
        })
    </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.js"></script>
</head>
<body>
​
    <div id="demoDiv">
        <h1>v-for</h1>
        <ul>
            <li v-for="(item,index) in arr">{{item}}------{{index}}</li>
        </ul>
        <table border="1">
​
            <tr v-for="(v,i) in obj">
                <td>{{v.name}}</td>
                <td>{{v.age}}</td>
            </tr>
​
        </table>
    </div>
    <script>
        new Vue({
            data:{
              arr:["VN","EZ","NOC","MF"],
              obj:[
                  {name:"xixi1",age:181},
                  {name:"xixi2",age:182},
                  {name:"xixi3",age:183},
                  {name:"xixi4",age:184},
                  {name:"xixi5",age:185}
              ]
            },
            el:"#demoDiv"
        })
    </script>
</body>
</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.js"></script>
</head>
<body>
​
    <div id="demoDiv">
        <h1>v-bind</h1>
        <a v-bind:href="ahref">{{atext}}</a>
        <!-- 简写 -->
        <a :href="ahref">{{atext}}</a>
    </div>
    <script>
        new Vue({
            data:{
                atext:"点我去百度",
                ahref:"http://www.baidu.com"
            },
            el:"#demoDiv"
        })
    </script>
</body>
</html>

v-if v-else v-else-if

v-if 判断当前内容是否加载

指令值: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.js"></script>
</head>
<body>
    <div id="demoDiv">
        <h1>v-if</h1>
        <input type="checkbox" v-model="bool"/>
        <h1 v-show="bool">看我是否显示v-show</h1>
        <h1 v-if="bool">看我是否显示v-if</h1>
​
    </div>
    <script>
        new Vue({
            el:"#demoDiv",
            data:{
                bool:true
            },
            methods:{
​
            }
        })
​
    </script>
</body>
</html>

v-if 与 v-show的区别

相同点 : 从用户的角度都是对内容可以隐藏

不同点 :v-show 是通过css来对元素进行显示和隐藏 但是v-if 是对dom进行添加和删除

v-show 通常使用在对安全性不高的地方 它在初始化的时候对性能有影响 在频繁切换的时候对性能比较友好

v-if 用在对安全性较高的地方 对初始化的性能比较友好 在频繁切换的时候对性能比较差

v-else

必须配合v-if来使用 不能单独使用

当v-if不符合的时候 v-else的内容显示

<!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.js"></script>
</head>
<body>
    <div id="demoDiv">
        <h1>v-else</h1>
        <h1 v-if="bool">请登录</h1>
        <!-- <p>我是站位的一个没用的内容</p> -->
        <h1 v-else>欢迎您尊敬的vip</h1>
​
    </div>
    <script>
    
        new Vue({
            el:"#demoDiv",
            data:{
               bool:false
            },
            methods:{
​
            }
        })
​
    </script>
</body>
</html>

v-else-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.js"></script>
</head>
<body>
    <div id="demoDiv">
        <h1>v-else-if</h1>
        <h1 v-if="num==1">111111111</h1>
        <h1 v-else-if="num==2">111111112</h1>
        <h1 v-else-if="num==3">111111113</h1>
        <h1 v-else>111111114</h1>
​
    </div>
    <script>
        new Vue({
            el:"#demoDiv",
            data:{
              num:222222
            },
            methods:{
​
            }
        })
    </script>
</body>
</html>

v-text

向网页中插入纯文本 {{}} 和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.js"></script>
</head>
<body>
    <div id="demoDiv">
        <h1>v-text</h1>
        
        <h1 v-text="text"></h1>
​
    </div>
    <script>
        new Vue({
            el:"#demoDiv",
            data:{
              text:"我是一段字符串"
            },
            methods:{
​
            }
        })
​
    </script>
</body>
</html>

小扩展---屏幕闪烁/屏幕闪动

就是因为网速或者是用户的设备加载过慢 在vue还没有渲染内容的是时候页面就显示了 可能在用户的界面中出现很多{{}}然后突然间 加载出来了页面由变得正常了

解决方式

1.v-text

2.v-cloak 在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>
    <!-- <script src="./node_modules/vue/dist/vue.js"></script> -->
    <style>
        [v-cloak]{
           display:none; 
        }
    </style>
</head>
<body>
    <div id="demoDiv" v-cloak>
        <h1>v-text</h1>
        
        <h1 v-text="text"></h1>
        <h1>{{text}}</h1>
​
    </div>
    <script>
        new Vue({
            el:"#demoDiv",
            data:{
              text:"我是一段字符串"
            },
            methods:{
​
            }
        })
​
    </script>
</body>
</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.js"></script>
</head>
<body>
    <div id="demoDiv">
        <h1>v-html</h1>
        
        <div>
            {{demohtml}}
        </div>
        <div v-html="demohtml"></div>
​
    </div>
    <script>
        new Vue({
            el:"#demoDiv",
            data:{
                demohtml:"<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.js"></script>
</head>
<body>
    <div id="demoDiv">
        <h1>v-once</h1>
        <input type="text" v-model="text">
        <h1>{{text}}</h1>
        <h1>{{text}}</h1>
        <h1 v-once>{{text}}</h1>
        <h1>{{text}}</h1>
        <h1>{{text}}</h1>
        <h1>{{text}}</h1>
​
    </div>
    <script>
        new Vue({
            el:"#demoDiv",
            data:{
                text:"我是数据"
            },
            methods:{
​
            }
        })
​
    </script>
</body>
</html>

watch监听器

watch就是用来监听data中的数据的 当监听的data数据改变了 那么watch就会自动触发

watch在初始化不会执行

语法:

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

watch:{

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

当监听的数据改变了你要操作的逻辑

}

}

计算属性 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.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>

注意:

上面的写法没有问题 但是我们把大量的逻辑放到了{{}}中会导致后期代码可读性和可维护性非常低 而且{{}}中在实际开发中主要就是用来展示数据的 并不是用来处理数据的

其实我们可以把一条数据在不同位置展示不同形态 计算属性中来完成

什么是计算属性 computed?

计算(处理数据)属性(就是vue实例中的一个属性) vue实例中可以计算数据处理数据的一个属性 计算属性他是依赖data数据的 当依赖的数据改变了 计算属性会重新计算这个数据并且返回计算之后的新结果

语法:

写在与 el data methods watch等同级位置

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.js"></script>
</head>
<body>
    <div id="demoDiv">
        <h1>正常展示:{{text}}</h1>
        <h1>大写展示:{{text.toUpperCase()}}</h1>
        <h1>大写加截取展示:{{text.toUpperCase().substr(1,4)}}</h1>
        <hr>
        <h1>计算属性来处理上面的业务</h1>
        <h1>正常展示:{{text}}</h1>
        <h1>大写展示:{{uppertext}}</h1>
        <h1>大写加截取展示:{{upperstrtext}}</h1>
    </div>
    <script>
        new Vue({
            el:"#demoDiv",
            data:{
                text:"abcdefghijk"
            },
            methods:{
​
            },
            watch:{
​
            },
            // 计算属性
            computed:{
                uppertext(){
                    return this.text.toUpperCase()
                },
                upperstrtext(){
                    return this.text.toUpperCase().substr(1,5)
                }
            }
        })
    </script>
</body>
</html>

计算属性与方法的区别

计算属性是基于依赖缓存的 也就是说 计算属性处理数据只会处理一次 如果你多次调用的话 那么她只会给你返回第一次处理之后存储在内存中的内容

方法 只要被调用那么就执行

计算属性依赖缓存相对于方法来说更加节省资源性能

计算属性与watch有什么区别

计算属性:在computed中 他是把data的数据变成自己依赖的数据 当这个数据改变了计算属性会重新计算这个依赖的数据并且返回处理之后的结果

watch:在watch中 他是监听一个data的数据 当这个数据改变了 他会完成一些业务操作

事件对象

谁触发了这个事件 事件对象就指向谁

$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.js"></script>
</head>
<body>
    <div id="demoDiv">
      <input type="text" @keydown="fun($event)">
    </div>
    <script>
        new Vue({
            el:"#demoDiv",
            data:{
         
            },
            methods:{
                fun(e){
                    console.log(e)
                }
            },
            watch:{
​
            },
        
            computed:{
             
            }
        })
    </script>
</body>
</html>

修饰符

就是帮助我们可以更简单的在事件实现的过程中处理一些基本的操作

语法:

@事件.修饰符=“函数()”

按键修饰符

可以对键盘事件进行简化

.up .down .ctrl .enter .space等等

<!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.js"></script>
</head>
<body>
    <div id="demoDiv">
      <input type="text" @keydown.ctrl="fun()">
    </div>
    <script>
        new Vue({
            el:"#demoDiv",
            data:{
         
            },
            methods:{
              fun(){
                console.log("aaaaaaaa")
              }
            },
            watch:{
​
            },
        
            computed:{
             
            }
        })
    </script>
</body>
</html>

事件修饰符

阻止事件默认行为 : .prevent

阻止冒泡: .stop

事件捕获: .captrue

事件只触发一次: .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.js"></script>
    <style>
        .fu{
            width: 500px;
            height: 500px;
            background-color: pink;
        }
        .zi{
            width: 200px;
            height: 200px;
            background-color: gray;
        }
    </style>
</head>
<body>
    <div id="demoDiv">
​
            <div class="fu" @click.once="fu()">
                <div class="zi" @click.stop="zi()">
​
                </div>
            </div>
    
        </div>
    <script>
        new Vue({
            el:"#demoDiv",
            data:{
         
            },
            methods:{
              fu(){
                console.log("福福福福福福")
              },
              zi(){
                console.log("滋滋滋滋滋滋滋滋滋")
              }
            },
            watch:{
​
            },
        
            computed:{
             
            }
        })
    </script>
</body>
</html>

生命周期的钩子函数

钩子函数

在特定情况下被自定钩起的函数(自动调用的函数)

vue的生命周期

vue实例从创建到销毁的过程

生命周期的钩子函数

vue实例从创建到销毁的过程中被自动调用的函数

生命周期的钩子函数:

1.实例创建前后

实例创建之前: beforeCreate 数据观测和初始化并没有开始

实例创建之后: created 完成了数据的观测 属性方法等内容都开始初始化 但是这个时候视图层还没有开始渲染

2.模板渲染前后

模板渲染之前: beforeMount 模板开始准备被渲染 但是还没有渲染

模板渲染之后: mounted el已经被vue实例挂在并且页面的dom也进行了渲染

3.数据更新前后

数据更新之前: beforeUpdate 在数据更新之前被调用 这个时候是准备开始更新

数据更新之后: updated 数据更新之后调用并且页面重新渲染展示修改之后的内容

4.实例销毁前后

实例销毁之前:beforeDestroy

实例销毁之后:destoryed

vue首次加载的时候之前前两组4个钩子

过滤器

在vue中过滤器使用 filter来表示

在不改变原始数据的情况下 格式化(按照我们的需要)展示内容

过滤器本应该分为自定义过滤器和内置过滤器 但是在vue2.x之后取消了内置过滤器 内置过滤器只停留在1.x之中

自定义过滤器

全局与局部的概念

<!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.js"></script>
</head>
<body>
    <h1>全局和局部的改变</h1>
    <!-- 全局就是一个内容可以在任意区域都可以使用
    局部只能在局部范围内使用 -->
    <div id="demodiv">
        11111{{text}}
​
    </div>
    <div id="demodivb">
        22222{{text}}
​
    </div>
    <script>
        new Vue({
            el:"#demodiv",
            data:{
                text:"你好么么哒"
            }
        })
        new Vue({
            el:"#demodivb",
            data:{
​
            }
        })
    </script>
</body>
</html>

全局过滤器

全局过滤器在任意位置都可以使用

语法:

定义在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.js"></script>
</head>
<body>
    <h1>全局过滤器</h1>
 
    <div id="demodiv">
     <h1>{{num}}</h1>
​
    </div>
    <div id="demodivb">
       <h1>{{num}}</h1>
​
    </div>
    <script>
        // 全局过滤器
​
        Vue.filter("xiaoming",(data)=>{
            
            return data.substr(0,10)
​
        })
​
        new Vue({
            el:"#demodiv",
            data:{
              num:"2017-03-12 22:48:56"
            }
        })
        new Vue({
            el:"#demodivb",
            data:{
                num:"2017-03-14 13:30:39"
            }
        })
    </script>
</body>
</html>

使用过滤器

{{变量| 过滤器的名字 }}

<div id="demodiv">
     <h1>{{num|xiaoming}}</h1>
​
    </div>
    <div id="demodivb">
       <h1>{{num|xiaoming}}</h1>
​
    </div>

局部过滤器

只能在创建过滤器的这个实例中进行使用

语法:

写在指定实例的el methods watch 等同级位置 使用 filters来进行定义

filters:{

过滤器的名字(你要过滤器的数据){

必须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.js"></script>
</head>
<body>
    <h1>局部的过滤器</h1>
​
    <div id="demodiv">
   
        {{num}}
    </div>
    <div id="demodivb">
  
        {{num|xiaoming}}
    </div>
    <script>
        new Vue({
            el:"#demodiv",
            data:{
              num:"2017-03-12 22:48:56"
            }
        })
        new Vue({
            el:"#demodivb",
            data:{
                num:"2017-03-14 13:30:39"
            },
            filters:{
                xiaoming(data){
                    return data.substr(0,10)
                }
            }
        })
    </script>
</body>
</html>

脚手架

什么是脚手架

在vue中 脚手架使用的是 vue-cli这个技术

脚手架 就是一个今后所写项目的一个基本的空框架 这个空框架中包含了 与项目业务无关的空框框

创建:

前期准备:电脑上必须药有node 建议页安装好淘宝镜像

1.全局安装 npm install -g @vue/cli

2.查看安装之后的脚手架版本 vue --version

3.把cmd cd到你要创建项目的路径下

4.创建项目 vue create 项目名

5 把路径cd到你创建的项目下

6.启动项目 npm run serve

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

在一个.vue文件中有三个部分

1.template html部分写在template中

2.script 就是用来写js相关的代码 data methods watch computed等等

3.style 就是用来编写组件的样式

拿到空的脚手架项目之后怎么办?

1.点开src文件夹 找到components文件夹 删除其中的helloword.vue

2.在components文件夹中创建一个属于我们自己的.vue文件 在其中把template script style补齐

<template>
  <div>
      <h1>你好我是第一个vue文件1</h1>
      <h1>你好我是第一个vue文件2</h1>
      <h1>你好我是第一个vue文件3</h1>
      <h1>你好我是第一个vue文件4</h1>
      <h1>你好我是第一个vue文件5</h1>
  </div>
</template>
​
<script>
export default {
​
}
</script>
​
<style>
​
</style>

3.到app.vue(所有组件的老大 不能删)中修改 原有的配置

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <!-- 3.设置成我们自己的 -->
    <Demo/>
  </div>
</template>
​
<script>
// 1.修改下面的引用 把原来的helloword    路径改成我们自己创建的
// 首字母必须大写
import Demo from './components/demo.vue'
​
export default {
  name: 'App',
  components: {
    // 2。修改引用的名字为我们创建的
    Demo
  }
}
</script>
​
<style>
#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>
​

4.在app.vue中删除图片与默认样式

<template>
  <div id="app">
    <!-- 4.删除默认欢迎图片 -->
    <!-- <img alt="Vue logo" src="./assets/logo.png"> -->
    <!-- 3.设置成我们自己的 -->
    <Demo/>
  </div>
</template>
​
<script>
// 1.修改下面的引用 把原来的helloword    路径改成我们自己创建的
// 首字母必须大写
import Demo from './components/demo.vue'
​
export default {
  name: 'App',
  components: {
    // 2。修改引用的名字为我们创建的
    Demo
  }
}
</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>
​

扩展--- 自动开启浏览器

1.在vue项目的根路径下根路径下根路径下根路径下根路径下根路径下根路径下 创建一个vue.config.js

2.在其中编写

module.exports={
    devServer:{
       open:true 
    }
}

3.重启项目

组件

把页面中多次重现 或者是 可以复用的内容 封装起来 在复用的时候只需要重读调用 二部需要重写的一个技术叫做组件

组件就是用来提高代码的复用性 减少代码量 提高开发速度 降低后期维护难度

组件的本质是 自定义标签

创建组件

全局组件--component

可以在任何地方都是用

1.在main.js中引用调用

import Vue from 'vue'
import App from './App.vue'
// 1.引用组件
import Demo from "./components/demo.vue"
// 2.调用
// Vue.component("组件名",引用的组件)
Vue.component("Demo",Demo)
Vue.config.productionTip = false
​
new Vue({
  render: h => h(App),
}).$mount('#app')
​

2.在想使用的地方直接使用

<template>
  <div>
      我是测试全局组件的
      <!-- 直接使用全局组件 -->
      <Demo/>
  </div>
</template>
​
<script>
export default {
​
}
</script>
​
<style>
​
</style>

注意 全局组件会污染项目 所以使用的时候请注意

局部组件--components

只能在局部进行使用的组件

创建

1.需要在components文件家中创建一个.vue文件 并写入内容

2.使用组件

(1) 引用 import 首字母大写 from "引用文件的路径"

(2)调用 需要与data methods watch 等同级位置 使用components来进行表示

语法:

components:{

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

}

(3)使用 把组件当做标签在template中进行使用

组件的坑与使用

坑1 组件中有多个标签

在vue的组件中 如果你要有多行标签那么必须把这多行标签 使用一个父组件包裹(就是在template中只能有一个根节点)

<template>
<div>
    <!-- 多行标签必须要有一个根节点 -->
    <div>
      我是测试组件中有多个标签的例子
    </div>
    <div>
        我是测试组件中有多个标签的例子
    </div>
</div>
  
 
</template>
​
<script>
export default {
​
}
</script>
​
<style>
​
</style>

坑2 组件之间的样式污染--scoped

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

<style scoped>
/* scoped 当前样式仅对当前组件生效 */
    h1{
        color:red;
    }
</style>

坑3 vue指令v-for需要加key属性

key 是在vue使用v-for的时候添加的一个属性 它的作用就是给遍历出来的内容添加一个唯一标识 因为有了这个唯一的名字之后 vue在处理这些新遍历出来的数据 效率更高

<template>
  <div>
      <h1>测试本地模式学习的属性---{{text}}</h1>
      <ul>
          <li v-for="(v,i) in arr" :key="i">{{v}}</li>
      </ul>
  </div>
</template>

本地模式知识点使用

1.data属性 语法有区别

 data(){
        return {
            text:"我是字符串",
            num:18
        }
    }

自行查找 vue组件的data为什么是一个函数?

剩下的所有属性写法一模一样

2.methods属性

3.watch属性

4.computed属性

5.8个生命周期钩子

6.filters过滤器

7.components属性

父子组件

组件与组件之间有嵌套关系

就是按照组件使用的语法在一个组件中调用另外一个组件

组件作用域

我在父组件中创建一个变量 在子组件中呢直接使用吗?

不能直接用

我在子组件中创建一个变量 在父组件中呢直接使用吗?

不能直接用

组件是一个完整的独立的个体 数据与数据之间不能直接相互使用 父子不行 子父不行 爷孙更不行

组件传值

正向传值

父组件把数据给子组件

使用props来实现正向传值 props 就是组件中的一个开口 可以让数据在父子之间正向传递

语法:

写在与data merhods watch 等同级位置

props:[ "接收数据的变量1",“接收数据的变量2”,.........n ]

使用:

子组件定义接收参数

<template>
  <div>
      ziziz
  </div>
</template>
​
<script>
export default {
    // 定义正向传值的接收数据
    props:["title","num"],
    data(){
        return {
            
        }
    }
}
</script>
​
<style>
​
</style>

父组件开始传递

   <Zi title="我是父组件传递的title数据" num="18"/>

props验证

就是在正向传值的时候对父组件传递过来的数据进行数据类型 默认值等 数据的格式效验

props验证不会影响页面的显示(哪怕验证的是错误的都不会影响页面显示 )但是会在控制台给我们开发者一个警告的错误提示

props验证上线后需要移除

语法:

props:{

接收参数:数据类型,

//如果我想验证接收参数可以是多个类型怎么办?

接收参数:[数据类型1,数据类型2]

//默认值呢?

接收参数:{

default:"你的默认值"

}

}

 props:{
        text:String,
        // num:Number
        // num:[String,Number]
        num:{
            default:"我是num的默认值",
            type:String//设置了默认值之后设置数据类型校验的写法
        }
    }

逆向传值

子组件把数据给父组件

注意:在vue中默认情况下 逆向传值是不被允许的 如果想实现你想传值 那必须通过事件来触发

实现:

1.子组件通过事件来触发一个 vue中自定义事件($emit)的抛出

this.$emit("自定义事件的名字随便起",你要抛出的数据)

<template>
  <div>
      zizizizzizizizi
      <button @click="fun()">点我逆向传值</button>
  </div>
</template>
​
<script>
export default {
    methods:{
        fun(){
            // 通过自定义事件来抛出数据
            this.$emit("xiaoming","我是子的数据")
        }
    }
}
</script>
​
<style>
​
</style>

2.接收 在子组件被调用的位置 使用@xiaoming="父组件的函数但是不加()不加()" 加()就会自动调用所以不加

<template>
  <div>
      fuffufufufufufu
      <Zi @xiaoming="fufun"/>
  </div>
</template>
​
<script>
import Zi from "./zi.vue"
export default {
    methods:{
        fufun(data){
            console.log(data);
        }
    },
    components:{
        Zi
    }
}
</script>
​
<style>
​
</style>

ref的方式

把ref绑定到组件之上就可以获取到子组件的数据

同胞传值

平级组件之间传递数据

中央事件总线 ---- eventBus

中央事件总线 其实就是凌驾在两个需要传递数据的兄弟组件之上的一个空的vue实例

1.创建eventBus文件夹 用来存放这个中央事件总线

import Vue from "vue"
​
export default new Vue

2.在需要传递数据的组件中 抛出 中央事件总线.$emit() 抛出一个自定义事件

<template>
  <div>
      zia
      <button @click="fun()">点我进行同胞传值</button>
  </div>
</template>
​
<script>
// 引用中央事件总线
import eventBus from "@/eventBus/index.js"
export default {
    methods:{
        fun(){
            // 进行同胞传值的抛出操作
            eventBus.$emit("datafun","我是a的数据么么哒!!!")
        }
    }
}
</script>
​
<style>
​
</style>

3.在需要数据的页面 组件中 接收 中央事件总线.$on() 监听实例上的自定义事件

<template>
  <div>
      zib
  </div>
</template>
​
<script>
import eventBus from "@/eventBus/index.js"
export default {
    created(){
        // 中央事件总线的数据接收
        // eventBus.$on("你要监听的事件名",(data就是你监听的事件中的参数)=>{
​
        // })
        eventBus.$on("datafun",(data)=>{
            console.log(data);
        })
    }
}
</script>
​
<style>
​
</style>

跨组件传值---vuex

爷孙组件 或者 更多层级之间的数据传递

vuex就是一个vue中进行数据状态管理的工具

主要就是把项目组件中的数据 集中的管理存储 方便项目中组件与组件之间的相互访问与使用

vue是单向数据流 数据只能值父子这种关系进行相互的流动 但是兄弟组件这种关系就没有办法了

使用:

state--数据源

就是用来在vuex中存储数据的位置

  state: {//存储数据的
    demoatext:"我是demoa的数据",
    ziatext:"我是zia的数据",
    zibtext:"我是zib的数据"
  },

state 组件获取数据

this.$store.state.xxx 获取数据

 <!-- 获取数据 -->
          {{this.$store.state.demoatext}}
          {{this.$store.state.ziatext}}
          {{this.$store.state.zibtext}}

module 模块

就是把原来写在vuex文件中的内容分门别类的 进行拆解 用模块来进行管理 方便后期维护

1.创建modules文件夹用来runaway模块

2.把原有写在一起的数据 拆分到模块中

let zib={
    // 是一个模块
    state: {//存储数据的
        zibtext:"我是zib的数据"
     
      },
}
​
export default zib

3.在vuex文件中引用模块 并且注入到modules

import Vue from 'vue'
import Vuex from 'vuex'
import demoa from "./modules/demoa.js"
import zia from "./modules/zia.js"
import zib from "./modules/zib.js"
Vue.use(Vuex)
export default new Vuex.Store({
  state: {//存储数据的
    
  },
  mutations: {
  },
  actions: {
  },
  modules: { //模块
    demoa,
    zia,
    zib
  }
​
})
​

页面取值

     <!-- 如果vuex被模块管理了   那么取值的时候 -->
          <!-- {{this.$store.state.模块名.数据}} -->
          {{this.$store.state.demoa.demoatext}}
          {{this.$store.state.zia.ziatext}}

mutations 修改

mutations就是在vuex中进行数据的修改的 mutations中是很多个函数 每一个函数就是一个修改的任务

1.修改数据 在组件中使用commit() 来触发vuex的mutations修改动作 (commit触发mutations修改state)

fun(){
            // 触发vuex的修改任务
            // this.$store.commit("mutations的任务名")
            this.$store.commit("setdemoa")
        }

2.新建mutations

mutations中是一个个的函数 函数的名字就是任务名 注意使用mutations的时候名字不能重复

 mutations:{//修改state的数据
        // state 就是上面的state数据源
        setdemoa(state){
            state.demoatext="哈哈我变了!!!!"
        }
     } 

payload 载荷

payload就是一个可以接收commit传递数据的一个形参

1.在使用commit的时候 除了第一个参数是调用的名字之外 可以传递第二个参数

// this.$store.commit("mutations的任务名",你传递给mutations的数据)
            this.$store.commit("setdemoa","哈哈")

2.在mutations中接收的时候 就可以使用payload这个形参来接收传递进来的数据

 // 接收第二个形参  payload
        setdemoa(state,payload){
            state.demoatext=payload
        }

vuex数据修改刷新丢失

在需要解决的组件中

使用事件监听器监听beforeunload页面关闭事件 在其中使用本地存储本store的数据转成字符串存起来

然后在页面重新加载之后判断本地存储中有没有之前存的那个数据 如果有 就把数据取出来替换store中的state数据源

   created(){
         window.addEventListener("beforeunload", () => {
      localStorage.setItem("stateInfo", JSON.stringify(this.$store.state));
    });
    if (localStorage.getItem("stateInfo")) {
      this.$store.replaceState(
        Object.assign(
          {},
          this.$store.state,
          JSON.parse(localStorage.getItem("stateInfo"))
        )
      );
    }
​
    },

actions 异步操作

在vuex中如果想进行异步数据请求那么就在actions中进行发送

1.在指定模块中 编写actions 并且actions中是一个个的函数 每个函数就是一个异步操作

 actions:{//进行异步操作的
        demolink(){
            // 把请求放在这里
            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);
            })
        }
     } 

2.在组件中通过dispatch()来调用actions中异步操作

  funb(){
            // 调用actions
            // this.$store.dispatch("你要调用actions的名字")
            this.$store.dispatch("demolink")
        },

请求来的数据怎么赋值给state

1.在actions中 是一些异步操作 我们需要把异步请求过来的数据 交给muttaions 才能修改state

 actions:{//进行异步操作的
        demolink(context){
            // 把请求放在这里
            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.data.data.commentList);
​
                // 我们需要把请求过来的数据交给mutations
                // context.commit("mutations的名字",你要传递的数据)
                context.commit("setarr",ok.data.data.commentList)
​
            })
        }
     } 

2.新建mutations 并且新建对应的state数据

setarr(state,payload){
            // 把actions传递过来的数据修改state
            state.arr=payload
        }

在组件中通过this.$store.dispatch(“你要调用的actions的名字”)触发actions进行异步操作 在actions中通过数据请求把数据请求过来 然后通过context.commit() 调用mutations 修改state的数据

getters

是vuex中5大属性的其中之一 gettes 就是vuex中的计算属性

getters与vue的计算属性的区别

相同点 都是对数据进行计算并且返回处理好的结果方便页面展示

不同点: 计算属性处理的数据只能在当前组件内部使用 vuex的getters 他处理好的数据由于在vuex中 所以可以在任何组件中使用

语法:

写在与 state mutations 等同级的位置 getters里面对应的是一个个的函数 每个函数就是一个处理数据的操作 但是必须return

  getters:{//vuex的计算属性
        upnum(state){
            return state.num.toUpperCase()
        }
    }

在组件中 可以 直接使用getters处理好的数据 this.$store.getters.xxx

    <h1>{{this.$store.getters.upnum}}</h1>

数据请求

原生ajax与jquery的方式实现

vue-resource 是vue官方出品 vue2.0之后官方停止维护了

axios

axios

axios是一个第三方的数据请求 可以在vuer中使用 也可以在原生js中使用 也可以在今后学习的react等知识点中使用

axios 就是基于XHR对象 使用promise进行异步封装的一个扩展 的写法(让他更符合当下的语法要求)

axios.get()

axios.post()

axios({ })

使用:

1.下载 npm install --save axios

2.引用

3.使用

  mounted(){
        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);
        })
    }

axios拦截器

使用

1.下载axios

2.新建util文件夹 工具文件夹

3.新建api文件夹 用来封装数据请求的文件夹

4.在util中新建拦截器文件

import axios from "axios"
// 创建axios 赋值给常量service 
const service = axios.create();
​
// 添加请求拦截器(Interceptors)
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
​

5.封装数据请求

​
import service from "@/util/service.js"
// 用来封装数据请求的文件
let getlink=(url)=>{
    // 当我调用这个函数的时候需要让他返回一个promise对象(因为我们使用promise对象来封装我们的异步请求让他的可读性更高并且更符合当下语法主流)
     return new Promise((resolve,reject)=>{
        //  来写你的异步操作
        service.request({
           url,
           method:"GET"
        }).then((ok)=>{
             resolve(ok)
        }).catch((err)=>{
              reject(err)
        })
        
     })
}
export default getlink

6 在需要使用的组件内 调用api的请求 进行数据请求

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

跨域

因为浏览器的安全机制 同源策略引起的 同端口 同域名 同协议

如果数据请求出现如下错误 表示跨域了

localhost/:1 Access to XMLHttpRequest at 'http://www.weather.com.cn/data/cityinfo/101320101.html' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

使用代理跨域即可解决

我们日常发送数据请求是通过浏览器进行发送的

代理跨域

1.在项目的根路径下 新建vue.config.js

2.编写如下内容

module.exports={
    devServer:{
        open:true,
        // 设置跨域
        proxy:{
            "/api":{
                // target:"设置你要帮助跨域的地址"
                target:"http://www.weather.com.cn/",
                changeOrigin:true,
                ws:true,
                pathRewrite:{
                    "^/api":""
                }
            }
        }
    }
}

3.在组件的请求中 设置/api

 getlink("/api/data/cityinfo/101320101.html").then((ok)=>{
            console.log(ok)
        }).catch((err)=>{
            console.log(err);
        })

mockjs 模拟数据

1.下载 npm install --save mockjs 没有点

2.新建文件夹 mock 用来存放模拟数据相关代码 并且在其中新建data文件夹用来存放模拟数据的json文件 在新建index.js来编写代码

let Mock=require("mockjs")
// Mock.mock("模拟请求地址","请求方式",require("json模拟数据地址"))
Mock.mock("/mock/data/movielist","get",require("./data/moviedata.json"))

3.需要在全局配置文件中添加mock的引用

import Vue from 'vue'
import App from './App.vue'
// 因为在es6中 如果只指向了文件夹  那么他会自己去找文件夹下的index.js
require("./mock")
Vue.config.productionTip = false
​
new Vue({
  render: h => h(App),
}).$mount('#app')
​

4.重启项目

发送数据

GET

params来进行数据的发送 params:{ 发送数据的key:发送数据的val}

import service from "@/util/service.js"
export function getlink(url,params){
    return new Promise((resolve,reject)=>{
        service.request({
            url,
            method:"GET",
            // 发送get数据使用params来发送
            params
        }).then((ok)=>{
            resolve(ok)
        }).catch((err)=>{
            reject(err)
        })
    })
}

POST

基本的封装上与get相同

post发送数据 使用data

import service from "@/util/service.js"
export function postlink(url,data){
    return new Promise((resolve,reject)=>{
        service.request({
            url,
            method:"POST",
            // post发送数据使用data
            data
        }).then((ok)=>{
            resolve(ok)
        }).catch((err)=>{
            reject(err)
        })
    })
}

在前端页面使用的时候需要帮助axios解析

  fun(){
            // 因为axios不知道怎么去解析post发送数据  所以我们需要帮助
            // axios来解析post
           let usp = new URLSearchParams()
        //    usp.append(后台要的key,val)
            usp.append("uname",this.inputa)
            usp.append("upwd",this.inputb)
            
            postlink("/api/user/denglu",usp).then((ok)=>{
                console.log(ok);
            })
        }

slot 槽口/插槽

引子

组件的本质 --- 自定义标签

组件在调用的时候 可以使用单标签或者双标签 (双标签的情况我们能不能在组件调用的标签中插入内容?)

如果我们默认情况下硬要插入内容 没有用 什么都不显示

slot

槽口是一种组件的复用技巧

props 正向传值 在复用组件的时候 复用的内容不同 但是数量相同

slot槽口 在复用组件的时候 复用的内容不同 但是数量也不相同相同

语法:在组件向现实插入内容的位置写上 <slot></slot>

<template>
  <div>
    <span>首页</span>
    <button>按钮1</button>
    <!-- 设置槽口 -->
    <slot></slot>
  </div>
</template>

在组件被调用的时候在其中插入内容

  <Zi>
        <h1>我是插入的内容</h1>
        <h1>我是插入的内容</h1>
        <h1>我是插入的内容</h1>
        <h1>我是插入的内容</h1>
        <h1>我是插入的内容</h1>
        <h1>我是插入的内容</h1>
      </Zi>

具名slot

带有名字的槽口

<slot name="给槽口起个名字"></slot>

在插入的时候 给插入的内容添加一个slot=“你要插入的槽口名”

      <Zi>
        <h1 slot="demoa">我是插入的内容1</h1>
        <h1 slot="demob">我是插入的内容2</h1>
        <h1 slot="democ">我是插入的内容3</h1>
        <h1 slot="demod">我是插入的内容4</h1>
        <h1 slot="demoe">我是插入的内容5</h1>
        <h1 slot="demoe">我是插入的内容6</h1>
      </Zi>

作用域槽口

后面会讲

ref----vue中的dom操作

使用

1.给你要操作的dom元素起个名字(ref="名字")

2.找到他 this.$refs.xxx

<template>
  <div>
      <h1>ref的使用</h1>
      <!-- 1.设置名字 -->
      <h1 ref="xiaoming">设置我的颜色</h1>
      <button @click="fun()">点我设置h1的颜色</button>
  </div>
</template>
​
<script>
export default {
    methods:{
        fun(){
            // 2.通过ref的名字找到你要设置的dom内容
            this.$refs.xiaoming.style.color="pink";
        }
    }
}
</script>
​
<style>
​
</style>

ref设置到组件之上

如果我们把ref绑定到组件之上 那么就可以得到当前组件的组件实例 得到了实例就得到了组件的所有的属性和方法

其中一点就是可以得到组件的data数据从而完成逆向传值

父组件如何直接触发子组件的方法?通过ref绑定到组件之上即可

动态组件

多个组件使用同一个挂载点 并且动态切换

挂载点: <component :is="组件名的变量"></component>

<template>
  <div>
      fuffufufufuf
        <button @click="fun('Zia')">点我去a</button>
        <button @click="fun('Zib')">点我去b</button>
        <button @click="fun('Zic')">点我去c</button>
        <!-- 动态组件 -->
        <component :is="com"></component>
  </div>
</template>
​
<script>
import Zia from "./zia.vue"
import Zib from "./zib.vue"
import Zic from "./zic.vue"
export default {
    methods:{
        fun(data){
            this.com=data
        }
    },
    data(){
       return {
            com:"Zic"
       }
    },
    components:{
       Zia, 
       Zib, 
       Zic 
    }
}
</script>
​
<style>
​
</style>

路由

传统的html+css+js的项目中如何完成页面之间的切换呢?

1.写多个html

2.在html里面可以使用超链接标签a 来跳转或者使用 js的方式进行跳转

js方式:

window.location.href 设置当前url 可以使用浏览器的回退按钮返回回来

window.history.replace() 替换当前页面 跳转之后就回不来了

路由的基本概念

路由就是根据url的地址不同(就是根据url的锚点路径 在加载不同的组件页面) 来动态分配不同的组件页面 从而完成单页面应用(SPA)

单页面应用 在用户切换页面的时候 没有那种白屏的效果 很丝滑

vue-router库 就是在vue中实现路由的基础依赖库

路由的创建

脚手架方式创建

在创建项目的时候 选中router选项即可

大家会发现src中多了一个router (配置路由的) 与 views(组件页面)的文件夹

1.删除views与components里面的内容

2.配置路由i router文件夹下的index.js中进行配置

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'
​
Vue.use(VueRouter)
​
const routes = [
  {
    path: '/',//url的匹配路径
    name: 'Home',//就是给当前这个规则起个名字
    component: Home //引用的显示组件页面
  },
  {
    path: '/shop',
    name: 'Shop',
    component: Shop
  },
  {
    path: '/user',
    name: 'User',
    component: User
  },
]
​
const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})
​
export default router
​

3.来到app.vue设置初体验点击跳转

      <router-link to="/">Home</router-link> |
      <router-link to="/shop">shop</router-link> |
      <router-link to="/user">user</router-link> |

手工方式

1.创建出vue路由所需要的相关文件夹与文件 并且编写路由页面

2.下载vue-router库 来帮助我们实现路由 npm install --save vue-router

3.引用相关依赖 并且在vue使用use方法使用vuerouter

import Vue from 'vue'
​
import VueRouter from 'vue-router'
​
import Home from '../views/Home.vue'
​
​
​
Vue.use(VueRouter)

4.配置路由规则

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  }
]
​

5.实例化路由对象 并且在路由对象中 设置路由模式与注入路由规则

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

6引用路由并且在vue实例中注入路由规则

import Vue from 'vue'
import App from './App.vue'
// 引用路由
import router from './router'
​
Vue.config.productionTip = false
​
new Vue({
  router,//在vue实例中注入路由规则
  render: h => h(App)
}).$mount('#app')
​

7 设置router-view的路由出口

路由的规则与配置

src文件夹下的router里面的index.js文件

只要新建了路由的页面 那么必须在此文件中进行配置

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'
​
// 在vue中使用vue路由功能
Vue.use(VueRouter)
​
​
// 数组对象  就是用来配置路由规则的
const routes = [
  {
    path: '/',//url的匹配路径
    name: 'Home',//就是给当前这个规则起个名字
    component: Home //引用的显示组件页面
  },
  {
    path: '/shop',
    name: 'Shop',
    component: Shop
  },
  {
    path: '/user',
    name: 'User',
    component: User
  },
]
​
​
// 实例化路由对象   并且传入相关依赖参数
const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})
​
export default router
​

路由导航

声明式导航

标签的方式

使用router-link 来实现路由之间的页面切换 其中有一个to属性 用来表示跳转的页面路径

<router-link to="/你要去的路径">页面显示的内容</router-link>

注意:

打开浏览器查看源码会发现把router-link翻译成了a标签 因为浏览器不能识别router-link标签所以被编译成了a标签

虽然vue在编译的时候会把router-link解析成a标签 但是 我们不能在写跳转的时候使用a标签

动态样式类

router-link会在切换的选中时候动态的 添加一个router-link-active的类名 方便我们设置路由导航的选中效果

编程式导航

js的方式

this.$router.push( "/你要去那里") 跳转页面

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

this.$router.go(正数前进 负数回退)

 fun(){
      // 编程式导航
      this.$router.push("/user")
    }

路由出口

就是用来设置 路由页面的显示位置 使用router-view来进行表示 路由出口必须有

多级路由/嵌套路由

一个路由中嵌套另外一个路由页面

使用 children 进行多级路由的配置

实现:

1.先完成二级路由的路由页面

2.在router文件夹下的index.js中配置规则

2-1先引用

2-2 配置路由规则(二级路由路由规则是配置到 他对应的一级路由规则中进行设置)

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/home.vue'
import Phone from '../views/phone.vue'
import User from '../views/user.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: '/user',
    name: 'User',
    component: User,
    // 设置二级路由
    children:[
      {
        path: 'era',//二级路由的path可以不带/
        name: 'Era',
        component: Era
      },
      {
        path: 'erc',
        name: 'Erc',
        component: Erc
      },
      {
        path: 'erd',
        name: 'Erd',
        component: Erd
      },
    ]
  },
  {
    path: '/phone',
    name: 'Phone',
    component: Phone
  }
]
​
const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})
​
export default router
​

3.配置二级路由的路由出口

router-view 来进行设置

二级路由的路由出口需要写在对应一级路由页面中

4.设置路由导航

4-1 如果在配置二级路由的时候path没有带/ 那么二级路由导航的路径是 /一级路由/二级路由

      <!-- 如果在配置二级路由的时候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>

4-2 4-1 如果在配置二级路由的时候path带/ 那么二级路由导航的路径是 /二级路由

  <!-- 如果在配置二级路由的时候path带/  那么二级路由导航的路径是 /二级路由 -->
        <router-link to="/era">era</router-link>
        <router-link to="/erc">erc</router-link>
        <router-link to="/erd">erd</router-link>

路由重定向-redirect

重定向 :重新定位方向

{ path:"/你要重定向的路径",redirect:"/定位到那个路径上" }

 // 重定向
  {
    path:"/",
    redirect:"/home"
  }

404页面

在规则的最下面设置404

 // 404页面规则必须必须必须写在最下面
  {
    path: '*',//星号匹配所有地址
    name: 'No',
    component: No
  }

路由模式

vue中路由模式分为两种

history模式

因为有些时候我们需要把写好的页面 嵌入到手机原生app中 但是有些app要求路径中不能带#号

url中不带#号

history模式的页面刷新会丢失 上线之后会丢失 丢失解决的方式是 让你们的后端服务器的那个人 配置下后端的页面重定向

hash 模式

hash是默认模式 如果你不写路由模式默认就是他

url带#号

区别

区别hashhistory
url显示上带#不带#
页面刷新正常展示上线后刷新丢失
支持版本支持低版本浏览器HTML5新增的内容所以不支持低版本浏览器

路由传参/动态路由匹配

传统的html+css+js项目中如何把一个页面的数据传递到另外一个页面?

url传参

vue中 如果想把数据从一个页面传递到另外一个页面的时候 需要使用路由传参

路由传参模式

params模式

1.在你需要传递数据的路由页面规则中 设置接收参数(谁接收 在谁的规则中进行配置 在其规则的path中添加 接收参数 /:xxx)

  {
    // 1.在需要接收数据的路由规则中 设置接收参数
    path: '/phone/:xiaoming',
    name: 'Phone',
    component: Phone
  }

2.发送数据

声明式

方式1(知道就好了解):

  <router-link to="/phone/我是传递给phone的数据">点我把数据给phone</router-link>

方式2(推荐使用):

 <!-- <router-link :to="{name:'你要去的路由的名字',params:{你要发送的数据名需要和规则配的一样:传递的数据}}">点我传递数据</router-link> -->
      <router-link :to="{name:'Phone',params:{xiaoming:'呵呵'}}">点我传递数据</router-link>
     

编程式

就是把上面声明式的两种写法to中的参数其一 放到this.$router.push()

3.接收数据

注意单词是 $route

{{this.$route.params.你配置的参数}}

query模式

不需要在路由规则中配置接收参数

1.发送

声明式

方式1:

  <router-link to="/query?xiaoming=我是参数">点我使用query发送数据</router-link>

方式2:

<!-- <router-link :to="{name:'你要去的页面规则的名字',query:{发送的key:值}}">点我使用query发送数据</router-link> -->
     
     <router-link :to="{name:'Query',query:{xiaoming:'我是第二种方式发送的query数据么么哒'}}">点我使用query发送数据</router-link>

方式3:

  <router-link :to="{path:'你要去的页面的path路径',query:{发送的key:值}}">点我使用query发送数据</router-link> 

编程式

2.接收

{{this.$route.query.xiaoming}}

query与params方式的区别

1.用法上:

query传参的时候可以使用path也可以使用name来进行传参 params只能用name来进行使用

query方式接收和params方式在接收的时候语法有所不同

2.url展示上

query 在传递数据的时候时候url会显示传递数据的参数与参数值

http://localhost:8080/query?xiaoming=111参数

params 只会显示传递的参数值

http://localhost:8080/phone/数据

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

在路由切换的过程中的一些钩子函数(路由切换的时候被自动执行的函数) 可以在vue中进行一些比如登录验证 等需求

全局守卫

全局前置守卫-- beforeEach()

就是在路由准备切换的时候 触发的一个钩子函数

语法:

to:你即将要进入的路由

from :你从那个路由来的

next: 执行下一步

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

})

注意需要写在 路由的配置文件里面

router.beforeEach((to,from,next)=>{
​
  if(to.path=="/denglu"||to.path=="/zhuce"){
    next()
  }else{
    alert("您没有登录请您登录后访问vip页面!!!")
    next("/denglu")
  }
​
  // console.log(to);
  // console.log(from);
  
​
})

全局后置守卫-- afterEach()

路由切换完毕之后触发的一个钩子函数

语法:

router.afterEach((to,from)=>{

})

路由独享

就是只对配置当前钩子函数的哪一个路由生效

beforeEnter((to,from,next)=>{})

写在指定路由的配置上

组件内守卫

只会对当前组件范围生效

进入组件前调用

beforeRouteEnter()

离开组件之前调用

beforeRouteLeave()

   beforeRouteLeave(to,from,next){
        console.log(to);
        console.log(from);
        if(confirm("您确定离开phone吗?")){
            next()
        }else{
            // 不跳转
            next(false)
        }
    }

$route与$router的区别

$router vueRouter对象 他代表的就是vue路由的实例 这个对象是一个全局对象 它包含了所有路由的关键属性 $route 路由的跳转对象 他包含的是当前页面路由对象

vue路由懒加载

懒加载 是为了spa单页面应用中出现的首次加载白屏问题(第一次运行的时候会把所有的页面都加载一边浪费资源)

使用路由懒加载 让我们的程序按照我们的需要按需加载页面 免去了第一次加载时候的性能损耗

语法

import导入方式 component: () => import('你使用的路由页面路径')

es6异步组件方式 component: (resolve) => require(['你使用的路由页面路径'], resolve),

keep-alive

在我们路由或者动态组件中发现不停切换不同页面的时候 页面的数据会丢失

原因是因为 当我们不停切换的时候页面的显示内容也在不听的切换 每次切换的时候 vue都会把原有的那个组件或者页面实例删除 并且创建一个新的vue组件实例

那么怎么样让页面切换的时候数据不丢失呢?

使用keep-alive来实现 就是用来保存在切换或者中的组件状态 可以防止页面dom重复渲染 减少页面在切换时候对程序造成的性能损耗 减少加载时间提升用户体验

<keep-alive>

你要保存状态的那些内容

</keep-alive>

如果想保存路由的状态

使用keep-alive包裹路由出口

    <keep-alive>
        <router-view/>
    </keep-alive>

如果想保存动态组件的状态

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

keep-alive的属性

在vue2.1.0版本之后 keep-alive添加了两个属性

include 你要缓存谁

      <!-- include 你想缓存谁把谁写的进去 -->
      <keep-alive include="Demoa,Demob">
          <component :is="com"></component>
      </keep-alive>

exclude 你不缓存谁

 <!-- exclude 你不想缓存谁把谁写的进去 -->
      <keep-alive exclude="Demob">
          <component :is="com"></component>
      </keep-alive>

问题 如果我两属性都写了呢? exclude的优先级大于include

keep-alive的钩子函数

keep-alive在管理的内容中特定阶段内 被自动调用的函数

activated keep-alive管理的组件被使用的时候触发

deactivated keep-alive管理的组件被停止使用的时候触发

自定义指令

在指令不够用的时候 我们可以自己定义指令方便后期使用

语法:

写在data methods等同级位置

directives:{

自定义指令的名字:{

自定义指令的钩子函数(你要操作的dom元素){ ​ 你的逻辑

}

}

}

自定义指令的钩子函数

bind 绑定到dom之上只执行一次

inserted 是咱们百分之99使用到的钩子 指令绑定到dom之上在页面加载之后调用

update 指令绑定到元素之上 在组件更新的时候调用

componentUpdate 指令绑定到元素之上 当前指令与及他所有的子节点更新完成后调用

unbind 当前指令和页面接触绑定的时候调用

<template>
  <div>
      注册
      <!-- 使用 -->
      <h1 v-xiaoming>我是测试自定义指令的dom</h1>
  </div>
</template>
​
<script>
export default {
    directives:{
        xiaoming:{
            // 指令绑定到谁身上el就是谁
            inserted(el){
                el.style.color="red";
            }
        }
    }
}
</script>
​
<style>
    
  
    
​
</style>

$set

数据改变了 但是视图并没有发生改变?

总结下 :当vue的data里面声明了数组或者是对象的时候,但是在项目运行的时候向数组和对象中添加新的属性的时候 就是属性发生改变 但是对应的视图并不会发生改变

官方: 如果定义在实例创建之后 向data属性中添加新的内容的时候 他不会触发视图的更新

<template>
  <div class="hello">
    <!-- 当前几按钮添加新属性的时候  会发现obj.age并没有改变 -->
    <h1>{{obj.name}}-----{{obj.age}}</h1>
    <button @click="fun()">点我添加</button>
  </div>
</template>
​
<script>
export default {
  methods:{
    fun(){
      this.obj.age=18
      console.log(this.obj.age);
    }
  },
  data(){
    return {
       obj:{
         name:"xixi"
       }
    }
  }
 
}
</script>
​
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
​
</style>
​

原理:

双向绑定 数据劫持与发布者订阅者模式 数据劫持 使用的是js中Object.defineProperty()进行数据劫持 但是vue2x 由于数据劫持使用的是Object.defineProperty() 但是这个方法有一个非常大的问题 就是他只能监听初始化的数据 如果中途添加新的属性时候 那么就不会被监听到 也就没有了双向绑定

解决

使用$set()来解决上述问题

语法:

this.$set(你要处理的数据,新增的数据的key,新增数据的val)

<template>
  <div class="hello">
​
    <h1>{{obj.name}}-----{{obj.age}}</h1>
    <button @click="fun()">点我添加</button>
  </div>
</template>
​
<script>
export default {
  methods:{
    fun(){
      // this.obj.age=18
      // console.log(this.obj.age);
​
      this.$set(this.obj,"age",666)
      console.log(this.obj.age);
    }
  },
  data(){
    return {
       obj:{
         name:"xixi"
       }
    }
  }
 
}
</script>
​
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
​
</style>
​

vue.nextTick

是什么?

nextTick就是等到dom更新完毕之后执行的一个钩子函数

使用场景

就是在想使用指定页面dom的时候 但是使用的时机是dom还没有加载的情况下

在生命周期的钩子中的初始化部分 如果我们想在这个钩子中读取dom中的值是读取不到的。

<template>
  <div>
      <h1 ref="demoh">{{text}}</h1>
  </div>
</template>
​
<script>
export default {
    data(){
        return {
            text:"我是测试使用的变量!!!"
        }
    },
    created(){
        // 会报错因为在此钩子中 dom还没有加载
        console.log(this.$refs.demoh.innerText);
    }
}
</script>
​
<style>
​
</style>

但是如果我就是想在其中得到怎么办?

<template>
  <div>
      <h1 ref="demoh">{{text}}</h1>
  </div>
</template>
​
<script>
export default {
    data(){
        return {
            text:"我是测试使用的变量!!!"
        }
    },
    created(){
        // 会报错因为在此钩子中 dom还没有加载
        // console.log(this.$refs.demoh.innerText);
​
        // 等待dom记载完毕后在执行打印内容
        // 当dom加载完毕后nexttick的回调就会自动触发
        this.$nextTick(()=>{
            console.log(this.$refs.demoh.innerText);
        })
    }
}
</script>
​
<style>
​
</style>

vue响应式的执行时机

响应式 数据变视图变视图变数据变

vue数据的响应式 不是数据变了 视图立即更新 是等待一系列的数据都改变了 在同一进行视图更新

1.vue首先修改数据 是一个同步任务 这个修改操作可能有跟多个 那么这些修改操作就会在进行中依次执行 知道数据全部被修改了 但是修改的时候还没有设置dom操作

2.vue开启一个异步的执行列队 并且把当前事件循环中发生的虽有数据变化缓存起来

3.开始依次更新dom

<template>
  <div>
   
      <h1 ref="numh">{{num}}</h1>
      <button @click="fun()">点我修改数据</button>
  </div>
</template>
​
<script>
export default {
    methods:{
        fun(){
            this.num=666;
            // 当数据修改之后我想直接得到改变之后的dom内容
            // vue不是数据变视图立即改变
            console.log(this.$refs.numh.innerText);
        }
    },
    data(){
        return {
            text:"我是测试使用的变量!!!",
            num:18
        }
    }
}
</script>
​
<style>
​
</style>

如果我就想在数据改变了 获取dom的信息怎么办?nexttick来解决

<template>
  <div>
   
      <h1 ref="numh">{{num}}</h1>
      <button @click="fun()">点我修改数据</button>
  </div>
</template>
​
<script>
export default {
    methods:{
        fun(){
            this.num=666;
            // 当数据修改之后我想直接得到改变之后的dom内容
            // vue不是数据变视图立即改变
            this.$nextTick(()=>{
                console.log(this.$refs.numh.innerText);
            })
            
        }
    },
    data(){
        return {
            text:"我是测试使用的变量!!!",
            num:18
        }
    }
}
</script>
​
<style>
​
</style>

mixins 混入

混入就是vue的一个组件复用性的功能 如果多个页面有相同的方法存在的时候 可以把这些相同的内容提取出来 从而进行封装

全局

在全局引用之后 所有的组件都可以正常使用mixins的内容 ( 容易造成污染 )

1.在main.js中引用

2.使用Vue.mixin(调用)

3.你在组件中就可以正常使用了

import Vue from 'vue'
import App from './App.vue'
// 全局混入
import xiaoming from "./mixins/index.js"
​
Vue.mixin(xiaoming)
​
Vue.config.productionTip = false
​
new Vue({
  render: h => h(App),
}).$mount('#app')
​

局部--mixins

1.新建文件夹 在其中封装你想复用的内容

let xiaoming={
    methods:{
        fun(){
            console.log("你好");
        }
    }
}


export default xiaoming

2.组件使用

<template>
  <div>
      <h1>混入的使用</h1>
      <!-- 3.直接使用 -->
      <button @click="fun()">点我打印</button>
  </div>
</template>
​
<script>
// 1.引用混入内容
import xiaoming from "@/mixins/index.js"
export default {
//    2.使用mixins来进行调用
    mixins:[xiaoming]
}
</script>
​
<style>
​
</style>

组件的二次封装

1.ui框架的样式有的时候不能满足我们开发的需求 因为ur库的样式都是提前定义好的就几个 所以有的时候提供的功能是我们可以用的但是样式却不能满足我们

2.ui库也会出现一些问题 某个我们使用的ui库不兼容我们其中引用的某些第三方插件 那我们提前把这些ui库封装起来就不会影响我们的项目坍塌

使用二次封装会增加我们的代码量

二次封装就是 使用props与slot等组件的复用性功能来进行的 把组件变成一个全局组件即可

路由扩展

路由规则中的meta

就是路由中的路由记录 就是给路由规则中设置一些变量数据

  {
    path: '/shop',
    name: 'shop',
    component: () => import('../views/shop.vue'),
    // 设置一些路由规则的数据
    meta:{
      title:"购物"
    }

在页面可以展示这些信息

this.$router.meta.xxx

页面全部的路由信息

this.$router.options.routes

根据用户不同设置不同的权限页面

1.新建好不同用户的路由页面

2.配置不同用户的路由规则

3.在跳转的时候需要根据不同的用户权限分配不同的路由规则从而显示不同的页面

<template>
  <div>
     登录
     <hr>
     <router-link to="/shouye">管理员登录</router-link>
       <hr>
     
     <button @click="fun()">普通用户登录</button>
  </div>
</template>

<script>
// 1.引用你需要的路由规则
import {putouter} from "@/router/purouter.js"
export default {
  methods:{
    fun(){
      // 2.把你引用的路由插入到vue的路由实例中
      this.$router.options.routes=putouter

      // 3.添加到路由实例上
      this.$router.addRoutes(putouter)

      this.$router.push("/shouye")
    }
  }
}
</script>

<style>

</style>

需要在每个路由规则中设置meta信息 然后根据this.$router.options.routes获取到全部路由的信息 并且挑选出我们先要的部分路由 根据得到的规则便利生成页面路由导航 在页面跳转的时候首先根据需要设置的不同用户权限信息的路由规则进行引用在通过

1把你引用的路由插入到vue的路由实例中 this.$router.options.routes=putouter

2添加到路由实例上
  this.$router.addRoutes(putouter)

vue3.0

3.0变化

1.响应式

2.0当中 数据的响应式 是居于Object.defineProperty()方法来实现的 只会监听初始化的数据 如果在初始化(数据观测)完毕之后 再向数据中添加新的属性的时候 Object.defineProperty() 就不会监听到 就数去了响应式

3.0响应式采用了 最新的proxy来替代Object.defineProperty() proxy是惰性监听(不会在初始化监听数据 而是在数据需要用到时候才回去监听数据) proxy标准太新了 所以ie不兼容 在3.0中 专门为ie进行了适配 他会判断你的浏览器是什么 如果是ie那么久继续使用Object.defineProperty() 来实现响应式 如果不是是用proxy来完成响应式

2.实例的属性改变

2.0中 组件的属性是通过声明式的方式直接写在实例中的

3.0 改变了使用方式 变成了 compositionAPI (组合式api) 就把原有的属性写法变成了一个个的方法进行剥离式编写 也免去了new一系列的流程

3.声明响应式

3.0中 data methods等属性 都需要写在一个setup的方法中 并且return出去

setup

setup3.0中最终要的一个启动方法 setup方法是出去beforCreate 与 Created两个钩子之间调用的函数 setup是组合式api的入口 在其中可以进行变量 方法 计算属性等内容的启动 但是不要忘了return出去

创建基本数据类型变量

ref 来进行创建 ref需要接受一个参数作为数据的值 会返回一个响应式的对象

let text=ref("变量值")

<template>
  <div>
      我是一个组件---{{text}}
  </div>
</template>
​
<script>
import {ref} from "vue"
export default {
    setup(){
        // 创建变量  ref
       let text = ref("我是变量")
​
        return {
            text
            }
    }
}
</script>
​
<style>
​
</style>

修改

想要修改ref创建的数据 必须在修改的时候使用.value属性来修改

想要修改ref创建的数据 必须在修改的时候使用.value属性来修改

想要修改ref创建的数据 必须在修改的时候使用.value属性来修改

想要修改ref创建的数据 必须在修改的时候使用.value属性来修改

<template>
  <div>
      我是一个组件---{{text}}
      <button @click="fun()">点我修改</button>
  </div>
</template>
​
<script>
import {ref} from "vue"
export default {
    setup(){
        // 创建变量  ref
       let text = ref("我是变量")
       function fun(){
        //    想要修改ref创建的数据   必须在修改的时候使用.value属性来修改
           text.value="我被修改了"
       }
​
        return {
            text,fun
            }
    }
}
</script>
​
<style>
​
</style>

引用数据类型变量

reactive 来创建复杂数据类型变量

<template>
  <div>
      {{obj.age}}
      <button @click="fun()">点我修改</button>
  </div>
</template>
​
<script>
import {reactive} from "vue"
export default {
    setup(){
       let obj = reactive({
            name:"xixi",
            age:18
        })
        // reactive创建的变量直接修改
        function fun(){
            obj.age=666
        }
​
        return {
            obj,fun
        }
    }
}
</script>
​
<style>
​
</style>

ref 与reactive的区别

ref 与reactive的区别

创建的数据类型是不相同的

修改的时候ref必须使用.value来进行修改 reactive直接修改

ref操纵dom

ref操作dom的话 我们在使用ref的时候需要向ref(传入null)即可操纵dom

<template>
  <div>
      <input type="text" ref="demoinput">
      <button @click="fun()">点我得到input的值</button>
  </div>
</template>
​
<script>
import {ref} from "vue"
export default {
    setup(){
        // 创建ref对象
        let demoinput=ref(null)
        function fun(){
            console.log(demoinput.value.value)
        }
        return {
            demoinput,fun
        }
    }
}
</script>
​
<style>
​
</style>

计算属性

computed 实现计算属性

<template>
  <div>
      <h1>正常显示--{{text}}</h1>
      <h1>大写显示--{{uptext}}</h1>
  </div>
</template>
​
<script>
​
​
import {ref,computed} from "vue"
export default {
    setup(){
        let text=ref("abcdefg")
        // 计算属性
        // let 接收新值的变量= computed(()=>{
        //     return 操纵逻辑
        //  })
​
        let uptext=computed(()=>{
            return text.value.toUpperCase()
        })
​
        return {
            text,uptext
        }
    }
}
</script>
​
<style>
​
</style>

watch

<template>
  <div>
      
      <input type="text" v-model="text">
      <h1>{{text}}</h1>
  </div>
</template>
​
<script>
import {ref,watch} from "vue"
export default {
    setup(){
       let text = ref("变量")
    //    监听
        // watch(()=>{
        //     return 你要监听的数据
        // },(newval,oldval)=>{
                // 数据变了之后干什么
        // })
​
       let inputwatch= watch(()=>{
            return text.value
        },(a,b)=>{
            console.log(a)
            console.log(b)
        })
​
​
​
        return {
            text,inputwatch
        }
    }
}
</script>
​
<style>
​
</style>

生命周期变化

https://blog.csdn.net/weixin_43294560/article/details/107585301

扩展----elementUI

是一个UI框架(就是写页面)

有的同学去公司之后可能使用的是公司内部的框架

使用

npm 安装 npm i element-ui -S

在main.js中写入如下内容

​
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
​
​
Vue.use(ElementUI);

扩展---- 原型设计

主要就是用来构建整体项目的基本框架和轮廓 方便甲方或者是项目组内部开发讨论的一个快速构建项目图片的一个东西

工具有: 蓝湖 墨刀 慕客 等工具

vant

Vant - Mobile UI Components built on Vue

打包

npm run build 打包 会生成一个dist文件夹 运行其中的html文件发现报了很多的错(无法找到相关的js css文件)

需要在打包之前设置打包之后的静态资源路径 vue.config.js 设置静态资源路径

// 配置静态资源路径

publicPath:"./",

还需要把路由模式设置成hash模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值