vue.js

与三阶段无关

渐进增强和优雅降级

渐进增强就是先兼容低版本 在逐渐地向高版本提高

优雅降级就是先完成高版本浏览器的编写 在向低版本兼容

disabled 标签禁用的属性

加上这个属性标签就不能使用了

请你说一下常见的js dom操作有哪些?

dom查找

dom新增创建

dom克隆删除属性操作

app分类

移动webapp 运行在移动端浏览器上的app

原生app :就是从移动端应用商店下载的app

混合式app:就是我们前端写好的页面(vue react html+css+js) 把我i们写的页面内嵌到原生项目中

es6解构赋值

就是把数组或者对象快速赋值的一个语法

Vue

vue的基本概念

vue就是当下最流行的前端js框架(数据处理和数据绑定的一个工具)

是什么

vue是一款用于构建用户界面的渐进式自底向上增量开发MVVM框架

渐进式:就是不做职责以外的事情.(就是vue可以在一个项目中的局部使用 他不会影响没有使用的位置 也可以整个项目都是用)

自底向上增量开发:先写好一个基础的页面 在去添加各个复杂的功能,简单到繁琐的过程

MVVM是一个框架的模式:

什么是框架

用来封装一些与业务(就是你写的项目的功能)无关的代码块 我们使用他进行拼装 即可完成指定项目功能

框架的优势

大大提高了开发效率(但是要学习新的语法对初学者来说比较麻烦)

MVC

是昨早的一种框架模式------》mvvm是mvc的变种

就是把一个项目一个功能抽象成了不同的模块 每个模块来管理自己的事情 让开发变得更加的简单

M (model)模型(今后只要说到模型大家自动转换成数据) 管理数据的

V (view) 视图 (就是用户可以看见的地方)

C (controller)控制器 用来对数据接收和展示的中间商

MVVM

是vue中使用的一种模式

M (model)模型(今后只要说到模型大家自动转换成数据) 管理数据的

V (view) 视图 (就是用户可以看见的地方)

VM (ViewModel)视图模型 模型数据与视图中的一个数据桥梁(这个桥梁更加智能他能发现模型或者是视图中的数据改变 当一方发生了改变 就会立即通知另外一方进行改变)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8XguNX2y-1624890895632)(.\img\2.bmp)]

vue的开发目的

1.解决了数据绑定问题

2.可以开发大型单页面SPA应用

3.支持组件化

HelloWord

1.我们要使用先下载 :npm install -save vue

2.开始编写页面代码


<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>Documenttitle>
    
    <script src="node_modules/vue/dist/vue.min.js">script>
head>
<body>
    

        
        <div id="demoDiv">
            {{text}}------{{num}}
        div>
     
        <script>
            // 3.新建vm层 (就是vue实例)
            new Vue({
                // 4.关联模型与视图层
                el:"#demoDiv",
                data:{ //5模型层
                    text:"你好么么大",
                    num:18
                }  
            })
        script>


body>
html>

vue的渲染方式

{{}}-----》模板语法 模板表达式 双花括号赋值法

作用:

用于在vue中解析表达式 (表达式 通过某种计算可以返回结果的一个公式)虽然在{{}}中可以来处理一些数据

但是在vue中不推荐在{{}}中写入太符复杂的逻辑(因为视图层就是显示的 你在里面处理太复杂的逻辑不合适)


<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>Documenttitle>
    <script src="node_modules/vue/dist/vue.min.js">script>
head>
<body>
        <div id="demoDiv">
            <h1>模板语法h1>
            
            <h1>{{text}}h1>
            <h1>{{num}}h1>
            <h1>{{bool}}h1>
            <h1>{{arr[2]}}h1>
            <h1>{{obj.age}}h1>

            <hr>
            <h1>{{updata.toUpperCase()}}h1>
            <h1>{{updata.substr(1,3)}}h1>
            <h1>{{arr.length}}h1>
        div>
        <script>
            new Vue({
                el:"#demoDiv",
                data:{
                    text:"我是字符串",
                    num:666,
                    bool:true,
                    arr:[111,2222,3333,4444],
                    obj:{
                        name:"xixi",
                        age:18
                    },
                    updata:"abcdefg"
                }
            })
        script>
body>
html>

声明式渲染与数据驱动

vue中核心是允许我们使用简洁的模板语法进行声明式的数据渲染

声明式渲染:我们告诉程序我想干什么程序就会自动完成

命令式渲染:原生的都是命令时 我们需要告诉程序一步一步应该怎么走 他才会按照我们的指令前进

数据驱动

vue会时时刻刻的监控着模型和视图 当一方发生了改变另外一方也会随之发生改变

总结:

vue的双大括号中不要加双引号

指令

什么式HTML的属性?

就是用来扩展HTML标签的功能

属性的语法?

写在HTML的开标签中 并且属性=“属性值”

vue的指令

指令是带有 v- 前缀的特殊属性 (就是在vue中带有v-前缀的 扩展HTML标签功能的一个技术)

vue指令的语法

写在HTML的开标签中 并且指令=“指令值” 注意:一个开始标签内可写入多个指令,多个指令间使用空格分隔

v-model

v-model 指令

作用:主要是用于表单上数据的双向绑定
语法:v-model = 变量
注:v-model 指令必须绑定在表单元素上

Vue框架核心的功能就是双向的数据绑定。 双向是指:HTML标签数据 绑定到 Vue对象,另外反方向数据也是绑定的
使用 v-model 指令来实现双向数据绑定 把视图数据与模型数据相互绑定


<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>Documenttitle>
    <script src="node_modules/vue/dist/vue.min.js">script>
head>
<body>
        <div id="demoDiv">
            <h1>v-model指令h1>
            
            
            <input type="text" v-model="inputval"/>
            <h1>{{inputval}}h1>

            <hr>
            
            <input type="checkbox" v-model="bool"/>
            <h1>{{bool?"你勾选了":"你没有勾选"}}h1>
        div>
        <script>
            new Vue({
                el:"#demoDiv",
                data:{
                  inputval:"",
                  bool:true
                }
            })
        script>
body>
html>

双向绑定的原理

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

数据劫持:数据拦截 当我们访问或设置对象的属性的时候,都会触发Object.defineProperty()函数来拦截(劫持),然后在返回(get)或设置(set)对象的属性的值。并且当数据发生改变的时候做出反应。

发布者-订阅者模式:其定义对象间一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。

v-show

v-show 指令
作用:控制切换一个元素的显示和隐藏
语法:v-show = 表达式
根据表达式结果的真假,确定是否显示当前元素
true表示显示该元素;false(默认)表示隐藏该元素
元素一直存在只是被动态设置了display:none


<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>Documenttitle>
    <script src="node_modules/vue/dist/vue.min.js">script>
head>
<body>
        <div id="demoDiv">
            <h1>v-showh1>
            <input type="checkbox" v-model="bool"/>{{bool?"显示":"取消"}}

            <p v-show="bool">我要显示和隐藏p>
            
        
        div>
        <script>
            new Vue({
                el:"#demoDiv",
                data:{
                    bool:true
                }
            })
        script>
body>
html>

v-on

v-on 指令
作用:为 HTML 元素绑定事件监听
语法:v-on:事件名称=‘函数名称()’
简写语法:@事件名称=‘函数名称()’
注:函数定义在 methods 配置项中


<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>Documenttitle>
    <script src="node_modules/vue/dist/vue.min.js">script>
head>
<body>
        <div id="demoDiv">
            <h1>v-onh1>
            <button v-on:click="fun()">点我打印内容button>
            <button @click="fun()">点我简写打印内容button>
        div>
        <script>
            new Vue({
                el:"#demoDiv",
                data:{
                  
                },
                // 函数写在与data el同及位置使用methods包裹
                methods:{
                    fun(){
                        console.warn("你好么么哒")
                    } 
                }
            })
        script>
body>
html>

v-for

v-for 指令
作用:遍历 data 中的数据,并在页面进行数据展示
语法:v-for = ‘(item, index) in arr’
item 表示每次遍历得到的元素
index 表示item的索引,可选参数


