【VUE】Vue知识点整理

vue 基本概念

作者: 尤雨溪

渐进式自底向上增量开发mvvm框架

渐进式 可以和多种框架进行合并 vue是一个渐进式的框架(vue只会按照程序员的需要来进行功能的实现 不会影响到项目中没有用到vue框架的区域)只会做职责以内的事情

自底向上增量开发:先完成最基本的页面 然后再使用vue进行数据的绑定 一步步完成整个项目

    MVVM

    M    model       模型----》就是存储变量数据的地方
    V    view        视图----》页面 html所写的那些东西
    VM   viewModel   视图模型----》就是页面与数据之前桥梁

helloword

1、获取vue库文件(使用npm(包管理工具)来进行获取)

(1)在你要写项目的文件夹 上打开cmd

(2)初始化 npm init -y

(3) 下载 npm install --save xxx (默认最新版 指定版本 npm install --save xxx@你的版本)

如果太慢 可以切换成淘宝镜像

安装:npm i -g cnpm --registry=https://registry.npm.taobao.org

(4)开始编写vue的helloword


<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.js">script>
head>
<body>
    

     
     <div id="demoDiv">
        <h1>{{text}}h1>
        <h1>{{obj.name}}h1>
     div>
     <script>
        //  3。vm层创建(就是vue实例)
        new Vue({
            // 4.创建m层数据
            data:{
                text:"你好",
                num:18,
                bool:true,
                arr:[111,223,444,555,6,6,7,7],
                obj:{
                    name:"xixi",
                    age:18
                }
            },
            // 5.关联视图层
            el:"#demoDiv"
        })

     script>
    
body>
html>

el:创建的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.js"> script>
head>
<body>
    <div id="demoDiv">
        <h1>{{}}中不建议复杂的内容h1>
        {{num+demo}}
        <h1>{{bool?"你好":"你坏"}}h1>
        <h1>{{text}}h1>
        <h1>{{text.toUpperCase()}}h1>

    div>
    <script>
        new Vue({
            el:"#demoDiv",
            data:{
                num:2,
                demo:3,
                bool:false,
                text:"abcdefghijk"
            }
        })

    script>
body>
html>

数据渲染

声明式渲染

我们只需要告诉程序你要干什么 他就会自动完成

命令式渲染

在js中我们使用的所有变量的插入页面的过程 就是命令式 我们需要指挥程序一步步干什么

传统的css就属于命令式渲染,效率较低


<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>
head>
<body>
    <h1 id="demoh">h1>
    <script>
        let text="你好"
        document.getElementById("demoh").innerHTML=text
    script>
body>
html>

数据驱动

vue就是一个js框架 作用就是把数据用更加简单的方式插入到页面中 vue可以根据数据的改变让页面也随之发生改变

指令

基本概念

在vue中带有v-前缀的html特殊属性

指令的作用:是给html添加特殊的功能

语法:写在html的开标签中 v-指令=“指令值”

v-model

作用: 给表单元素进行数据绑定的

语法: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.js"> script>
head>
<body>
    <div id="demoDiv">
        <h1>v-modelh1>
        

        <input type="text" v-model="text"/>
        
        <em>{{text}}em>



    div>
    <script>
        new Vue({
            el:"#demoDiv",
            data:{
              text:"你好"
            }
        })

    script>
body>
html>

双向绑定的原理

原理:数据劫持发布者订阅者模式

数据劫持:数据拦截 vue中使用Object.defineProerty() 就是可以监听着我们data中的模型数据 当数据改变的时候 Object.defineProerty() 就会触发 模型改变 他会通知视图改变 视图改变 就会通知模型进行改变 会监听着改变 与修改。

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

v-show

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

语法:v-show=“布尔值” true显示 false隐藏


<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.js"> script>
head>
<body>
    <div id="demoDiv">
        <h1>v-showh1>
        <h1 v-show="bool">控制我的显示和隐藏h1>
    div>
    <script>
        new Vue({
            el:"#demoDiv",
            data:{
               bool:false
            }
        })

    script>
body>
html>

v-on/@

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

语法: v-on:事件(不加on)=“函数” v-on:click=“fun()” v-on:change=“fun()”

简写语法: @事件=“函数”

函数写在那?

函数写在与el data 同级的位置 使用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.js"> script>
head>
<body>
    <div id="demoDiv">
        <h1>v-onh1>
        <button v-on:click="fun()">点我打印内容button>
        <button @click="funb()">简写button>

    div>
    <script>
        new Vue({
            el:"#demoDiv",
            data:{
        
            },
            methods:{
                fun(){
                    console.log("你好")
                },
                funb(){
                    console.error("你坏")
                }
            }
        })

    script>
body>
html>

v-for

作用:遍历data中的数据

语法:v-for="(遍历的值,遍历的下标) in 要遍历的数据名字"

<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.js">script>
head>
<body>
    <div id="demoDiv">
        <h1>v-forh1>
        <ul>
            <li v-for="(v,i) in arr">
                {{v}}------{{i}}
            li>
        ul>

    div>

    <script>
        new Vue({
            el:"#demoDiv",
            data:{
                arr:["EZ","MF","NOC","VN"]
            },
            methods:{

            }
        })

       
    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.js">script>
head>
<body>
    <div id="demoDiv">
        <h1>v-forh1>
        <ul>
            <li v-for="(v,i) in arr">
                {{v}}------{{i}}
            li>
        ul>
        <hr/>

        <table border="1">
            <tr v-for="(v,i) in obj">
                <td>{{v.name}}td>
                <td>{{v.age}}td>
                
            tr>
        table>

    div>

    <script>
        new Vue({
            el:"#demoDiv",
            data:{
                arr:["EZ","MF","NOC","VN"],
                obj:[
                    {name:"huanghuang",age:27},
                    {name:"bilin",age:29},
                    {name:"xixi",age:26}
                ]
            },
            methods:{

            }
        })

       
    script>
body>

v-bind/:

作用: 给html的标签属性插入变量

语法: v-bind:html的属性=“变量” 简写 :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.js">script>
head>
<body>
    <div id="demoDiv">
        <h1>v-bindh1>
       <a v-bind:href="ahref">{{text}}a>
       <a :href="ahref">{{text}}a>

    div>

    <script>
        new Vue({
            el:"#demoDiv",
            data:{
                text:"点我去百度",
                ahref:"http://www.baidu.com"
            },
            methods:{

            }
        })

       
    script>
body>
html>

v-if 全家桶

v-if

作用:判断dom是否加载

语法: v-if=“布尔值” true加载 false不加载


<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.js">script>
head>
<body>
    <div id="demoDiv">
        <h1>v-ifh1>
      
        <input type="checkbox" v-model="bool">
        <h1 v-if="bool">我是测试v-if的h1>
        <h1 v-show="bool">我是测试v-show的h1>

    div>

    <script>
        new Vue({
            el:"#demoDiv",
            data:{
               bool:true
            },
            methods:{

            }
        })

       
    script>
body>
html>

v-if与v-show的区别

v-if 是对dom元素进行添加和移除 v-if 在加载的时候对性能损耗低 v-if在元素频繁切换的时候性能损耗高

v-show 是对dom元素使用css进行显示和隐藏 v-show 在加载的时候对性能损耗高 v-if在元素频繁切换的时候性能损耗低

v-else

作用: v-if不符合的时候执行else

语法:必须配合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.js">script>
head>
<body>
    <div id="demoDiv">
        <h1>v-elseh1>
      
        <input type="checkbox" v-model="bool">
        <h1 v-if="bool">你好h1>
        <h1 v-else>你坏h1>
       

    div>

    <script>
        new Vue({
            el:"#demoDiv",
            data:{
               bool:true
            },
            methods:{

            }
        })


       
       
    script>
body>
html>

v-else-if

作用 可以对多个内容进行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.js">script>
head>
<body>
    <div id="demoDiv">
        <h1 v-if="num==1">h1>
        <h1 v-else-if="num==2">h1>
        <h1 v-else-if="num==3">上厕所h1>
        <h1 v-else-if="num==4">在睡h1>
        <h1 v-else>什么也没有干h1>

    div>

    <script>
        new Vue({
            el:"#demoDiv",
            data:{
              num:8
            },
            methods:{

            }
        })

       
    script>
body>
html>

v-text

作用:在网页中展示纯文本内容 同{{}}类似的功能

语法: v-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.js">script>
head>
<body>
    <div id="demoDiv">
        <h1>v-texth1>
       <h1>{{demo}}h1>
       <h1 v-text="demo">h1>

    div>

    <script>
        new Vue({
            el:"#demoDiv",
            data:{
               demo:"我是文本"
            },
            methods:{

            }
        })

       
    script>
body>
html>

v-text与{{}}的区别

相同点: 都可以向页面中插入内容

不同点:{{}}模板插值的语法 而v-text是指令

           v-text可以解决屏幕闪烁问题

屏幕闪烁

当用户网络很慢的时候 由于js没有加载 可能会导致页面出现{{}} 问题 然后js加载成功之后 {{}}消失变成正常的数据展示 可能会在成用户体验不好

解决:

1.使用v-text

2.使用v-cloak指令来解决 当前这个指令的作用是保持元素上直到关联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.js">script>
    <style>
        [v-cloak]{
            display: none; //解决屏幕闪烁问题
        }
    style>
head>
<body>
    <div id="demoDiv" v-cloak>
        <h1>v-texth1>
       <h1>{{demo}}h1>
       <h1 v-text="demob">h1>

    div>

    <script>
        new Vue({
            el:"#demoDiv",
            data:{
               demo:"我是文本1",
               demob:"我是text"
            },
            methods:{

            }
        })

       
    script>
body>
html>

v-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.js">script>
head>
<body>
    <div id="demoDiv">
      <div>
          {{text}}
      div>
     <div v-text="text">

     div>
     
     <div v-html="text">div>

    div>

    <script>
        new Vue({
            el:"#demoDiv",
            data:{
               text:"我是斜体"
            },
            methods:{

            }
        })

       
    script>
body>
html>

v-once

作用:一次性插值


<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.js">script>
head>
<body>
    <div id="demoDiv">
        <input type="text" v-model="text">
        <h1>{{text}}h1>
        <h1 v-once>{{text}}h1>
        <h1>{{text}}h1>

    div>

    <script>
        new Vue({
            el:"#demoDiv",
            data:{
               text:"你好么么哒"
            },
            methods:{

            }
        })

       
    script>
body>
html>

watch监听

监听data中的数据,如果数据改变了,watch就会收到通知,调用一个函数。(我们就可以在这个函数中完成指定的逻辑)

语法:whtch写在与 el data methods同级

​ 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.js">script>
head>
<body>
    <div id="demoDiv">
        <input type="text" v-model="inputval">
    div>
    <script>
        new Vue({
            el:"#demoDiv",
            data:{
                inputval:""
            },
            methods:{
                
            },
            // 监听
            watch:{
                inputval(newval,oldval){
                    console.log(newval+"----"+oldval)
                }
            }
        })
    script>
body>
html>

watch首次加载的时候能触发吗?

首次加载不会触发

如何让watch首次加载能触发?

首次加载执行函数需通过其immediate 属性进行配置,默认为false
监听数组值变化需通过其deep属性进行配置,默认为false