<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>Documenttitle>
    <script src="node_modules/vue/dist/vue.min.js">script>
head>
<body>
        <div id="demoDiv">
            <h1>v-forh1>
            <ul>
                <li v-for="(v,i) in arr">{{v.name}}------{{v.age}}li>
            ul>


            <table border="1">
                
                <tr v-for="(xiaoming,xiaohong) in arr">
                    <td>{{xiaohong}}td>
                    <td>{{xiaoming.name}}td>
                    <td>{{xiaoming.age}}td>
                tr>
            table>
        div>
        <script>
            new Vue({
                el:"#demoDiv",
                data:{
                  arr:[
                      {name:"xixi1",age:118},
                      {name:"xixi2",age:218},
                      {name:"xixi3",age:183},
                      {name:"xixi4",age:184},
                      {name:"xixi5",age:185},
                      {name:"xixi6",age:186}
                  ]
                }
            })
        script>
body>
html>

v-bind

v-bind 指令
作用:给html的属性绑定变量
语法:v-bind:属性名 = ‘表达式’/ 简写 :属性名=‘表达式’
绑定一个属性:
绑定多个属性(不能使用简写):


<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>Documenttitle>
    <script src="node_modules/vue/dist/vue.min.js">script>
head>
<body>
        <div id="demoDiv">
            <h1>v-bindh1>
            <a v-bind:href="ahref">{{text}}a>
            <a :href="ahref">11{{text}}11a>
        div>
        <script>
            new Vue({
                el:"#demoDiv",
                data:{
                    text:"点我去百度",
                    ahref:"http://www.baidu.com"
                }
            })
        script>
body>
html>

v-if 全家桶

v-if v-else v-esle-if

v-if指令
作用:判断是否加载固定的内容
语法:v-if = 表达式
根据表达式结果的真假,确定是否显示当前元素
true表示加载该元素;false表示不加载该元素
元素的显示和隐藏 是对Dom元素进行添加和删除


<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>Documenttitle>
    <script src="node_modules/vue/dist/vue.min.js">script>
head>
<body>
    <div id="demodiv">
        <h1>v-ifh1>
        <input type="checkbox" v-model="bool"/>
        <p v-show="bool">我是v-show的元素p>
        <p v-if="bool">我是v-if的元素p>
    div>

    <script>
        new Vue({
            el:"#demodiv",
            data:{
                bool:true
            }
        })
    script>
body>
html>

v-if与v-show的区别

首先两者在用户的角度效果一样 都是对元素在页面进行显示和隐藏的 接收数据布尔值 true显示 false隐藏
但是 v-if 是对DOM元素进行添加和删除已达到显示和隐藏 v-show是使用css进行的

应用场景:

v-show 在初始化的时候对电脑的资源消耗比较到 (对安全性相对较低的内容进行显示和隐藏)

v-if 是在切换的时候对电脑的资源消耗比较到 (对安全相对较高的内容进行显示和隐藏)

v-else

作用:必须配合v-if使用否则无效。当v-if条件不成立的时候执行


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


        <h1 v-if="bool">我是if的内容h1>
        <p>v-if与v-else之间不能有第三者p>
        <h1 v-else>我是else的内容h1>
    div>

    <script>
        new Vue({
            el:"#demodiv",
            data:{
                bool:false
            }
        })

       
    script>
body>
html>+

v-else-if


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

        <select v-model="text">
            <option value="吃饭">吃饭option>
            <option value="睡觉">睡觉option>
            <option value="在吃">在吃option>
            <option value="在睡">在睡option>
            <option value="上厕所">上厕所option>
        select>
        <p v-if="text=='吃饭'">用户选择了吃饭饭p>
        <p v-else-if="text=='睡觉'">用户选择了睡觉觉p>
        <p v-else-if="text=='在吃'">用户选择了在吃饭饭p>
        <p v-else-if="text=='在睡'">用户选择了在睡觉觉p>
        <p v-else-if="text=='上厕所'">用户选择了上厕所p>
        <p v-else>用户什么都没有选择p>
     
    div>

    <script>
        new Vue({
            el:"#demodiv",
            data:{
               text:""
            }
        })

       
    script>
body>
html>

v-text

v-text 指令
作用:操作网页元素中的纯文本内容。{{}}是他的另外一种写法 就是向网页中插入纯文本

v-text与{{}}等价,{{}}叫模板插值,v-text叫指令。

有一点区别就是,在渲染的数据比较多的时候,可能会把大括号显示出来,俗称屏幕闪动

屏幕闪动

①使用v-text渲染数据
②使用{{}}语法渲染数据,但是同时使用v-cloak指令(用来保持在元素上直到关联实例结束时候进行编译),v-cloak要放在什么位置呢,v-cloak并不需要添加到每个标签,只要在el挂载的标签上添加就可以

v-html与v-once

v-html 指令
作用:双大括号会将数据解释为纯文本,而非 HTML 。为了输出真正的 HTML ,你需要使用 v-html 指令
语法:

v-once 指令
作用:当数据改变时,插值处的内容不会更新(会影响到该节点上的所有属性)
语法:

{{text}}


<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>Documenttitle>
    <script src="node_modules/vue/dist/vue.min.js">script>
head>
<body>
    <div id="demodiv">
        <h1>v-htmlh1>
        {{newhtml}}
        <div v-html="newhtml">div>
        <h1>v-once 一次性插值h1>

        <input type="text" v-model="text">
        <p>{{text}}p>
        <p v-once>{{text}}p>
        <p>{{text}}p>
        <p>{{text}}p>
    div>

    <script>
        new Vue({
            el:"#demodiv",
            data:{
                newhtml:"

我是字符串标签

"
, text:"我是默认值" } })
script> body> html>

侦听/监听 watch

watch是用来监听data模型数据中的内容 当数据发生改变的时候 watch就会触发


<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>Documenttitle>
    <script src="node_modules/vue/dist/vue.min.js">script>
head>
<body>
    <div id="demodiv">
        <input type="text" v-model="text">
    div>
    <script>
        new Vue({
            el:"#demodiv",
            data:{
                text:"我是默认值"
            },
            // 监听
            watch:{
                // 你要监听的数据:function(新值,旧值){
                //     你要完成的逻辑
                // }
                text(newval,oldval){
                    console.log(`${newval}-----${oldval}`)
                }
            }
        })
    script>
body>
html>

计算属性

概念:顾名思义,首先它是一种属性,其次它有“计算”这个特殊性质。每次取得它的值得时候,它并不像普通属性那样直接返回结果,而是经过一系列的计算之后再返回结果。同时只要在它的当中里引用了 data 中的某个属性,当这个属性发生变化时,计算属性仿佛可以嗅探到这个变化,并自动重新执行。

计算属性(computed) 是一个属性 所以与el methods等同级位置编写 它的主要作用是计算(计算data的数据 当data属性发生改变的时候他会知道 并且重新计算返回我们想要的结果 一条数据在不同位置展示出不同形态的时候)


<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>Documenttitle>
    <script src="node_modules/vue/dist/vue.min.js">script>
head>
<body>
    <div id="demodiv">
        <h1>为什么用计算属性 在模板中写太多的逻辑 会导致后期无法维护h1>
        <p>{{text}}p>
        <p>{{text.toUpperCase()}}p>
        <p>{{text.toUpperCase().substr(1,3)}}p>

        <h1>计算属性h1>
        <p>{{newatext}}p>
        <p>{{newbtext}}p>
    div>
    <script>
        new Vue({
            el:"#demodiv",
            data:{
                text:"abcdefghijk"
            },
       
            watch:{
              
            },
            // 计算属性
            computed:{
                // 需要返回的数据: function () {
                //     return 处理操作
                // }
                newatext(){
                    // 必须return
                    return this.text.toUpperCase()
                },
                newbtext(){
                    return this.text.toUpperCase().substr(1,4)
                }
             
            }
        })
    script>
body>
html>

计算属性(computed)与methods(方法)的区别

为什么会造成这个想法


<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>Documenttitle>
    <script src="node_modules/vue/dist/vue.min.js">script>
head>
<body>
    <div id="demodiv">
        <p>{{newtext}}p>
        <p>{{showtext()}}p>
        大家会发现两个的结果没有区别
        
    div>
    <script>
        new Vue({
            el:"#demodiv",
            data:{
                text:"abcdefg"
            },
          
            watch:{
             
            },
            methods:{
                showtext(){
                    return this.text.toUpperCase()
                }
            },
            computed:{
                newtext(){
                    return this.text.toUpperCase()
                }
            }
        })
    script>
body>
html>

如果我们把计算属性调用多次 他只执行了一次

但是我们把方法调用多次 调用几次执行几次 有很大的资源浪费

区别:

计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变时才会重新求值。
方法绑定数据只要被调用,方法将总会再次执行函数。
计算属性相对于方法在处理特定场合下节省资源性能

计算属性与侦听器的区别:
当watch监听的值发生改变就会被调用,watch可以在数据变化时做一些异步处理或者开销大的操作
计算属性是计算依赖的值,当依赖的值发生改变才会触发。

事件对象

事件对象就是用于描述触发这个事件的元素信息

$event

修饰符

v-on指令提供了事件修饰符来处理DOM事件细节

按键修饰符

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


<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>Documenttitle>
    <script src="node_modules/vue/dist/vue.min.js">script>
head>
<body>
    <div id="demodiv">
        
       <input type="text" @keydown.ctrl="fun()">
    div>
    <script>
        new Vue({
            el:"#demodiv",
            data:{
              
            },
           methods:{
               fun(){
                   console.log("aaaaaaaaaa")
               }

                    
           },
            watch:{
             
            }
        })
    script>
body>
html>

事件修饰符

【扩展】事件修饰符
prevent修饰符:阻止事件的默认行为(submit提交表单)
stop修饰符:阻止事件冒泡
capture修饰符:与事件冒泡的方向相反,事件捕获由外到内
self:只会触发自己范围内的事件,不包含子元素
once:只会触发一次
注意:修饰符可以串联使用

交互

vue请求数据有Vue-resource、Axios、fetch三种方式。Vue-resource是Vue官方提供的插件,axios是第三方插件,fetch es6原生

Vue-resource在vue2.0的时候已经停止更新了

axios是对XHR对象使用promise进行了二次封装简化了语法

fetch是es原生(react中会带大家写)

axios

初体验

axios 是一个第三方的数据请求库 使用promise对XHR对象进行了封装 是现今最主流的一种数据请求方式

使用先下载

npm install --save axios

axios封装

生命周期与钩子函数

生命周期 就是vue实例从创建到销毁的过程

钩子函数:本质是一个函数 但是他是一个会被自动调用的函数

生命周期的钩子函数:就是vue从创建到销毁的过程中被自动调用的函数(可以帮助我们在vue中完成一些特定条件下的自动执行的业务)

生命周期的钩子:

beforeCreate(创建实例)

created(创建完成)

beforeMount(开始创建模板)

mounted(创建完成)

beforeUpdate(开始更新)

updated(更新完成)

beforeDestroy(开始销毁)

destroyed(销毁完成)


<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>Documenttitle>
    <script src="node_modules/vue/dist/vue.min.js">script>
head>
<body>
    <div id="demodiv">
        <h1>{{text}}h1>
        <button @click="text='我被改了'">点我更新button>
    div>
    <script>
        new Vue({
            el:"#demodiv",
            data:{
                text:"我是一个字符串"
            },
            methods:{

            },
            watch:{

            },
            computed:{

            },
            // 生命周期
            // **beforeCreate(创建实例)**

            // **created(创建完成)**

            // **beforeMount(开始创建模板)**

            // **mounted(创建完成)**

            // **beforeUpdate(开始更新)**

            // **updated(更新完成)**

            // **beforeDestroy(开始销毁)**

            // **destroyed(销毁完成)**


            beforeCreate(){
                console.log("创建实例")
            },
            created(){
                console.log("实例创建完成")
            },
            beforeMount(){
                console.log("开始创建模板")
            },
            mounted(){
                console.log("创建完成")
            },
            beforeUpdate(){
                console.log("开始更新")
            },
            updated(){
                console.log("更新完成")
            },
            beforeDestroy(){
                console.log("开始销毁")
            },
            destroyed(){
                console.log("销毁完成")
            },
        })
    script>
body>
html>

自定义过滤器

过滤器作用
在不改变数据的情况下,输出前端需要的格式数据

坑 :面试的时候 面试官或者今后与同事沟通的时候可能会被 问道 你能给我说下vue中的内置过滤器吗?

2.0中已经废弃了内置过滤器,需要我们自定义过滤器来使用filter

全局过滤器

全局过滤器定义的内容在页面中的所有实例中都可以使用


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


    <div id="demodivb">
            {{text|xiaoming}}
    div>
    <script>
        // 如果数据在页面展示的时候和我们的续期想法不一样我们可以使用过滤器格式化展示数据
        // 全局过滤器定义在实例之前
        Vue.filter("xiaoming",(val)=>{
            // 大于5个就保留5位 并且在后面加...
            if(val.length>=5){
                return val.substr(0,5)+"..."
            }else{
                return val
            }
        })
        new Vue({
            el:"#demodiv",
            data:{
                text:"我是第一个内容哦么么哒" 
            }
        })
        // =====================
        new Vue({
            el:"#demodivb",
            data:{
                text:"呵呵哒呵呵哒" 
            }
        })
    script>
body>
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>Documenttitle>
    <script src="node_modules/vue/dist/vue.min.js">script>
head>
<body>
    <div id="demodiv">
       {{text|xiaohone}}
    div>


    <div id="demodivb">
        
            {{text|xiaohone}}
    div>
    <script>
        // 局部过滤器  写在指定实例当中  与data等同级
        
        new Vue({
            el:"#demodiv",
            data:{
                text:"西游记" 
            },
            filters:{
                xiaohone(val){
                    return "<<"+val+">>"
                }
            }
        })

        new Vue({
            el:"#demodivb",
            data:{
                text:"红楼梦" 
            }
        })
    script>
body>
html>

总结:

在没有冲突的前提下,过滤器可以串联

项目环境配置 vue脚手架

前期准备

电脑上必须要有node

安装淘宝镜像 cnpm (非必装,网络慢的情况可安装)
npm install -g cnpm --registry=https://registry.npm.taobao.org

如果安装过程中报错 请您连你手机的wifi

使用

1 全局安装vue-cli npm install -g @vue/cli (除了你电脑重装系统或者是重装了node以外 就不用在安装了)

2.查看版本 vue --version

3.开始创建项目 但是需要先把你的cmd路径切换到你想创建项目的文件夹下 vue create 项目名

在弹出的选择中 选择第三项 剩下的眼睛闭上一路回车

4 cd到项目名下

5 npm run serve启动

空脚手架创建好之后怎么办?

因为空脚手架中有很多与我们开发没有关系的内容 所以拿到脚手架在写我们的代码之前 需要删除一些默认的内容

1.删除components文件夹中的HelloWord.vue

2.进入到app.vue(是所有组件的老大所有的组件今后要显示都要关联到app.vue中 写在app中的内容在所有地方都会显示)

保留如下内容:





单文件组件

以.vue结尾的文件就是单文件组件

在一个.vue文件中分为三部分 template是写html script 是写js的 style是写css的

我们之前学的 data methods watch computed filters 以及8个钩子 除了data的语法变了 剩下没有任何改变

扩展小概念

组件:用来封装可以复用的ui代码块

模块:用来封装可以复用的js代码块

组件

组件:用来封装可以复用的ui代码块

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

1.提高开发效率

2.降低测试难度

分类

全局组件

在所有地方都可以使用的组件

如果要使用

在main.js中引用 调用

import Vue from 'vue'
import App from './App.vue'
import router from './router'
// 1.全局组件的引用
import Bb from "@/components/bottombar.vue"
// 2.全局组件调用
// Vue.component("组件名",你要使用的组件)
Vue.component("Bb",Bb)

Vue.config.productionTip = false

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

之后在任何位置直接使用

局部组件

创建

1.在components文件夹下创建 以.vue结尾的文件