watch:{
    "aaa":{
     immediate:true, // 首次加载的时候执行函数
     deep:true, // 深入观察,监听数组值,对象属性值的变化
     handler:function(){
     }
}

vue-cil脚手架

安装4x(脚手架版本)

1.必须有node

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

3.全局下载脚手架 npm install -g @vue/cli (只需要下载一次)

4.查看版本 vue --version

5.创建项目

​ 5.1 在项目所在路径打开cmd

​ 5.2 在打开的cmd里输入 vue create 项目名 (选择第三个 手动选择)

6.启动项目

​ 6.1 cmd里cd到项目所在路径

​ 6.2 cmd里输入 npm run serve

第三方项目如何启动

1.查看项目文件夹中是否存在 node_modules?如果没有,在cmd里cd到当前项目路径 使用 npm install 重新下载依赖

2.在项目目录下找到package.json文件,在文件中查看scripts节点

所有的命令都需要使用npm run 配置项 (有一个特例 npm start)

下载空项目后需要做的

1.删除src下commponents文件夹的helloworld.vue文件

2.删除src下app.vue的内容

  

3.VSCode里下载插件:vetur

4.在src下的commponents中新建.vue文件

5.在app.vue中引用自己创建的.vue文件






.vue文件——单文件组件

.vue文件有三部分

template部分 就是今后写html的地方



//style部分 CSS


使用data






vue组件的data为什么是一个函数而不是一个对象?

JavaScript中的对象是引用类型的数据,当多个事例引用同一个对象时,一个实例对这个对象进行操作,其他实例中的数据也会发生变化

在vue中,为了使每个组件都有自己的数据空间,不干扰其他组件的运行,就把他写成函数的形式,数据以函数返回值的形式定义,当我们每次复用组件的时候,就会返回一个新的data。

methods

与本地模式写法相同






watch

与本地模式写法相同






事件对象——$event

谁触发这个事件 事件对象就是谁






修饰符

vue中对于事件上面添加了一个新的内容修饰符,通过修饰符可以对当前这个事件来设置更多辅佐性的功能

语法:v-on: 或@事件.修饰符="函数"

1.按键修饰符

对键盘上面的按键进行指定

.up .down .left .right .ctrl .enter .space






2.事件修饰符

阻止冒泡 .stop
阻止默认行为 .prevent
设置捕获(与事件冒泡相反) .capture
只触发一次 .once
只触发自己范围内的事件,不包含子元素的 .self

修饰符同时可以串联

 
          





计算属性——computed

vue的属性 这个属性是有计算功能的(对data数据进行计算展示)

语法:写在与data methods等同级位置

一条数据 在多个位置 以不同形态展示的时候 可以使用计算属性computed

一个变量 在显示之前 进行数据处理 也可以使用计算属性computed

computed:{

计算出的结果变量(){

return 计算内容

}

}

数组字符串截取时

splice不可使用 会报错。splice会对改变原数组

slice 可以使用 slice不会对原数组产生影响







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






计算属性与方法最大的区别是

计算属性走缓存,只要计算属性处理过数据之后,数据在没有改变的时候,无论在页面调用多少次,它都只执行一次,剩下的调用都是从缓存中进行读取的,节省资源。

函数(方法)只要被调用就会执行,调用多少次就会执行多少次,比较消耗资源

计算属性(computed)与监听(watch)的区别

计算属性与监听都是对data的数据进行相关的操作

计算属性是依赖data的数据,并且对data的数据进行处理并把处理后的结果返回

监听仅仅是监听,当data的数据改变时它会触发一个函数,来完成一些逻辑

前后台交互

axios

axios是一个基于promise的第三方数据请求库

下载:npm insatll --save axios







上面代码有跨域问题,会出现如下错误

跨域

浏览器的安全机制,不同源(不同端口 不同协议 不同域名)就会造成跨域

解决跨域
1.jsonp(面试会问,工作不用)

2.代理跨域
	devServe代理跨域
	nginx反向代理
3.cors

代理跨域:

devServe代理跨域

方式:

​ 1.需要在vue项目的根目录下创建一个vue.config.js文件

​ 2.在vue.config.js文件中写以下内容:

module.exports={
    devServer:{
        proxy:{
            "/api":{
                target:"http://www.weather.com.cn/",
                changeOrigin:true,
                pathRewrite:{
                    "^/api":""
                }

            }
        }
    }
}



​ 3.【重要】修改项目的请求路径为/api

​ 4.因为上一步修改了配置文件,项目必须重启(重新npm run serve)

拦截器

在发送请求的时候,在项目中 每次请求都要携带一些参数数据的时候,可以使用拦截器,把每次发送请求时需要携带的数据,使用拦截器先拦截下来 添加要携带的参数,再发送出去,减少代码重复编写。

拦截器分为两种:

1.请求拦截

2.响应拦截(404或其他拦截错误时给用户作出相应提示)

使用:

1.在项目的src文件夹新建两个文件夹

api===存储数据请求封装

util===存储工具库的

2.创建拦截器 在util文件夹下新建service.js文件,写以下内容:

import axios from "axios"
// 创建axios实例
let service=axios.create()

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

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

  export default service

响应拦截

import axios from "axios"
// 创建axios实例
let service=axios.create()

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

// 添加响应拦截器
service.interceptors.response.use(function (response) {
    // 对响应数据做点什么   当相应成功正确的时候你所写的地方
    return response;
  }, function (error) {
      console.log("http状态吗",error.response.status)

      switch (error.response.status) {
          case 404:
            alert("哎呀网络连接超时!!!!")      
          break;
          case 500:
            alert("当前服务器正在维护请您稍后再试")      
          break;
      
          default:
             alert("您的错误反馈后台技术已经接收  请您稍后在次访问此页面!") 
              break;
      }


    // 对响应错误做点什么
    return Promise.reject(error);
  });

  export default service

请求拦截

就是在发送请求的时候 会先经过他 可以在请求拦截里面添加每次发送请求都要携带的参数

请求封装

1.在src/api文件夹下创建一个getapi.js文件封装数据请求

import service from "@/util/service.js"

// 开始封装数据请求
function getlink(url){
   return new Promise((resolve,reject)=>{
    //    开始写你的数据请求
        service.request({
            url,
            method:"GET"
        }).then((ok)=>{
            resolve(ok)
        }).catch((err)=>{
            reject(err)
        })
   })
}


export default getlink

2.调用数据请求

模拟数据===mockjs

1.下载 npm install --save mockjs

2.在src文件夹下创建一个mock文件夹(用来存放模拟数据的文件夹)

3.编写模拟数据json与mock配置

​ 3.1在src/mock文件夹下创建.json文件用来编写模拟数据

​ 3.2配置模拟数据==在mock文件夹里新建index.js文件

// 1.引用mockjs
let Mock=require("mockjs")
// 2.配置
// Mock.mock("模拟数据地址","方式get/post",require("你的json数据"))
Mock.mock("/data/list/xiaoming","get",require("./data.json"))

4.在main.js里使main.js和mockjs建立关联

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

// 1.引用组件
import Ceshi from "./components/ceshi.vue"
// 2.配置成为全局组件
// Vue.component(给你引用的组件起个调用名,你引用的组件)
Vue.component("Ceshi",Ceshi)


// 建立mock与项目的关系
// 因为如果我们只写了文件夹的地址  那么他会自动找到这个文件夹的index
// .js
require("./mock")

Vue.config.productionTip = false

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

发送get数据

get请求 发送数据使用params发送

发送post数据

使用data

发送数据需要进行转换

post发送数据需要进行转换URLSearchParams( )之后 后台才能正常接收到数据

fun(){
      // 发送post需要使用
     let usp= new URLSearchParams()
    //  每条数据都需要使用append进行绑定
    //  usp.append(你要发送数据的key,val)
     usp.append("uname",this.inputaval)
     usp.append("upwd",this.inputbval)
      link("/api/niubi_userlist/user/denglu","post",{},usp).then((ok)=>{
        console.log(ok)
      })
    }
  }

vue.congif.js

运行项目后浏览器自动开启===修改端口号

1.根目录下新建vue.config.js文件

  1. moudle.exports={
    	devServer:{
         // 自动开启
    	open:true,
    	port:8888//修改端口号 手动指定端口号
    	}
    }
    

修改文件夹引用别名

在项目的根目录下vue.config.js文件中

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

    // 配置引用别名
    configureWebpack:{
        resolve:{
            alias:{
                // 别名:真实路径
                "niubi":"@/utils"
            }
        }
    }
}

组件

基本概念

组件自定义控件(通过组件可以把一个页面拆分成一个个小UI模块,然后把它们拼装到一块形成一个完整的页面)

通过组件,创建出可复用的UI代码块

组件的本质:自定义标签(单标签,双标签均可)

组建的分类

1.局部组件===components

只能在部分地方使用

​ 1.在src下的components文件夹创建对应的组件.vue文件并且编写内容

​ 2.显示组件【在APP.vue中进行】(默认情况下 只创建组件 是不会在页面显示的)

​ (1)引用(import from)

​ (2)调用(components+组件名)

在data、methods的同级位置 创建components:{调用的组件}

​ (3)使用






2.全局组件===component

可以在项目的任何地方使用(想过想在多个地方使用某组件,可以把这个组件变成全局组件)除非前期设计好组件的使用,否则建议少用全局组件(全局组件名会造成项目的污染)

1.在main.js中进行引用配置

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

// 1.引用组件
import Ceshi from "./components/ceshi.vue"
// 2.配置成为全局组件
// Vue.component(给你引用的组件起个调用名,你引用的组件)
Vue.component("Ceshi",Ceshi)

Vue.config.productionTip = false

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

2.在想使用全局组件的地方直接用

​ 比如想在a.vue组件中使用,在页面如下位置引入


组件样式隔离===scoped

各组件之间样式互不干扰

使用scoped后,当前样式仅对当前组件生效


父子组件

组件与组件之间是可以相互嵌套的,这种嵌套关系就是父子组件

组件的作用域

组件与组件之间的数据可以相互使用吗?

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

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

组件与组件之间是一个完整的独立的个体,数据与数据之间默认是不能相互直接使用的

组件传值

父子组件传值===正向传值(父>子)===props

props是一个属性

普通传值

1.在子页面中 data methods同级使用 props:[接收父组件传值的变量1,接收父组件传值的变量2,接收父组件传值的变量3,接收父组件传值的变量.......]




2.在子组件中进行使用




3.父组件传值


传值验证

props验证,在传统的props验证的写法中,我们可以给子组件传递任何数据类型的数据

但是在一些特殊情况下这样可能会出问题(如果子组件拿到数据需要对数据进行操作的时候,可能不同的数据类型所展示的结果就会出现偏差)

props验证如果不成功,不会影响页面的展示,只会在控制台给出一个警告提示