2.在其中写入 template script style (每次都写很麻烦 所以快速创建方式是vscode中






大家会发现什么都没有显示 原因是因为没有在app中建立关系

3.要把我们的组件和app建立关系

(1)引用

// 1.引用组件
// import 是给引用进来的内容起个名字 首字母大写 from "你引用的路径"
  import Home from "./components/home.vue"

export default {
  name: 'App',
  components: {
  
  }
}

(2)调用

​ 局部组件使用components来进行表示 写在与el data methods等同级的位置

// 1.引用组件
// import 是给引用进来的内容起个名字 首字母大写 from "你引用的路径"
  import Home from "./components/home.vue"

export default {
  name: 'App',
  components: {
  // 2.调用
  // 组件名:你引用的组件
  Home
  }
}

(3)使用






组件中的属性使用

data methods watch computed filters 八个钩子 组件中的属性(后面还有内容)

data的使用

<template>
  <div>
      {{text}}
  </div>
</template>

<script>
export default {
    data(){
        return {
            text:"你好么么哒"
        }
    }
  
}
</script>

<style>

</style>

思考?为什么组件的data是一个函数 而原来的写法确是一个对象?

课下自行百度

其他属性语法以及使用没有任何变化

组件的样式设置

在组件的style范围内来写样式

但是默认情况下一个组件写的样式会影响其他组件 为了解决这个问题

所以我们需要给样式的范围添加一个scoped当前样式仅对当前组件生效

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

父子组件

就是vue组件与组件之间的嵌套关系 我们就可以非常方便的使用这种嵌套关系来进行页面内容的 拼装 从而减少组件的体积

父子组件的作用域

父组件能直接使用子组件的数据吗? 不能

子组件能直接使用父组件的数据吗?不能

vue中组件与组件之间是一个完整的 独立的个体 他们之间的数据默认情况下是绝对不能相互使用的

既然默认不行 那么有没有办法可以呢?

父子组件传值

正向传值

父组件把数据给子组件

props 是vue的一个属性 写在与data methods等同级的位置

props的作用就是用于接收组件外部传递进来的数据

props:[“接收参数1”,“接收参数2”,…“接收参数n”]

使用:

1.在子组件中设置props的接收参数

export default {
    props:["xiaoming"],//设置接收参数
    data(){
        return {
            zitext:"我是子组件的数据"
        }
    }
}

2.在页面内想使用的地方把props的数据插入页面

<template>
  <div>
      <!-- 使用props的小明数据 -->
      zizizizizizzizizizi----{{xiaoming}}
  </div>
</template>

<script>
export default {
    props:["xiaoming"],//设置接收参数
    data(){
        return {
            zitext:"我是子组件的数据"
        }
    }
}
</script>

<style>

</style>

3.父组件开始传递

在子组件被调用的地方进行传递

     <!-- 传递数据给子组件    -->
      <Zi :xiaoming="futext"/>

总结下基本props的使用

props就是标签的属性

props验证

就是对父组件传递过来的数据进行校验 (数据类型 是否为空 默认值)

props:{ //对象

}

为什么写的有问题 但是props验证没有错误提示?
生产版本也就是压缩版的文件删除了警告,所以使用非压缩版的js文件就可以看到错误

逆向传值

子组件把数据给父组件

默认是不被允许的 必须要通过自定义事件来进行传递

使用:

子组件中:

1.在页面中创建一个事件 调用一个函数

2.在函数中使用this.$emit进行自定义事件的创建

<template>
  <div>
     
     <button @click="fun()">点我进行逆向传值button>
  div>
template>

<script>
export default {
    data(){
        return {
            num:"我是子组件的数据么么哒!!"
        }
    },
    methods:{
        fun(){
            // 千万不要把$emit记成逆向传值了   他是自定以事件
            // this.$emit("自定义事件的名字","你传递的数据")
            this.$emit("xiaoming",this.num)
        }
    }
}
script>

父组件:

1.在子组件被调用的地方 使用 @/v-on:自定义事件名=“当前父组件的函数(不要圆括号不要圆括号)”

2.创建那个父组件的函数 函数中形参就是子组件传递过来的数据

<template>
    <div>
      <h1>逆向传值h1>
      
      <Bzi @xiaoming="fun"/>
  div>
template>

<script>
import Bzi from "./bzi.vue"
export default {
    methods:{
        // val就是子组件传递的数据
        fun(val){
            console.log(val)
        }
    },
    components:{
        Bzi
    }
}
script>

路径别名

内置别名

@ 看见这个@就是src文件夹 (无论在那个层级中只要写了@ 那么就是src文件夹)

自定义别名

在vue脚手架中默认给我们提供了一个@=src的一个文件夹别名

但是呢不够用比如我们要找到components这个类路径怎么办?

配置:

在项目的根路径下在项目的根路径下在项目的根路径下在项目的根路径下在项目的根路径下在项目的根路径下

在项目的根路径下在项目的根路径下在项目的根路径下在项目的根路径下在项目的根路径下在项目的根路径下

在项目的根路径下在项目的根路径下在项目的根路径下在项目的根路径下在项目的根路径下在项目的根路径下

在项目的根路径下在项目的根路径下在项目的根路径下在项目的根路径下在项目的根路径下在项目的根路径下

创建一个vue.config.js(名字不能变)的文件

在其中使用 module.exports={}进行暴漏

module.exports={
    configureWebpack:{
        resolve:{
          alias:{
            // "别名":"对应的文件夹"
            "com":"@/components"
          }
        }
      }
}

千万不要忘了重启项目 因为修改了配置文件必须重启项目

slot

插槽/槽口

引子:

如果我把组件的调用写成双标签 并且在开标前和关标签中写入内容 会显示吗?

不会

slot使用

1.基本使用 就是你在想接受外部插入的内容组件之上放置一个slot组件






问题:

刚才直插入了可以一个 多个呢?

可以插入的

但是一个开口插入多个内容 后期如何管理?

具名槽口

带有名字的槽口 slot

在定义slot的时候 使用name属性起个名字

插入的时候 给元素使用slot属性=“slot的名字”

问题 有啥用?

很多使用slot和props有相似点

props在 一个组件被多次调用 但是内容不同数量相同的时候使用

slot 在 一个组件被多次调用 但是内容不同数量也不相同的时候使用

路由

可以搭建spa(单页面应用) 的一个技术 让我们的项目可以进行页面的切换
可以根据url的不同来切换不同的组件页面以达到用户观感上的页面切换

特点与原理

利用锚点完成切换
页面不会刷新

路由创建

脚手架自动创建

流程 :就是在vue create 新建项目的时候 选中Router项即可

与之前默认的脚手架项目区别

在src文件夹下多了一个router的文件夹与views的文件夹

router文件夹 就是配置路由的文件夹

views就是写路由页面的文件夹

创建新页面过程

1.在views下创建你新建的路由页面组件

2.配置路由规则在router文件夹下的index.js中去先引用在配置

import Vue from 'vue'
import VueRouter from 'vue-router'

//1.引用  你要用的所有路由页面必须先引用
import Home from '../views/Home.vue'
import About from '../views/About.vue'
import Shop from '../views/shop.vue'

Vue.use(VueRouter)
//2配置路由规则
const routes = [
  {
    path: '/',  //url匹配的路径
    name: 'Home', //当前这个规则的命名空间(给当前这个路由起个名字)
    component: Home //当匹配到的时候我要显示的组件页面是什么
  },
  {
    path: '/about',
    name: 'About',
    component: About
  },
  {
    path: '/shop',
    name: 'Shop',
    component: Shop
  },
  
]

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

export default router


3.需要去创建路由出口(自动创建的时候会给我们自动添加)

路由出口就是 我们的路由最终要在那里显示

4.设置路由导航

传统的跳转连接我们使用a标签

但是但是但是在vue中千万不要使用a标签哦!!!!!!!

要跳转使用 router-link 就是进行路由页面的跳转连接

手工创建

1.下载vue-router库 : npm install --save vue-router

2.创建路由组件页面

就是在views文件夹下创建哪些.vue文件

3.配置路由规则

在router文件夹下的index.js文件中进行先引用在配置

4.实例化路由对象并且传入路由规则

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

5 把路由实例在main.js中传入vue实例中建立关系

6.设置出口 router-view

7.设置导航 router-link

路由导航

路由导航就是切换路由的呢些方式

原生html+css+js如何进行页面切换?

1.html方式:a标签

2.js方式:href replace() go(正数负数) forword() back()

路由导航分类

1.标签的方式(声明式导航):router-link

router-link 有一个to属性用来表述去哪里

注意:

router-link这个声明式导航最终会在浏览器被编译成a标签 但是千万要注意 我们不能直接使用a标签

注意:

就是我们在写路由规则的时候path路径不要写/ 要不在路由导航中就会出现问题

注意:

router-link-active

每当我选中之后 会发现在路由导航中会自动添加一个类名这个类名是干什么的?

是设置当前选中的样式的 我们可以根据vue动态添加的类名 进行当前路由选中样式的设置

2.js的方式(编程式导航

编程式导航就是使用js的方式进行跳转

方式1:最常用页面跳转

this.$router.push("/去哪里“)

方式2:替换当前页面(退不回去了)

this.$router.replace("/那个页面")

方式3:this.$router.go(n)这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)。

路径通配符

就是使用*号在path中可以匹配所有路径 通常是完成404页面的创建

重定向路由

重定向也是通过 routes 中的redirect属性配置来完成

路由规则的优先级

同一个路径可以匹配多个路由,此时,匹配的优先级就按照路由的定义顺序:谁先定义的,谁的优先级就最高

路由模式

hash模式url里面永远带着#号,我们在开发当中默认使用这个模式。

history模式url里面没有#号

在开发app的时候有分享页面,这个分享出去的页面就是用vue做的,把这个页面分享到第三方的app里,有的app里面url是不允许带有#号的,所以要将#号去除那么就要使用history模式

上线之后:做刷新操作,会出现404错误,那么就需要和后端人配合让他配置一下apache或是nginx的url重定向,重定向到你的首页路由上。

路由模式的切换:

在index.js中找到vueRouter实例 在其中设置mode属性

const router = new VueRouter({
  mode: 'history',//设置路由模式的
  base: process.env.BASE_URL,
  routes
})

嵌套路由/多级路由/二级三级。。。。路由

二级以及以上的路由语法相同 都是使用children属性在路由规则中进行配置

创建:

1.创建多级路由页面组件

2.配置二级路由的路由规则

​ 要配置二级路由的规则首先你要知道他是谁的子路由(就在谁的路由规则中写children哦配置规则)

坑1 不加/

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/home.vue'
import Phone from '../views/phone.vue'
import Shop from '../views/shop.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: '/phone',
    name: 'Phone',
    component: Phone
  },
  {
    path: '/shop',
    name: 'Shop',
    component: Shop
  },
  {
    path: '/user',
    name: 'User',
    component: User,
    // 配置二级路由
    // 坑1:在写二级路由的path时候先不加/
    // 坑1:在写二级路由的path时候先不加/
    // 坑1:在写二级路由的path时候先不加/
    // 坑1:在写二级路由的path时候先不加/
    children:[
      {
        path: 'era',
        name: 'Era',
        component: Era
      },
      {
        path: 'erc',
        name: 'Erc',
        component: Erc
      },
      {
        path: 'erd',
        name: 'Erd',
        component: Erd
      },
    ]
  },
  {
    path:"/",
    redirect:"/home"
  }
  
]