语法:

1.在data methods等同级位置

export default {
	props:{
	要接收的变量:数据类型//Number 数字类型、String 字符串类型、				   Boolean 布尔类型
	}
}





2.使用

3.传递

同基本写法

子>父组件传值===逆向传值

逆向传值默认不允许,想进行逆向传值的话,必须通过事件来触发传递

1.在子组件中创建一个事件触发一个函数,进行逆向传值的准备







2.在子组件中抛出子组件要传递的数据===把数据绑定到自定义事件之上

自定义事件-$emit

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






3.父组件接收子组件抛出的数据===接收自定义事件使用数据






ref完成逆向传值

只需要在组件之上使用ref即可直接取出子组件的数据

兄弟组件传值===同胞传值-中央事件总线(eventBus)

在同一父组件下的子组件进行相互数据传递

中央事件总线(eventBus):凌驾于两个兄弟组件之上的一个空的vue实例

1.在src文件夹下创建eventBus文件夹(容纳中央事件总线的文件夹),新建index.js文件

// 容纳中央事件总线
import Vue from "vue"
export default new Vue

2.在要传递的组件(src/components/里面的组件文件)上抛出






3.在要接收的组件中接收

$on 监听实例上的自定义事件





vuex-跨组件传值-爷爷传给孙子

vuex:状态(数据)管理工具

vuex可以把整个项目的数据集中地管理起来,方便组件与组件的使用(组件想使用数据, 不需要使用复杂的传递方式了,直接去vuex中进行数据的获取)

传统的vue是单向数据流,如果是兄弟或者是跨层级的组件在进行传递的时候,vue就非常麻烦,vuex就可以进行上述传递,简化了数据传递的复杂度

src/store文件夹 用来容纳vuex的文件夹

vuex创建流程

1.下载 npm install --save vuex

2.在src文件夹下新建store文件夹 并且新建index.js

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

Vue.use(Vuex)

export default new Vuex.Store({

})

3.在main.js中引用vuex文件 并且在vue实例上注册

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

Vue.config.productionTip = false

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

vuex5大属性

state属性:数据源

vuex的所有数据都在state中进行创建

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

Vue.use(Vuex)

export default new Vuex.Store({
  state: {//创建数据的类似于组件中的data
    text:"你好",
    age:18,
    arr:[111,2222,33333],
    obj:{
      love:"女"
    }
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
})

1.取值方式一

任意组件想要使用数据,使用this.$store.state.xxx






2.取值方式二

计算属性computed

​ 防止数据没有请求到的时候页面会报错






mutations属性:vuex的数据修改

vuex中state的数据不能直接修改

mutations里面封装的是一个个函数,每个函数就是一个修改的动作

如果要触发mutations的修改动作 我们要使用commit这个方法来进行调用commit触发mutations修改

1.通过事件触发commit来调用修改操作






2.去store中编写对应的mutations修改动作

  mutations: {
    uptext(){
      
    }

  },

3.开始修改

  mutations: {
    // 第一个形参state就是指向上面的state数据源
    // 第二个形参接收的就是commit方法中的第二个参数
    uptext(state,payload){
      state.text=payload.newtext
    }

  },
扩展===vuex数据修改刷新丢失

在vuex中如果修改数据之后,页面刷新一次,那么页面的数据会恢复成默认值。

解决方法:在页面刷新的时候,把vuex里的数据转成字符串,转成对象,存储到本地,页面刷新后,将本地存储的数据重新渲染到页面中

 created() {
    //在页面加载时读取sessionStorage里的状态信息
    if (sessionStorage.getItem("store")) {
      this.$store.replaceState(
        Object.assign(
          {},
          this.$store.state,
          JSON.parse(sessionStorage.getItem("store"))
        )
      );
    }

    //在页面刷新时将vuex里的信息保存到sessionStorage里
    window.addEventListener("beforeunload", () => {
      sessionStorage.setItem("store", JSON.stringify(this.$store.state));
    });
  },
actions属性===触发异步操作

actions是一个触发器,可以帮我们触发一个异步操作(异步请求)

actions中一个个方法,每一个方法就是一个异步的动作

actions调用的话,使用dispatch()调用

1.页面通过dispatch来触发actions






actions创建对应的方法

  actions: {
    // context形参  就是store对象
    demoLink(){
      console.log("我是actions")
    }
  },
数据请求闭环
  //   
    created(){
        // 2.通过dispatch触发一个actions
        this.$store.dispatch("getaxios",{url:"/data/one"})
    }

3.编写对应的actions

actions: {
 
    // 3编写对应的actions
    getaxios(){

    }
  },

4.引用数据请求 并且发送

import Vue from 'vue'
import Vuex from 'vuex'
// 4.引用数据请求
import getlink from "@/apis/getapi.js"

Vue.use(Vuex)

export default new Vuex.Store({
  state: {//创建数据的类似于组件中的data

  },
  mutations: {
   

  },
  actions: {
   
    // 3编写对应的actions
    getaxios(context,payload){
      console.log(context)
      // 5.发送一部操作
      getlink(payload.url).then((ok)=>{
        console.log(ok)
      })
    }
  },
  modules: {
  }
})

  actions: {

    // 3编写对应的actions
    getaxios(context,payload){
      console.log(context)
      // 5.发送一部操作
      getlink(payload.url).then((ok)=>{
        console.log(ok.data.data)
        // 6.把请求来的数据交给mutations来修改state
        context.commit("uparr",{arrdata:ok.data.data})
      })
    }
  },

7.创建对应的mutations

  // 7创建对应的mutations
    uparr(state,payload){
      // 8把请求来的数据修改state
      state.arr=payload.arrdata
    }

在页面展示






getters属性===vuex的计算属性

getters可以对一个数据在不同位置展示出不同的形态使用

getters处理的数据 任何组件都能用

vue的计算属性处理的数据只能当前组件使用

定义getters

 getters:{
    // 里面就一个形参  state代表的就是数据源
      newdemo(state){
        return state.demo.toUpperCase()
      }
  }

使用

在想使用的地方直接使用 this.$store.getters.xxx(getters里的函数名)即可获取到处理好的数据

module 模块

可以把原来写在一起的数据 修改 异步操作 计算属性 按照页面等进行分类管理

1.新建文件用来单独放置上述的属性

let userm={
    state: {
        text:"我是user的数据"
    },
    mutations: {
     
    },
    actions: {
    },
   
    getters:{
     
    }, 
}
export default userm

2.把模块注入到vuex中

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

// 引用模块
import Homem from "./modules/homem.js"
import Phonem from "./modules/phonem.js"
import Userm from "./modules/userm.js"

Vue.use(Vuex)

export default new Vuex.Store({
 
    // 注入
  modules: {
    Homem,
    Phonem,
    Userm

  }
})

3.使用数据 this.$store.state.模块名.xxx

slot槽口/插槽

用来混合父组件和子组件自己的模板(就是可以在组件被调用的时候向其内部插入新的dom节点)

使用方法:

1.在要抛出的组件使用:

solt子组减的值

2.在要接收的组件使用:

如果调用的时候组件使用的是双标签,默认情况下不能在他的开关标签中插入新的内容






基本插槽

在你想插入新内容的组件中,放置一个 ,外部的内容就会显示在slot插入的位置

槽口虽然只有一个 但是外部插入的所有内容都在这一个上面显示 后期不好管理


具名插槽-给槽口带个名字

1.定义槽口的时候 使用name创建槽口的名字

 
      

2.插入的时候需要指定往那个槽口插入 使用slot属性


作用域插槽

路由

为我们完成页面之间的跳转,让我们完成单页面多视图的应用(SPA)

vue-router库来实现路由

创建

手工创建

1.下载vue-route库

2.创建views文件夹 并写入路由页面组件

3.配置路由规则

​ 3.1新建router文件夹 并新建index.js文件

​ 3.2在index.js文件中

import Vue from 'vue'//引用vue
import VueRouter from 'vue-router'引用vuerouter


Vue.use(VueRouter)在vue中使用路由功能

创建了路由规则配置
const routes = [
  {
    path: '/home',
    name: 'Home',
    component: Home
  },
  
]
实例化路由对象   并且设置路由模式与路由规则的传入
const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})
暴露
export default router