const router = new VueRouter({
  mode: 'history',//设置路由模式的
  base: process.env.BASE_URL,
  routes
})

export default router

坑2 加/

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/home.vue'
import Phone from '../views/phone.vue'
import Shop from '../views/shop.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: '/phone',
//     name: 'Phone',
//     component: Phone
//   },
//   {
//     path: '/shop',
//     name: 'Shop',
//     component: Shop
//   },
//   {
//     path: '/user',
//     name: 'User',
//     component: User,
//     // 配置二级路由
//     // 坑1:在写二级路由的path时候先不加/
//     // 坑1:在写二级路由的path时候先不加/
//     // 坑1:在写二级路由的path时候先不加/
//     // 坑1:在写二级路由的path时候先不加/
//     children:[
//       {
//         path: 'era',
//         name: 'Era',
//         component: Era
//       },
//       {
//         path: 'erc',
//         name: 'Erc',
//         component: Erc
//       },
//       {
//         path: 'erd',
//         name: 'Erd',
//         component: Erd
//       },
//     ]
//   },
//   {
//     path:"/",
//     redirect:"/home"
//   }
  
// ]

const routes = [
  {
    path: '/home',
    name: 'Home',
    component: Home
  },
  {
    path: '/phone',
    name: 'Phone',
    component: Phone
  },
  {
    path: '/shop',
    name: 'Shop',
    component: Shop
  },
  {
    path: '/user',
    name: 'User',
    component: User,
    // 配置二级路由
    // 坑2:在写二级路由的path时候加/
    // 坑2:在写二级路由的path时候加/
    // 坑2:在写二级路由的path时候加/
    // 坑2:在写二级路由的path时候加/

    children:[
      {
        path: '/era',
        name: 'Era',
        component: Era
      },
      {
        path: '/erc',
        name: 'Erc',
        component: Erc
      },
      {
        path: '/erd',
        name: 'Erd',
        component: Erd
      },
    ]
  },
  {
    path:"/",
    redirect:"/home"
  }
  
]

const router = new VueRouter({
  mode: 'history',//设置路由模式的
  base: process.env.BASE_URL,
  routes
})

export default router

3设置二级路由的出口

默认情况下一级路由的出口被脚手架自动添加了 但是二级路由的出口必须手动添加

使用router-view 写在一级路由中






4.路由导航

坑1如果刚才创建path的时候没有加/

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

坑2如果刚才创建path的时候加了/


    
     <router-link to="/era">erarouter-link>  
     <router-link to="/erc">ercrouter-link>  
     <router-link to="/erd">erdrouter-link>  

动态路由匹配 路由传参

分类

params方式

(1)在需要接受数据的路由规则中设置 接受参数 :xxx

 {
    path: '/shopall/:随便写', //设置接受参数
    name: 'Shopall',
    component: Shopall
  },

(2)开始传递

声明式方式传递

 
      <router-link :to="{name:'Shopall',params:{xiaoming:'我是传递过去的参数params'}}">params声明式传参router-link>

编程式方法传递

课下自行尝试 并且添加笔记

(3)接受参数

this.$route.params.xxx

      
      {{this.$route.params.xiaoming}}

query方式

query方式不需要在路由规则中配置参数

query方式不需要在路由规则中配置参数

query方式不需要在路由规则中配置参数

query方式不需要在路由规则中配置参数

query方式不需要在路由规则中配置参数

(1)发送数据

编程式方式






声明式方式课下自行尝试与加笔记

(2)接收数据

this.$route.query.xxx

query与params区别

1.用法上的:query要用path来引入,params要用name来引入,接收参数都是类似的,分别是this. r o u t e . q u e r y . n a m e 和 t h i s . route.query.name和this. route.query.namethis.route.params.name。

2.url展示上

query 在url展示上 是key=val params在url展示上是只有val

因为query方式显示可key所以在数据传递上不那么安全 panams相对来说安全些

路由守卫/路由卫士/路由钩子/路由验证

就是vue路由在跳转的时候自动触发的一些钩子函数

全局守卫

对所有的路由在切换的时候都生效

全局前置守卫

进入路由之前触发

当一个导航触发时,全局前置守卫(在进入组件之前)按照创建顺序调用。
vue-router 提供的 router.beforeEach((to,from,next)=>{})可以方便地实现全局前置导航守卫
to:即将要进入的目标 路由对象
from: 当前导航正要离开的路由
next: 下一步执行

// 全局守卫
// to:去哪里
// from:从哪来
// next:下一步
router.beforeEach((to,from,next)=>{
  console.log(to)
  console.log(from)

  if(to.path=="/login"||to.path=="/zhuce"){
    next()
  }else{
    alert("您没有登录请登录后在试一试")
    next(false)
  }

})

全局后置守卫

进入路由之后触发

当一个导航触发时,全局后置钩子(在进入组件之后)调用。
vue-router 提供的 router.afterEach((to, from) => {})实现全局后置守卫
to:即将要进入的目标 路由对象
from: 当前导航正要离开的路由

路由独享的守卫

只对当前这一个生效

与全局前置守卫相比路由独享守卫只是对当前路由进行单一控制参数和全局前置守卫相同
在路由配置上直接定义 beforeEnter 进行路由独享守卫定义

 {
    path: '/',
    name: 'Home',
    component: Home,
    // 路由独享
    beforeEnter(to,from,next){
      alert("当前为vip页面 请您登录后访问")
      next("/login")
    }
  },

组件内守卫

组件内守卫是对某一个自定的组件范围在切换路由的时候触发的

进入之前

beforeRouteEnter(to, from, next) {}来进行进入组建前的钩子

离开的时候

在组件中使用beforeRouteLeave(to, from, next) {}来进行离开组件的钩子






路由懒加载

因为vue-router是单页面应用(就是只有一个显示页面 剩下的内容都是根据url在切换 在哪一个显示页面中切换路由页面组件)

默认情况 vue在第一次加载的时候会把我们写的所有路由页面全部都加载出来 本来是没有什么太大问题的 但是一旦页面变多 (由于第一次加载的时候需要加载很多页面 所以可能会造成浏览器白屏问题/首屏加载过慢的问题

解决:使用路由懒加载

使用

必须掌握的方式

import 方式

import Vue from 'vue'
import VueRouter from 'vue-router'



Vue.use(VueRouter)

const routes = [
  // 懒加载的方式
  {
    path: '/home',
    name: 'home',
    component: () => import('../views/home.vue')
  },
  {
    path: '/phone',
    name: 'phone',
    component: () => import('../views/phone.vue')
  },
  {
    path: '/shop',
    name: 'shop',
    component: () => import('../views/shop.vue')
  },
  {
    path: '/user',
    name: 'user',
    component: () => import('../views/user.vue')
  }
]

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

export default router

了解的方式—异步组件方式

  {
    path: '/shop',
    name: 'shop',
    component: resolve=>(require(["引用的组件路径"],resolve))
  },

扩展小知识----脚手架项目怎么启动?

去公司之后 每个项目的启动方式可能都不相同 所以 我们需要会查看项目是使用什么命令启动的

在项目的根路径下根路径下根路径下根路径下 查看package.json文件 找到scripts 节点即可知道怎么启动的

axios与拦截器封装

基本写法(不建议使用 太low 公司也不用 但是不讲不行)

1.下载axios npm install --save axios

2.要使用先引用 import axios from “axios”

拦截器

  1. 请求拦截器
    请求拦截器的作用是在请求发送前进行一些操作,例如在每个请求体里加上token,统一做了处理如果以后要改也非常容易。

  2. 响应拦截器
    响应拦截器的作用是在接收到响应后进行一些操作,例如在服务器返回登录状态失效,需要重新登录的时候,跳转到登录页。

创建

1.新建一个util文件夹(就是存放一些工具库的文件夹)在新建一个api文件夹

2.创建拦截器文件并且写入拦截器内容

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

3.封装数据请求

// 封装数据请求
// 引用拦截器
import service from "@/util/request.js"
// 2.开始封装请求
export function getlink(url){
    return new Promise((resolve,reject)=>{
        service.request({
            // 原来的axios怎么写 现在就怎么写
            url,
            method:"GET"
        }).then((ok)=>{
            resolve(ok)
        }).catch((err)=>{
            reject(err)
        })
    })
}

4页面使用

模拟数据mockjs

mockjs用来在vue中创建模拟数据接口的 方便我们在后台没有给我们接口的时候让我们的项目变成动态请求

1.下载 :npm install --save mockjs

2.我们在项目中要有模拟数据 那么需要写在那个位置呢?-----创建mock文件夹来容纳模拟数据

3.在mock文件夹下创建data文件夹用来容纳模拟数据 并且创建.js文件来编写mockjs代码

import Mock from "mockjs"
// 创建第一个请求
注意大小写   get要小写
// Mock.mock("请求地址你自己写","请求方式get/post",require("你的模拟数据json的地址"))
Mock.mock("/xiaoming/xiaohong","get",require("./data/demo.json"))

4.mock还需要在配置文件中引用千万不要忘

mock还需要在配置文件中引用千万不要忘

mock还需要在配置文件中引用千万不要忘

mock还需要在配置文件中引用千万不要忘

mock还需要在配置文件中引用千万不要忘

mock还需要在配置文件中引用千万不要忘

mock还需要在配置文件中引用千万不要忘

mock还需要在配置文件中引用千万不要忘

mock还需要在配置文件中引用千万不要忘

在main.js中引用

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

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

Vue.config.productionTip = false

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

后台发送参数

rest api 是前后端分离最佳实践,是开发的一套标准或者说是一套规范,不是框架。

规范:我告诉你应该怎么做 但是你不按照我说的可能不会出问题 但是出问题了你别找我

规则:我告诉你应该怎么做 你就必须怎么做 不按照我说的就完蛋了

restapi 就是在定义接口的时候 给接口设置更加语义化的名称

GET 获取数据

POST 发送数据

DELETE 删除

更新/修改

PUT 更多的意思是全部修改或者修改一些

PATCH 更多的意思是修改一个

怎么给后台发送参数

发送参数的时候 其实百分之70的情况可以使用如下写法

GET

http://localhost:3000/ceshi/get

请求参数是 name

使用params来进行参数的传递

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

DELETE

http://localhost:3000/ceshi/delete

参数 delid

同get 修改发送方式即可

PUT

http://localhost:3000/ceshi/put

参数 putid

同get 修改发送方式即可

POST

http://localhost:3000/ceshi/post

参数 postid

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)
        })
    })
}
   mounted(){
        // post发送参数的时候是没有办法直接发送的  因为默认情况下没有
        // 办法解析
        // 所以我们要设置post参数并且解析参数
        let usp=new URLSearchParams()
        // usp.append("你发送的key","你发送的val")
        usp.append("postid",9999)
        
        postlink("/api/ceshi/post",usp).then((ok)=>{
            console.log(ok)
        })
    }

解决跨域

jsonp

正向代理

必须在vue的根路径下创建一个vue.config.js文件

在其中写入如下配置

module.exports={
    // 配置跨域
    devServer: {
        proxy: {  //配置跨域
          '/api': {
            target: 'http://localhost:3000/',  //这里后台的地址模拟的;应该填写你们真实的后台接口
            changOrigin: true,  //允许跨域
            pathRewrite: {
              '^/api': '' 
            }
          },
        }
      },
}

修改请求地址为/api/xxxx 注意配置的代理之后项目必须重启

cors

拦截器更多配置与token的前端使用

1.拦截器更多配置—相应拦截

失败响应的status(状态码)需要在response中获得 error.response.status

// 添加响应拦截器
service.interceptors.response.use(function (response) {
    // 对响应数据做点什么-----后台能后正常给我们相应数据拦截的地方
 
    return response;
  }, function (error) {
    // 对响应错误做点什么-----404 500 403出现的位置
    console.log(error.response.status)
    switch (error.response.status) {
        case 500:
                // 处理的操作
                alert("当前连接超时")
            break;
        case 404:
                // 处理操作
                alert("您访问的页面不存在")
                // 把页面跳转到首页    
                break;
        default:
            return Promise.reject(error);
           
    }
    return Promise.reject(error);
  });

2.请求拦截(在请求头中发送koken)

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

先要在项目的根路径下创建vue.config.js

module.exports={

  devServer:{

​    port:8899// 修改端口

  }

}

自动开启 浏览器

module.exports={
    devServer:{
        port:8899,// 修改端口
        open:true//自动开启浏览器
    }
}

动态组件

多个组件使用同一个挂载点,并动态切换,这就是动态组件。





keep-alive—解决状态丢失

在上一个demo中我们不停的切换两个标签页的内容时候,会发现在练习我们中选择好的内容,切换路由之后会恢复初始化。
也就是说之前的状态丢失。原因是每次切换路由的时候,Vue 都创建了一个新的 组件实例