4.注入路由 main.js文件中注入

import Vue from 'vue'
import App from './App.vue'
import router from './router'  引用路由


Vue.config.productionTip = false

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

vue-cli自动创建

在创建vue脚手架项目的时候 要选中router项

在项目创建好之后 src文件夹下多了两个文件夹

views===页面文件夹

router===配置路由的

创建一级路由

1.在/src/views文件夹下创建对应页面

2.配置路由页面规则 /src/router/index.js中进行配置

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

// 1.引用路由页面到路由规则配置文件中
import Home from '../views/home.vue'
import Gouwu from '../views/gouwu.vue'
import Jingxi from '../views/jingxi.vue'
import Fenlei from '../views/fenlei.vue'
import Wode from '../views/wode.vue'

// 在vue中使用路由功能
Vue.use(VueRouter)
// 2、配置路由规则
const routes = [
  {
    path: '/',//url路径
    name: 'Home',//给当前的规则起个名字
    component: Home //你匹配的路由页面
  },
  {
    path: '/gouwu',//url路径
    name: 'gouwu',//给当前的规则起个名字
    component: Gouwu //你匹配的路由页面
  },
  {
    path: '/fenlei',//url路径
    name: 'fenlei',//给当前的规则起个名字
    component: Fenlei //你匹配的路由页面
  },
  {
    path: '/jingxi',//url路径
    name: 'jingxi',//给当前的规则起个名字
    component: Jingxi //你匹配的路由页面
  },
  {
    path: '/wode',//url路径
    name: 'wode',//给当前的规则起个名字
    component: Wode //你匹配的路由页面
  },
]

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

export default router

3.设置路由出口,在app.vue中 使用router-view进行标识

路由导航

分类

声明式==标签的跳转方式

router-link来进行页面的切换 其中to属性来设置跳转地址

选中的样式类

在vue路由导航中 会默认给我们选中的当前导航添加样式类 router-link-active

如果在配置路由的时候,路由规则的path中,有单独的/ ,那么无论是否选中当前这个路由,都会添加相应的类名。解决方法:在配置路由的时候,path中不设置单独 /

但是如果在设置路由规则path的时候,没有设置单独的 / 那么第一次进入页面的时候就没有默认路由规则,也就是没有默认的首页,解决方式就是使用重定向

编程式==js的方式进行跳转

this.$router.push("/要跳转的页面")






this.$router.replace("/要跳转的页面")===不能回退,付款等页面使用

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

重定向-redirect

重新定位方向 可以在第一次进入页面的时候帮助用户自动把页面进行指定为位置的切换

const routes = [
  {
    path: '/home',
    name: 'Home',
    component: Home
  },
  {
    path: '/shop',
    name: 'shop',
    component: Shop
  },
  {
    path: '/phone',
    name: 'phone',
    component: Phone
  },
  {
    path: '/user',
    name: 'user',
    component: User
  },

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

]

404页面

url中出现了没有配置过得路由页面,就会出现白屏

解决方法:需要给用户没有在url中没有配置过路由的情况下, 作出一个页面没有找到的提示

404页面必须在路由规则的最下面 就算有重定向也要在它下面

const routes = [
  {
    path: '/home',
    name: 'Home',
    component: Home
  },
  {
    path: '/shop',
    name: 'shop',
    component: Shop
  },
  {
    path: '/phone',
    name: 'phone',
    component: Phone
  },
  {
    path: '/user',
    name: 'user',
    component: User
  },

 
  // 重定向
  {
    path:"/",
    // 重新定位方向
    redirect:"/home"
  },
  // 404页面必须在路由规则的最最最下面  就算有重定向也要在他下面
  // 404页面必须在路由规则的最最最下面  就算有重定向也要在他下面
  {
    path: '*',
    name: 'no',
    component: No
  }

]

多级路由

在一个路由中嵌套另外一个路由就叫多级路由

(1)在views文件夹创建一级界面文件,在views/二级路由文件夹创建二级界面文件

(2)一级页面写 1.写切换的页面 2.router-view路由出口

切换页面1
切换页面1
     //路由出口

(3)在router/index.js文件中 先在顶部import引入一级和二级页面。给一级路由添加children属性,把二级页面添加进去

使用children关键字进行配置

1.在views文件夹下 新建二级路由页面

2.配置路由规则

​ 2.1在router文件夹下的index.js中引用二级路由页面

​ 2.2在要添加二级路由的一级路由的配置页(router/index.js)中配置二级路由

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/home.vue'
import Sj from '../views/shiji.vue'
import Syy from '../views/shuyingyin.vue'
import Wode from '../views/wode.vue'
import Xz from '../views/xiaozu.vue'


// 1.引用二级路由页面
import Era from "@/views/er/era.vue"
import Erc from "@/views/er/erc.vue"
import Erd from "@/views/er/erd.vue"
import Ere from "@/views/er/ere.vue"

Vue.use(VueRouter)

const routes = [
  {
    path: '/home',
    name: 'Home',
    component: Home
  },
  
  {
    path: '/sj',
    name: 'Sj',
    component: Sj
  },
  {
    path: '/syy',
    name: 'Syy',
    component: Syy,
    // 2.二级路由配置
    children:[
      {
        path: '/era',
        name: 'Era',
        component: Era
      },
      {
        path: '/erc',
        name: 'Erc',
        component: Erc
      },
      {
        path: '/erd',
        name: 'Erd',
        component: Erd
      },
      {
        path: '/ere',
        name: 'Ere',
        component: Ere
      },
    ]
  },
  {
    path: '/wode',
    name: 'Wode',
    component: Wode
  },
  {
    path: '/xz',
    name: 'Xz',
    component: Xz
  },

  {
    path:"/",
    redirect:"/home"
  }

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

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

export default router

3.在对应一级页面中,使用配置二级路由出口






4.设置路由导航

​ 4.1如果多级路由在配置规则(index.js)的时候,path带 / - path: “/xxx” 那路由导航()属性就是 /xxx

		{
        path: '/era',   //path带/斜杠
        name: 'Era',
        component: Era
      },
      
      路由导航
      <router-link to="/era">era</router-link>

​ 4.2如果多级路由在配置规则的时候 path不带 / path:“xxx” 那么 路由导航to属性就是/一级路由/二级路由

 	{
        path: 'era', //path不带/
        name: 'Era',
        component: Era
      },

路由导航
<router-link to="/syy/era">era</router-link>

路由模式

在vue设置路由的时候,有两种模式:hash、history

main.js中使用mode来设置

mode: 'history',
区别 hash(默认值) history
url展示上 url带# url不带#
兼容性 支持低版本浏览器 是HTML5新增的所以不兼容低版本浏览器
刷新页面(上线之后) 刷新正常 刷新页面会丢失

#号的影响

在开发APP分享页面的时候,如果这个页面就是vue写的,在嵌入到第三方原生app 的时候,有的app对url有要求,不能带#

动态路由匹配/路由传参

把数据从一个路由页面传递到另外一个页面的技术

传参方式

params

​ 1.在路由规则中设置接收参数(谁接收数据,就在谁的路由规则中配置)

 {
    path: '/xz/:xiaoming',//接收数据的规则上设置接收参数
    name: 'Xz',
    component: Xz
 },

​ 2.发送数据

this.$router.push({name:“要跳转的路由规则name”,params:{配置的接收参数:“数据”}})

      fun(id){
            console.log(id)
            // 传递数据
            // this.$router.push({name:"你要跳转的路由规则的name",params:{你配置的接收参数:"数据"}})
            this.$router.push({name:"Xz",params:{xiaoming:id}})
        }

​ 3.接收数据this.$route.params.xxx

 

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

query

1.发送数据

this.$router.push({name:“要跳转的路由规则的name”,query:{接收参数:“数据”}})

this.$router.push({path:“要跳转的路由的路径”,query:{接收参数:“数据”}})

// 使用query方式进行传参
            this.$router.push({name:"Sj",query:{xiaohong:"我是query传参"}})

2.接收数据

this.$route.query.xxx

区别

1.用法上:

query方式可以使用path也可以使用name作为跳转路径,params只能用name

接收上:query使用this. r o u t e . q u e r y . x x x 而 p a r a m s 使 用 t h i s . route.query.xxx 而params使用this. route.query.xxxparams使this.route.params.xxx

2.url展示上不同

query是key=val query显示key相对来说不安全

params url只有val 不显示key 相对来说安全一些

r o u t e r 与 router与 routerroute

$router 是vueRouter的全局对象里面包含了对路由全局操作的属性和方法

$route 是一个路由对象。每一个路由都有一个route对象也就是说他是类似于局部页面路由的一个对象他只能处理当前路由页面的操作

路由懒加载

懒加载就是按需加载,在想使用的时候进行加载

就是给使用者更好的用户体验,路由的项目可能会出现首页白屏问题

路由是完成spa单页面应用的一个技术,就是项目中之后一个页面,如果用户需要切换页面显示的话,就是在当前页面对整体内容进行一个替换

项目在第一次加载的时候 会把全部页面都加载 然后把需要显示的页面显示出来,可能页面过多,导致加载事件过长,那么用户所看到的就是白屏

路由懒加载分为两种:

在router/index.js中修改,采用懒加载后头部不需要import Home from '../views/home.vue的方式进行引用

1.vue异步组件的方式

component: (resolve) => require(['你要引用的路由页面路径'], resolve)

2.es中import的方式

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

  {
    path: '/class',
    name: 'Class',
    component: () => import ('../views/class.vue'),
  },

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

路由切换的时候被自动调用的函数

使用场景:vue项目中进行所在路由页面切换的时候 进行一些项目的验证,比如:用户登录的状态验证,就需要每次页面切换的时候进行状态的验证(会自动执行)

全局守卫

无论哪个路由 在切换到时候都会触发这个钩子函数

在router/index.js中写。写在实例化路由对象之后

全局前置守卫-beforeEach()

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


  if(to.path=="/about"){
    next()
  }else{
    alert("您没有登录请您登录后在试!!!")
    next("/about")
  }
 
})

全局后置守卫-afterEach()

进入到路由的时候生效

// 全局后置守卫
// router.afterEach((to从哪来,from去哪里)=>{})
router.afterEach((to,from)=>{
  console.log("to",to)
  console.log("from",from)
}) 

路由独享守卫-beforeEnter()

相对于全局守卫来说,路由守卫仅对一个路由页面生效

router/index.js 钩子函数写在指定要设置守卫的路由配置中,与path 那么 同级

 {
    path: '/phone',
    name: 'phone',
    component: () => import( '../views/phone.vue'),
    // 路由独享守卫
    beforeEnter(to,from,next){
      console.log(to)
      console.log(from)
      // 进行一些是否登录的判断判断成功让她进入  不成功不能进
     alert("当前页面是vip页面")
      next("/about")//不让下一步
    }
  },

组件内守卫

写在指定的.vue文件中

进入组件的时候调用-beforeRouteEnter

离开组件的时候调用-beforeRouteLeave






路由拓展-路由的更多信息

meta路由记录

开发者可以再路由中自己添加一些数据 方便页面使用

 {
        path: 'erf',
        name: 'erf',
        component: () => import( '../views/er/erf.vue'),
        meta:{
            title:"账号权限"
        }
      },

页面得到路由信息

this.$router.options.routes

mixin-混入

mixin是vue组件复用功能的技术之一 它可以把多个组件中重复出现的属性和方法多次进行封装方便多次调用

使用

1.混入就是把组件多次使用的属性和方法等内容进行封装

新建mixin文件夹用来容纳混入的封装

export let demo={
    methods:{
        fun(){
            console.log("你好!!!!!!")
        }
    },
    data(){
        return {

        }
    },
    computed:{

    }
}

调用

全局混入=mixin

慎用全局混入,可能会造成代码的污染

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
// 1.引用mixin
import {demo} from "./mixins"
// 2.配置全局混入
Vue.mixin(demo)

Vue.config.productionTip = false

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

局部混入=mixins





生命周期钩子函数

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

钩子函数 就是特定阶段内被自动调用的函数。给开发者在程序不同阶段提供一个自动执行程序(逻辑)的场所

8个钩子函数 4组(实例创建 模板渲染 数据更新 实例销毁)

实例的创建

beforeCreate实例准备创建。

created 实例创建完毕。在vue实例new 创建完毕之后立即调用,但是这个时候只是把vue实例出来了,实例中的data methods等属性还没有开始处理

模板渲染

beforeMount模板准备渲染

mounted 页面加载完毕之后立即调用 页面已经显示了 vue实例中的内容也已经处理完了

数据更新

beforeUpdata 开始准备更新

updated 更新完毕

实例销毁

beforeDestory 开始准备销毁

Destorted 销毁完毕

常见问题

1.生命周期在页面初次加载的时候执行什么?

前两组 分别为 实例创建前后(带英文) 模板创建前后(带英文)

2.声明周期的作用是什么?

vue实例从创建到销毁的过程中在特定阶段内被自动调用的函数同时给开发者在程序的不同阶段提供一个自动执行程序(逻辑)的场所

3.vue生命周期一共几个阶段?

4大阶段 8个钩子

4.简述vue生命周期的各个钩子函数?

beforeCreate 实例准备创建(数据观测与初始化事件还没有执行)

created 实例创建完毕 (完成了诗句的观测 属性 方法也都进行了初始化 但是页面没有显示渲染)

beforeMount 模板准备渲染 (在准备吧template模板网页面中进行挂载 准备编译页面内容)

mounted 页面加载完毕之后立即调用 (页面被成功的进行了挂载 页面的dom内容也都生成完毕)

updated 更新完毕(数据已经成功的在页面dom中更新完毕了)

beforeDestory 开始准备销毁(vue实例还能用)

Destoryed 销毁完毕