keepalive就是解决状态丢失的

使用

如果要使用 就在想保存组件状态的出口位置 使用keep-alice包裹

解决这个问题,我们可以用一个 元素将其路由出口包裹起来。在切换过程中将状态保留在内存中,防止重复渲染DOM,减少加载时间及性能消耗,提高用户体验性

使用在动态组件之上

    

使用在路由上
   
      
    

动态组件的属性

比如刚才我们动态组件举例 有三个组件 我使用包裹了动态组件 那么他就会保存所有的三个组件的状态

如果我在三个动态组件中指向保存两个的状态一个不保存怎么办?

include 需要缓存谁



    


exclude 不想缓存谁

注意

如果两个属性都写了 那么 exclude优先级大于include

keep-alive 的钩子函数

这两个生命周期函数一定是要在使用了keep-alive组件之上。

activated 类型:func 触发时机:keep-alive组件激活时使用;

deactivated 类型:func 触发时机:keep-alive组件停用时调用;

自定义指令

除了内置指令外, 用户自定义的指令
局部指令定义:
directives:{
自定义指令的名字:{
自定义指令钩子函数(el){
操作逻辑
}
}
},

自定义指令钩子函数

bind:绑定指令到元素上,只执行一次

inserted:绑定了指令的元素插入到页面中展示时调用,基本上都是操作这个钩子函数

update:所有组件节点更新时调用

componentUpdated:指令所在组件的节点及其子节点全部更新完成后调用

unbind:解除指令和元素的绑定,只执行一次






ref

思考vue中能用js的documet.getElementByxxxx进行dom操作吗?

可以使用

  mounted(){
        console.log(document.getElementsByTagName("p")[0].innerHTML)
    }

思考2思考vue中能用jquery进行dom操作吗?

可以使用

1.下载 npm install --save jquery\

2.,引用 import $ from “jquery”

3,.使用

为什么用ref

虽然在vue中 不建议不建议议不建议议不建议议不建议议不建议议不建议 大家使用dom操作

在有些极端情况下 不得不用 所以在vue中我们就是用ref进行vue中的dom操作

使用

ref 就是在vue中给dom元素起个名字

<em ref="demoem">我是测试vue的ref的例子em>

r e f s 这 个 就 相 当 于 d o m 查 找 t h i s . refs 这个就相当于dom查找 this. refsdomthis.refs.你给dom上起的ref名字

funb(){
            this.$refs.demoem.style.color="pink";
        }

ref绑定的位置

ref 绑定到dom元素之上

可以进行页面的dom操作

ref绑定到子组件之上

绑定到组件之上就可以获取到组件的所有属性和方法

请您能给我说下vue中父组件如何触发子组件的方法?

vuex

主要用于组件传值

正向传值 props

逆向传值 $emit()

同胞传值 (稍后讲)

夸层级/夸组件传值 ---- vuex

传统跨层级传值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JLyvLHGI-1624890895635)(.\img\3.bmp)]

新闻组件使用 联系组件的数据 传统方式进过几个正传和逆传 后期可维护性为0

简便的方式进行类似于跨层级传值

VUEX基本

vuex 状态(数据)管理工具

vuex就是一个数据仓库 把所有的组件数据 统一的放在vuex中 那么这样一来 那个组件想使用数据 那么这个组件直接就去vuex中进行读取即可 大大简化了传递数据的复杂性

vuex集中的数据存储,方便程序中的所有组件进行访问

创建vuex

自动创建方式

创建vue脚手架的时候选中vuex即可

手动创建(记住)

1.下载vuex npm install --save vuex

2.创建文件夹与文件

3.开始创建store(变量存储的就是vuex实例)

import Vue from 'vue'//引用vue
import Vuex from 'vuex' //引用vuex

Vue.use(Vuex)// 在vue中use(使用)vuex
// 暴露 vuex实例
export default new Vuex.Store({
  
 
})

4 把vuex实例引用注入到vue实例中

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'//引用vuex实例

Vue.config.productionTip = false

new Vue({
  router,
  store,//把vuex注入到vue实例中进行使用
  render: h => h(App)
}).$mount('#app')

vuex 的5大核心API

state—数据源

state的作用没有什么复杂的 就是用来创建数据的 vuex的所有数据必须必须必须只能放在state中

创建

import Vue from 'vue'//引用vue
import Vuex from 'vuex' //引用vuex

Vue.use(Vuex)// 在vue中use(使用)vuex
// 暴露 vuex实例
export default new Vuex.Store({
  state:{//存放数据的  可以存放任何数据
    text:"我是一个字符串",
    num:123,
    arr:[1111,2222,3333,444,5555]
  } 
 
})

使用数据state

在想使用数据的组件内 this.$store.state.xxx 使用vuex的state数据

<template>
  <div class="about">
    <h1>This is an about pageh1>
       <h1>{{this.$store.state.text}}h1>
  div>
template>

state里面存放的数据是响应式的,Vue组件从store中读取数据,若是store中的数据发生改变,依赖这个数据的组件也会发生更新

vuex的数据是响应式的 那么既然想是响应式 我们如何进行修改呢?

mutations

mutations 修改vuex的state数据 他只有一个作用就是修改

mutations是一个属性 他里面方的就是修改state的一个一个的方法。

创建

import Vue from 'vue'//引用vue
import Vuex from 'vuex' //引用vuex

Vue.use(Vuex)// 在vue中use(使用)vuex
// 暴露 vuex实例
export default new Vuex.Store({
  state:{//存放数据的  可以存放任何数据
    text:"我是一个字符串",
    num:123,
    arr:[1111,2222,3333,444,5555]
  } ,
  mutations:{//修改state的数据
    // 修改方法1(state 这个形参就是上面的state){},
    // 修改方法2(state 这个形参就是上面的state){},
    // 修改方法3(state 这个形参就是上面的state){},
    // 修改方法4(state 这个形参就是上面的state){},
    // 修改方法5(state 这个形参就是上面的state){},
    xiaoming(state){
        state.text="呵呵"
    }
  }
 
})

上面创建了一个修改的mutations

虽然有一个xiaoming的修改方法 但是我在组件页面中如何去调用它呢?

调用mutatioins中的修改方法 commit(“调用的方法名”)





vuex mutations 提交载荷 payload

  xiaoming(state,payload){
          state.text=payload.name
      }
      
  在组件调用
  this.$store.commit("xiaoming",{key:val,key:val})

扩展------必须要知道 很重要 vuex数据刷新丢失

<template>
  <div class="about">
    <h1>This is an about page</h1>
       <h1>{{this.$store.state.text}}</h1>
       <button @click="fun()">点我修改</button>
  </div>
</template>
<script>
export default {
// 解决vuex数据刷新丢失的问题
  created () {
        //在页面加载时读取localStorage里的状态信息
        if (localStorage.getItem("data") ) {
            //replaceState替换数据 Object.assign合并对象
            this.$store.replaceState(Object.assign({}, this.$store.state,JSON.parse(localStorage.getItem("data"))))
        } 
        //在页面刷新时将vuex里的信息保存到localStorage里
        window.addEventListener("beforeunload",()=>{
            localStorage.setItem("data",JSON.stringify(this.$store.state))
        })
      },
// 解决vuex数据刷新丢失的问题


  methods:{
    fun(){
      // 调用修改调用修改使用this.$store.commit("mutations的方法名")
      this.$store.commit("xiaoming")
    }
  }
}
</script>

actions 处理异步操作

actions 在vuex中的唯一作用就是用来处理异步操作的
actions 是vuex的一个属性 里面写的是一个一个的方法方法中存的就是异步操作

创建

import Vue from 'vue'//引用vue
import Vuex from 'vuex' //引用vuex