5.vue数据请求应该在哪个钩子函数中进行调用,为什么?

在created和mounted中都可以

但是,如果要涉及请求完毕操作dom的时候,那么必须在mounted中进行数据请求

过滤器

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

全局过滤器===filter

局部过滤器===filters

1.写在与data、methods等 同级位置

filters:{

​ 过滤器的名字(操纵的数据){

​ return 要做的事情===函数

}}

export default {
    props:["datalist"],
    // 过滤器
    filters:{
        xiaoming(val){
            if(val.length>6){
                return val.substr(0,5)+".."
            }else{
                return val
            }
            
        }
    }
}

使用过滤器,在想使用的数据后面使用 管道符(|)+过滤器名字

扩展

修改文件夹引用别名

在项目的根目录下vue.config.js文件中

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

    // 配置引用别名
    configureWebpack:{
        resolve:{
            alias:{
                // 别名:真实路径
                "niubi":"@/utils"
            }
        }
    }
}

动态组件

在给多个组件使用用一个挂载点并且动态切换(多个组件每次只显示一个并且动态的进行切换)

语法:

在页面想显示多个组件的时候会用下面的语法 来声明挂载点






keep-alive

在动态组件中如果有多个输入框 那么我们在切换动态组件的时候会发现这些输入框的内容会丢失

在多个路由页面中如果有多个输入框 那么我们在切换路由页面的时候会发现这些驶入框的内容也会丢失

我们在路由或者是动态组件切换的时候因为 每次切换vue都会出现一个新的vue组件实例 所以会丢失

keep-alive 可以在keep-alive包裹的内容 在切换的时候把数据状态保存在内存中 防止重复的DOM渲染 减少了性能与时间上的损耗

用在动态组件之上

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

用在路由之上 只需包裹路由的出口

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

动态组件的属性

include 你想缓存的

  
          
      

可以写多个 中间用逗号隔开

 		
          
      

exclude 你不想缓存谁

 <keep-alive  exclude="One,Two">
          <component :is="com"></component>
      </keep-alive>

动态组件的钩子函数

有两个钩子函数 但是在写的时候一定要在被keep-alive所管理的组件中进行使用

activated 进入到被keep-alive管理的组件时候触发

deactivated 离开被keep-alive管理的组件时候触发

    activated(){
        console.log("进入到keep-alive管理的组件了")
    },
    deactivated(){
        console.log("离开了keep-alive管理的组件了")
    }

$set

问题:vue数据改变页面没有改变(没有更新)的情况?

原理:当vue中data里的数据(对象和数组)在初始化完毕之后 再向其中插入新的属性的时候,这时候数据发生改变,但是页面视图不会更新






问题:Object.defineProerty()的问题

在vue2.0中双向绑定使用的是数据劫持Object.defineProerty(),但是Object.defineProerty()就监听不到 监听不到就没有数据劫持 没有劫持就没有双向绑定 所以数据变了视图也不会改变

解决:$set

想中途添加一个新属性并且数据变视图也要改变怎么办?

语法:this.$set(“要修改的”,“要新增的key”,“要新增的val”)

    

$set应用

{{ obj.text }}

set(text){ // this.$set(this.obj,"text",text); this.$set(this.obj,"text",text); this.obj.text="我是$set更改后的数据"; console.log(this.obj.text) }

ref

ref绑定到dom之上 可能得到这个dom元素

就是在vue中进行dom操作






ref绑定到组件之上

完成逆向传值

可以在父组件中触发子组件的方法

自定义指令=directives

在现有的指令不够用的时候,自己创建指令

语法:

写在与data methods同级

directives:{

​ 自定义指令的名字:{

​ 自定义指令的钩子函数(el 绑定的自定义指令所在的dom元素){

​ 要操作的逻辑(函数)

​ }

​ }

}

自定义指令钩子函数

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

inserted:绑定了指令的元素在插入页面展示的时候调用

update:所有节点更新的时候调用

componentUpdate:指令所在组件的节点一级他自己所有的子节点全部更新了 再调用

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

  directives:{//自定义指令
    xiaoming:{//自定义指令的名字随便起
      inserted(el){
        el.style.color="red";
      }
    }
  },

使用

v-自定义指令的名字

    

This is an about page

服务器上线

跨域

因为浏览器的同源政策,就会产生跨域。比如说发送的异步请求是不同的两个源,就比如是不同的的两个端口或者不同的两个协议或者不同的域名。由于浏览器为了安全考虑,就会产生一个同源政策,不是同一个地方出来的是不允许进行交互的。

解决跨域

1.jsonp的方法(面试的时候不要先说jsonp)

2.使用CORS解决跨域,即跨域资源共享,在后端设置响应头部,加一句代码:access-control-allow-origin:"*"或者允许交互的域名。

3.vue react angular 使用本地开发者服务器代理跨域

devserver的proxy解决,在根目录下新建vue.config.js文件,修改propyTable中的target的值,就可实现用前端解决跨域。(打包上线后就废了)

测试接口:http://www.weather.com.cn/data/cityinfo/101320101.html

proxy:{
        "/api(可以随便写)":{
             target:"请求地址",
             changeOrigin:true,
             "pathRewrite":{
               "^/api(和上面一样)":"/"
             }
        }
    },

实现流程vue

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

2.在这个文件中写入

module.exports={
    devServer:{
        open:true,//自动开启浏览器
        port:8888, //修改端口
        proxy:{
            "/api":{
                 target:"http://www.weather.com.cn",
                 changeOrigin:true,
                 "pathRewrite":{
                   "^/api":"/"
                 }
            }
        },
    }
}

3.修改里面的参数地址 并且 把你的/api 替换组件中的请求地址

4.重启项目

第四种,使用nginx反向代理跨域

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   dist;
            index  index.html index.htm;
        }
        #设置反向代理跨域
        #设置反向代理跨域
        #设置反向代理跨域
        #设置反向代理跨域
        #设置反向代理跨域
        #设置反向代理跨域
        #设置反向代理跨域
        #设置反向代理跨域
        location /api {
        #设置代理需要重写/api
因为在开发的时候所有的接口都是以/api开头的,所以在请求代理的时候和proxyTable一样的逻辑,需要rewrite重写。
            rewrite  ^.+api/?(.*)$ /$1 break;
            proxy_pass http://www.weather.com.cn;
        }
        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

}



 server {
        listen       9999; # 监听端口
        server_name  localhost; # 域名可以有多个,用空格隔开

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   C:\工作\project\client_admin_system\dist;     #站点根目录,即网页文件存放的根目录, 默认主页目录在nginx安装目录的html子目录。 
            index  index.html index.htm;    #目录内的默认打开文件,如果没有匹配到index.html,则搜索index.htm,依次类推
        }

        #ssl配置省略
         location /api {
            rewrite  ^.+api/?(.*)$ /$1 break;
            proxy_pass  http://192.168.1.100:7001;    #node api server 即需要代理的IP地址
            proxy_redirect off;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
         }

        #error_page  404              /404.html;    #对错误页面404.html 做了定向配置

        # redirect server error pages to the static page /50x.html
        #将服务器错误页面重定向到静态页面/50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }

第五种,使用otherWindow.postMessage 是html5引入的API,postMessage()方法允许来自不同源的脚本采用异步方式进行有效的通信,可以实现跨文本文档,多窗口,跨域消息传递.多用于窗口间数据通信,这也使它成为跨域通信的一种有效的解决方案.