Vue.use(Vuex)// 在vue中use(使用)vuex
// 暴露 vuex实例
export default new Vuex.Store({
  state:{//存放数据的  可以存放任何数据
    text:"我是一个字符串",
    num:123,
    arr:[1111,2222,3333,444,5555]
  } ,
  mutations:{//修改state的数据
    // 修改方法1(state 这个形参就是上面的state){},
    // 修改方法2(state 这个形参就是上面的state){},
    // 修改方法3(state 这个形参就是上面的state){},
    // 修改方法4(state 这个形参就是上面的state){},
    // 修改方法5(state 这个形参就是上面的state){},
      xiaoming(state,payload){
          state.text=payload.name
      }
  },
  actions:{//处理异步操作
    // 一个一个的方法
    demoa(){console.log("我是第一个异步")},
    demob(){console.log("我是第2个异步")},
    democ(){console.log("我是第3个异步")},
  }
 
})

调用 actions 如果actions想被调用 必须必须必须要使用this.$store.dispatch(“actions名字”)





actions进行vue异步请求数据闭环

1.既然要进行异步请求 就要走vue中使用axios的那些东西 新建util 新建api 来进行请求与拦截器的封装

2.异步操作是在vuex actions中 所以我们需要在actions中创建一个方法 在方法中调用异步请求

import Vue from 'vue'
import Vuex from 'vuex'
// 引用
import {getlink} from "@/api/getapi.js"

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
  },
  mutations: {
  },
  actions: {
    // 需要在vuex中发送异步操作
    actiondemoa(){
        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)
        })

        }
  }
  },
  modules: {
  }
})

3.在需要发送请求的组件页面中 触发actions (this.$stroe.dispatch())触发了之后这个请求就发送了







4.数据已经在actions打印出来了 由于vuex的数据需要存储在state中 所以我们需要让actions请求来得数据修改state中的某个变量

在actions中要调用commit触发mutations修改state

import Vue from 'vue'
import Vuex from 'vuex'
// 引用
import {getlink} from "@/api/getapi.js"

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    arr:[]
  },
  mutations: {
    dataarr(state,payload){
      state.arr=payload
    }
  },
  actions: {
    // 需要在vuex中发送异步操作
    actiondemoa(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("dataarr",ok.data.data.commentList)

        })

     }
  
  },
  modules: {
  }
})

在页面使用

数据请求闭环示意图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k0FtBJ8y-1624890895637)(.\img\4.png)]

payload

acions也可以通过dispatch向actions中传递参数 那么这个参数就是payload

getters

getters 就是vuex的计算属性

vuex的getters与传统vue的computed计算属性有什么区别?

作用域 vue的计算属性处理出来的数据只能在当前组件内使用 但是vuex使用getters处理的数据可以在任何组件中多次使用

一条数据在一个组件内展示不同的形态的时候 使用vue的计算属性

一条数据在多个组件内想重复使用处理出来的不同形态数据的时候 使用vuex的getters

getters是一个vuex的属性

创建:

  getters:{//vuex的计算属性
    newtext(state){
      return state.text.toUpperCase()
    }
  },

使用

与使用state相同在组件中的计算属性当中使用 this.$store.getters.xxx来进行调用

modules

在Vue中State使用是单一状态树结构,应该的所有的状态都放在state里面,如果项目比较复杂,那state是一个很大的对象,store对象也将对变得非常大,难于管理。
module:可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。

1.在store文件夹中新建文件夹存放模块

2.编写属于组件的模块

export let aboutm={
    state: {
        demoa:"111",
        demob:"22",
        democ:"113331",
      },
      mutations: {
      },
      actions: {
      },
}

3.在vuex的配置中引用使用

import Vue from 'vue'
import Vuex from 'vuex'
import {aboutm} from "./modules/aboutm.js"
import {homem} from "./modules/homem.js"

Vue.use(Vuex)

export default new Vuex.Store({
 
  modules: {
    aboutm,homem
  }
})

4注意 如果使用了模块在读取数据的时候就有区别了

this.$store.state.模块名.xxxx

vantui

https://vant-contrib.gitee.io/vant/#/zh-CN/

组件传值

正向传值 props

逆向传值 $emit() ref

同胞兄弟传值 eventBus

中央事件总线 eventBus

创建一个新的Vue实例,以后它就承担起了组件之间通信的桥梁了,也就是中央事件总线。

1.新建一个文件夹用来容纳中央事件总线这个vue实例

// 中央事件总线就是新建一个vue实例用来当兄弟组件的数据桥梁
import Vue from "vue"
export default new Vue()

2 兄弟传值 demoa需要把数据给demob

(1)现在demoa中使用$emit()把数据通过自定义事件绑定到那个vue实例上\






(2)在demob中使用$on来监听接收实例上的自定义事件






1、创建一个事件总线,例如demo中的eventBus,用它作为通信桥梁
2、在需要传值的组件中用bus. e m i t 触 发 一 个 自 定 义 事 件 , 并 传 递 参 数 ( e m i t 前 加 美 元 符 ) 3 、 在 需 要 接 收 数 据 的 组 件 中 用 b u s . emit触发一个自定义事件,并传递参数(emit前加美元符) 3、在需要接收数据的组件中用bus. emit(emit)3bus.on监听自定义事件,并在回调函数中处理传递过来的参数

跨组件传值 vuex

Mixins 混入

mixins是vue中组件的一种复用技术 它可以把组件中很多相同的属性与方法等属性 提取出来方便多个组件进行复用

局部混入

1.创建一个文件夹用来容纳混入内容

let mixinsdemo={
    methods:{
        funb(){
            console.log("我是一个方法")
        }
    },
    data(){
        return {
            textm:"我是混入的变量"
        }
    }
}
export default mixinsdemo

2.在想使用的地方引用调用使用






全局混入

在任何组件中都可以使用
在main中引用 并且使用
import MinXin from ‘@/components/MinXins/index.js’
Vue.mixin(MinXin);

在组件中即可随意使用混入中的数据

$set

在你们入场开发的时候有没有遇见过data数据修改了 但是视图没有更新?

出现的原因:在vue的data里面对已经创建过的对象或者是数组 添加新的属性的时候,vue是不会数据修改了视图更新

​```





原理:

因为vue在初始化的时候会使用Object.defineProperty()劫持数据并且进行监听,由于js的限制vue中数据劫持只能在vue实例初始化的时候才能通过getter和setter来进行数据的拦截 后续对于对象或者数组添加的新内容vue没有办法进行数据的劫持也就没有了双向绑定 所以 会造成数据改变了视图没有更新

解决

$set方法加进行完成 $set可以对数据新增属性并且触发视图的更新

$(“你要操作的数据”,新增的key,新增的val)






nextTick

vue中实现响应式不是不是不是数据变化了dom立即改变 而是按照一定的策略来进行dom更新的

用代码证明数据变了dom没有立即变






原理解析

在vue修改数据之后,视图成不是立即改变的 而是等待同一个事件循环把所有的数据都改变之后 他才会统一的进行视图的修改。

1.首先我们要进行数据修改,是一个同步任务,同一事件循环的所有同步任务都在主程序上进行执行,他们会形成一个修改的执行栈。这个时候还没有牵扯到dom操作

2.vue会开启一个异步的列队,把刚才修改的数据进行监听

3.同步任务执行完毕之后 开始执行上面的异步列队 进行vue dom的更新

nextTick是什么

就是等待dom操作完毕后执行的一个vue的方法

nextTick使用场景

1.在vue的生命周期钩子里面created

  created(){
        // 在created中能不能读取dom上绑定的内容
        // 我就是想在created中读取dom上的内容
        // console.log(this.$refs.demoh.innerText)

        this.$nextTick(()=>{
            // 我会在vue的dom加载完毕后执行
            console.log(this.$refs.demoh.innerText)
        })

    },

2.我想等待数据修改之后打印出对应dom改变的值

  fun(){
            this.text="呵呵哒"
            // 如何证明数据变了dom没有立即改变呢?
            // console.log(this.$refs.demoh.innerText)
            this.$nextTick(()=>{
                 // 我会在vue的dom加载完毕后执行
                 console.log(this.$refs.demoh.innerText)
            })

        }

路由拆分—与大纲内容无关(了解掌握)

1.router下的index这个文件随着项目体量逐渐增大 会导致后期维护困难

你可能感兴趣的:(笔记,vue,js,vue.js,前端)