打包上线

打包

将项目放在服务器上,在服务器上运行项目

流程:

1.基础命令:npm run build

build之后,运行打包后的文件夹 dist/index.html会发现页面什么都没有,并且console中有很多404错误,这是因为大报纸后静态资源文件路径有问题,需要修改才能正常显示

2.修改静态资源路径。在根目录下的vue.config.js文件里,增加 publicPath:"./"

module.exports={
    publicPath: './'
}

3.router/index.js中将路由模式改为hash

const router = new VueRouter({
  // mode: 'history',
  mode: 'hash',//将路由模式改为hash
  base: process.env.BASE_URL,
  routes
})

打包APP

Hbuilderx 新建 项目 h5+app

把build后的dist文件夹内的文件复制到hbuild新建的项目文件夹内

nginx服务器

Nginx是一个http服务器。是一个高性能的http服务器及反向代理服务器。官方测试nginx能够支支撑5万并发链接,并且cpu、内存等资源消耗却非常低,运行非常稳定。

代理服务器

代理服务器,客户机在发送请求时,不会直接发送给目的主机,而是先发送给代理服务器,代理服务接受客户机请求之后,再向主机发出,并接收目的主机返回的数据,存放在代理服务器的硬盘中,再发送给客户机。

注意

我们学习的vue的跨域 是基于脚手架内置服务器的 但是我们打包之后这个服务器就不帮助我们启动服务了 所以我们之前配置的跨域设置就作废了

使用

1.解压出nginx得到如下内容

8

2.打开conf文件夹 复制一份nginx.conf文件 并且修改名字(名字随便起) 这个文件就是nginx的配置文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rivP3ZT7-1646355391623)(C:\Users\SZnAl\Desktop\9.bmp)]

3.打开Powershell cd到当前nginx路径下 输入 ./nginx.exe -c ./conf/你复制的文件名.conf 启动

4.打开浏览器输入localhost:80即可启动

使用小扩展

记得如果修改服务器内容了 要停止之后在重新启动

打开Powershell cd到当前nginx路径下 输入 ./nginx.exe -c ./conf/你复制的文件名.conf -s stop 停止

运行我们打包项目

1.把我们打包好的dist放到根路径下

2.修改我们的.conf文件

node

什么是node?

node是一个基于chrome浏览器js解析器(v8)的一个JavaScript运行环境

可以让js在脱离浏览器的情况下进行单独运行

特点

单线程

非阻塞式IO(IO 输入输出)

事件驱动

repl交互式解释器

express后台基本创建

node的一个企业级应用框架,简化了我们在创建http服务的时候的复杂度

使用:

1.npm install --save express

2.创建后台服务

// 1.引用express
let express=require("express");
// 2.初始化express对象
let app=express()
// 3.创建服务
// req 请求
// res 相应
app.get("/xiaoming/xiaohong",(req,res)=>{
    res.send({msg:"我是一个后台服务"})
})
// 4.监听端口
app.listen(8888)

多个后台 接口 创建方法


let express=require("express");

let app=express()

app.get("/xiaoming/xiaohong",(req,res)=>{
    res.send({msg:"我是一个后台服务"})
})
// 如果有多个接口
app.get("/xiaoming/xiaohua",(req,res)=>{
    res.send({msg:"我是第二个"})
})
app.get("/xiaoming/xiaohei",(req,res)=>{
    res.send({msg:"我是第三个"})
})

app.listen(8888)

mongodb

非关系型数据库(NoSql数据库Not Only SQL):Mongodb、Redis

关系型数据库:MySql、SQL Server、Oracle、BD2

关系型与非关系型数据库区别

非关系型数据库非常快 稳定性不够 (没有一个正式的官方支持) 由于比较新 所以支持的特性还不够拓展是不够

mongoose链接mongodb

1.npm安装Mongiise: npm install --save mongoose@5

2.在项目下新建db.js文件 来封装数据库连接内容

// 封装数据库连接的模块
// 1.引用mongoose
let mongoose=require("mongoose")
// 2.设置连接
mongoose.connect("mongodb://localhost:27017/xiaoming")//xiaoming是你设置的数据库
// 3.开始连接
var db = mongoose.connection;
// 4.设置错误的时候信息和连接成功的信息
db.on('error', console.error.bind(console, '连接错误'));
db.once('open', function() {
  console.log("连接ok")
});
// 5.暴漏
module.exports=db

3.在创建的随便一个后台路由中引用db文件,并且调用


let express=require("express");

let app=express()

// 引用数据库连接模块
let db=require("./db")

app.get("/xiaoming/xiaohong",(req,res)=>{
    // 调用数据库连接模块
    db
    res.send({msg:"我是一个后台服务"})
})
// 如果有多个接口
app.get("/xiaoming/xiaohua",(req,res)=>{
    res.send({msg:"我是第二个"})
})
app.get("/xiaoming/xiaohei",(req,res)=>{
    res.send({msg:"我是第三个"})
})

app.listen(8888)

运行时候有设置连接模式的警告

(node:11436) DeprecationWarning: current URL string parser is deprecated, and will be removed in a future version. To use the new parser, pass option { useNewUrlParser: true } to MongoClient.connect.
(Use `node --trace-deprecation ...` to show where the warning was created)
(node:11436) [MONGODB DRIVER] Warning: Current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor.

根据以上提示配置连接模式

// 封装数据库连接的模块
// 1.引用mongoose
let mongoose=require("mongoose")
// 2.设置连接    设置连接模式
mongoose.connect("mongodb://localhost:27017/xiaoming",{ useNewUrlParser: true,useUnifiedTopology: true })//xiaoming是你设置的数据库
// 3.开始连接
var db = mongoose.connection;
// 4.设置错误的时候信息和连接成功的信息
db.on('error', console.error.bind(console, '连接错误'));
db.once('open', function() {
  console.log("连接ok")
});
// 5.暴漏
module.exports=db

Node+Vue项目

vue路由页面的创建

element

ElementUI 一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的桌面端组件库

下载 npm i element-ui@2 -S

2 在 main.js 中写入以下内容:

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

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

Vue.config.productionTip = false

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

网页占全屏

当前以及父级,html,body高度均设置 height: 100%

接口测试工具-postman

在调用接口的时候使用postman先检测接口是否正确

左上角新建-输入项目名称、介绍-输入地址、确认请求参数-点击send

Node接收请求

get

接收前台的get请求 使用 req.query.xxxx

restFulApi

是一个规范 定义接口的名字或者是使用上的内容

get 方式 获取数据

post方式 发送数据

delete方式 删除数据

put方式或者patch方式 修改更新数据

token

能加密也能解密的字符串(通常用来保存用户的登录状态)

使用jsonwebtoken库来实现token

npm install --save jsonwebtoken

1.加密–sign()

sign(你要加密的数据,密钥)

密钥:我们自己定义一段越乱越好的乱码

2.解密–verify()

verify(你要解密的数据,密钥(必须和你加密时候的密钥相同),回调函数)

1.在登录成功之后 生成一个token 并且一并返回给前台

2.前台得到这个token存起来(本地存储 cookie)

3.每次页面切换或者是需要这个知道用户是否登录的时候 我们就把这个token取出来,并且发送给后台,后台会有一个专门解密这个token的接口来判断用户是否登陆过

4.把用户是否登录告诉前台,我们再作出对应的反应

你可能感兴趣的:(VUE,vue,html)