• 3.Vue从入门到精通 (第三章 使用Vue脚手架)


    第三章. 使用Vue脚手架

    3.1 初始化脚手架

    3.1.1 说明

    • Vue脚手架时是Vue官方提供的标准化开发工具(开发平台)
    • 最新的版本是4.x
    • 文档: https://cli.vuejs.org/zh/

    3.1.2 具体步骤

    第一步(仅第一次执行):全局安装@vue/cli

    npm install -g @vue/cli
    
    • 1

    第二步:切换到你要创建项目的目录,然后使用命令创建项目

    vue create 项目名称
    
    • 1

    第三步:启动项目

    npm run server
    
    • 1

    备注:

    1. 如出现下载缓慢请配置npm淘宝镜像:npm config set registry https://registry.npm.taobao.org

    2. Vue脚手架隐藏了所有webpack相关的配置,若想查看具体的webpakc配置,请执行:

      vue inspect > output.js (但是output配置文件仅可以查看,并不能直接在上面修改)

      
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3.2 分析脚手架结构

    脚手架文件结构

      ├── node_modules 
      ├── public
      │  ├── favicon.ico: 页签图标
      │  └── index.html: 主页面
      ├── src
      │  ├── assets: 存放静态资源
      │  │  └── logo.png
      │  │── component: 存放组件
      │  │  └── HelloWorld.vue
      │  │── App.vue: 汇总所有组件
      │  │── main.js: 入口文件
      ├── .gitignore: git版本管制忽略的配置
      ├── babel.config.js: babel的配置文件
      ├── package.json: 应用包配置文件 
      ├── README.md: 应用描述文件
      ├── package-lock.json:包版本控制文件
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    3.3 修改默认配置( 修改后重新运行npm run serve命令 )

    vue.config.js配置文件

    1. 脚手架默认的配置文件是隐藏的,使用vue inspect > output.js可以查看到Vue脚手架的默认配置。

    2. 使用vue.config.js可以对脚手架进行个性化定制,详情见:https://cli.vuejs.org/zh

    vue.config.js 文件 直接放入到根目录下,需要覆盖的配置写入文件即可,脚手架会自动进行合并,覆盖原来默认的配置

    module.exports = {
      pages: {
        index: {
          //入口
          entry: 'src/main.js',
        },
      },
    	lintOnSave:false, //关闭语法检查
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3.4 ref属性

    ]

    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    总结:

    1. ref属性被用来给元素或子组件注册引用信息(id的替代者)
    2. 应用在html标签上获取的是真实DOM元素,应用在组件标签上是组件实例对象(vc)
    3. 使用方式:
        1. 打标识:```

    .....

    ```或 `````` 2. 获取:```this.$refs.xxx```
    • 1
    • 2
    • 3
    • 4
    • 5

    3.5 props属性

    <template>
        <div class="school">
            <h1>{{msg}}</h1>
            <h2>学生姓名:{{name}}</h2>
            <h2>学生年龄:{{myAge}}</h2>
            <button @click="addAge">增加年龄</button>
        </div>
    </template>
    
    <script>
    export default {
        name:"School",
        data(){
            return {
                msg:'我就一学生',
                myAge:this.age
            }
        },
        methods:{
            addAge(){
                this.myAge++
            }
        },
        // 简单声明接收, 最常用
        props:['name', 'age'] 
    
        // 接收的同时对数据类型进行限制
        // props:{
        //     name:String,
        //     age:Number
        // }
    
        // 接收的同时对数据:进行类型限制+默认值的指定+必要性的限制
        // props:{
        //     name:{
        //         type:String,
        //         required:true  // 设置必填项
        //     },
        //     age:Number,
        //     default:99  // 设置默认值
        // }
    }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    props总结:

    1. 功能:让组件接收外部传过来的数据
    2. 传递数据:
    3. 接收数据:
        1. 第一种方式(只接收):props:['name'] 
        2. 第二种方式(限制类型):props:{name:String}
        3. 第三种方式(限制类型、限制必要性、指定默认值):
            props:{
            	name:{
            	type:String, //类型
            	required:true, //必要性
            	default:'老王' //默认值
            	}
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

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

    3.6 mixin混入

    混入就是:如果两个或多个文件中有相同的代码,那么可以将相同的代码抽离出来,形成一个文件,在需要的地方引入这个文件,实现原本的功能

    在这里插入图片描述

    3.6.1 局部混合

    在这里插入图片描述

    对于data以及methods等来说,如果混合文件中有,原文件中也有,那么就以原文件为主,

    对于生命周期函数来说,如果混合文件和源原文件都有,那么全都要

    在这里插入图片描述

    在这里插入图片描述

    3.6.2 全局混合

    一旦使用全局, vm以及各个vc上全部具备混合文件中所具备的特征

    在这里插入图片描述

    总结:

    1. 功能:可以把多个组件共用的配置提取成一个混入对象
    2. 使用方式:
        第一步定义混合:
        {
            data(){....},
            methods:{....}
        }
    
        第二步使用混入:
        ​	全局混入:Vue.mixin(xxx)
        ​	局部混入:mixins:['xxx']
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    3.7 插件

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    3.8 scoped

    编码时在不同组件中写的样式都会被汇总到一起,因此会产生一个问题是,如果两个组件中的样式名字相同,那么就会产生冲突,冲突后会按照先后引入组件的次序不同,后引入组件会覆盖前面引入组件的样式

    在这里插入图片描述

    在这里插入图片描述

    注意:App.vue比较特殊,其内部写的style不但要自己使用,也要为别的组件使用,因此一般不用scoped修饰

    3.9 Todo-list案例

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

    3.10 浏览器本地存储

    3.10.1 localStorage

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>localStorage</title>
    </head>
    <body>
        <h2>localStorage</h2>
        <button onclick="saveData()">点击保存数据</button>
        <button onclick="readData()">点击读取数据</button>
        <button onclick="deleteData()">点击删除数据</button>
        <button onclick="deleteAllData()">点击清空数据</button>
    
        <script>
            function saveData(){
                let p = {name:'张三', age:18}
                // window可省略
                window.localStorage.setItem("msg","hello!!")
                localStorage.setItem("msg2",666)   // 即使是数字,保存的时候也会转成字符串
                window.localStorage.setItem("person",JSON.stringify(p))
            }
    
            function readData(){
                console.log(localStorage.getItem('msg'))
    
                const result = localStorage.getItem("person")  // 如果数据不存在,那么就返回null
                console.log(JSON.parse(result))  // 数据不存在时,JSON.parse解析也为null
            }
    
            function deleteData(){
                localStorage.removeItem("msg")
            }
    
            function deleteAllData(){
                localStorage.clear()
            }
        </script>
    </body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    3.10.2 sessionStorage

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>sessionStorage</title>
    </head>
    <body>
        <h2>sessionStorage</h2>
        <button onclick="saveData()">点击保存数据</button>
        <button onclick="readData()">点击读取数据</button>
        <button onclick="deleteData()">点击删除数据</button>
        <button onclick="deleteAllData()">点击清空数据</button>
    
        <script>
            function saveData(){
                let p = {name:'张三', age:18}
                // window可省略
                window.sessionStorage.setItem("msg","hello!!")
                sessionStorage.setItem("msg2",666)   // 即使是数字,保存的时候也会转成字符串
                window.sessionStorage.setItem("person",JSON.stringify(p))
            }
    
            function readData(){
                console.log(sessionStorage.getItem('msg'))
    
                const result = sessionStorage.getItem("person")  // 如果数据不存在,那么就返回null
                console.log(JSON.parse(result))  // 数据不存在时,JSON.parse解析也为null
            }
    
            function deleteData(){
                sessionStorage.removeItem("msg")
            }
    
            function deleteAllData(){
                sessionStorage.clear()
            }
        </script>
    </body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    总结:

    1. 存储内容大小一般支持5MB左右(不同浏览器可能还不一样)

    2. 浏览器端通过 Window.sessionStorage 和 Window.localStorage 属性来实现本地存储机制。

    3. 相关API:

      1. xxxxxStorage.setItem('key', 'value');
        该方法接受一个键和值作为参数,会把键值对添加到存储中,如果键名存在,则更新其对应的值。

      2. xxxxxStorage.getItem('person');

        ​ 该方法接受一个键名作为参数,返回键名对应的值。

      3. xxxxxStorage.removeItem('key');

        ​ 该方法接受一个键名作为参数,并把该键名从存储中删除。

      4. xxxxxStorage.clear()

        ​ 该方法会清空存储中的所有数据。

    4. 备注:

      1. SessionStorage存储的内容会随着浏览器窗口关闭而消失。
      2. LocalStorage存储的内容,需要手动清除才会消失。
      3. xxxxxStorage.getItem(xxx)如果xxx对应的value获取不到,那么getItem的返回值是null。
      4. JSON.parse(null)的结果依然是null。

    3.11 组件的自定义事件

    3.11.1 绑定自定义事件

    • 通过父组件给子组件绑定一个自定义事件 实现子给父传递数据 方式一:通过@或者v-on

    在这里插入图片描述

    • 通过父组件给子组件绑定一个自定义事件 实现子给父传递数据 方式二:通过ref

    在这里插入图片描述

    • 要让自定义事件只响应一次,使用once
    使用@或者v-on时可直接在后面加once
    <Student v-on:atguigu.once="getStudentName"/>
        
     使用ref时将$on更换为$once
    this.$refs.student.$once('atguigu',this.getStudentName)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 自定义事件传递多个参数

    在这里插入图片描述
    在这里插入图片描述

    3.11.2 解绑自定义事件

    在这里插入图片描述

    3.11.3 自定义事件总结

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

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

    3. 绑定自定义事件:

      1. 第一种方式,在父组件中:

      2. 第二种方式,在父组件中:

        <Demo ref="demo"/>
        ......
        mounted(){
           this.$refs.xxx.$on('atguigu',this.test)
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
      3. 若想让自定义事件只能触发一次,可以使用once修饰符,或$once方法。

    4. 触发自定义事件:this.$emit('atguigu',数据)

    5. 解绑自定义事件this.$off('atguigu')

    6. 组件上也可以绑定原生DOM事件,需要使用native修饰符。

    7. 注意:通过this.$refs.xxx.$on('atguigu',回调)绑定自定义事件时,回调要么配置在methods中,要么用箭头函数,否则this指向会出问题!

    3.12 全局事件总线

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

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

    2. 安装全局事件总线:

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

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

        methods(){
          demo(data){......}
        }
        ......
        mounted() {
          this.$bus.$on('xxxx',this.demo)
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
      2. 提供数据:this.$bus.$emit('xxxx',数据)

    4. 最好在beforeDestroy钩子中,用$off去解绑当前组件所用到的事件。

    3.13 消息订阅与发布

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

    2. 使用步骤:

      1. 安装pubsub:npm i pubsub-js

      2. 引入: import pubsub from 'pubsub-js'

      3. 接收数据:A组件想接收数据,则在A组件中订阅消息,订阅的回调留在A组件自身。

        methods(){
          demo(data){......}
        }
        ......
        mounted() {
          this.pid = pubsub.subscribe('xxx',this.demo) //订阅消息
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
      4. 提供数据:pubsub.publish('xxx',数据)

      5. 最好在beforeDestroy钩子中,用PubSub.unsubscribe(pid)去取消订阅。

    案例:Student组件发送消息,School组件订阅消息

    在这里插入图片描述
    在这里插入图片描述

    3.14 $nextTick

    1. 语法:this.$nextTick(回调函数)

    2. 作用:在下一次 DOM 更新结束后执行其指定的回调。

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

    当你修改了数据之后,vue帮你操作完dom之后,把真实的dom放入页面了,vue再帮忙调用nextTick函数

    3.15 动画

    vue封装的动画要求写在transition标签中,以进场和离场动画为例,若不给transition标签指定名字hello,那么这两个动画的名字要固定的写为.v-enter-active和.v-leave-active,如果给transition指定name为hello,那么两个动画的名字为.hello-enter-active和.hello-leave-active,如果希望在开始时就有出场动画,就要在transition标签上加入:appear=“true”, 可简写为appear

    <template>
    	<div>
    		<button @click="isShow = !isShow">显示/隐藏</button>
    		<transition name="hello" appear>
    			<h1 v-show="isShow">你好啊!</h1>
    		</transition>
    	</div>
    </template>
    
    <script>
    	export default {
    		name:'Test',
    		data() {
    			return {
    				isShow:true
    			}
    		},
    	}
    </script>
    
    <style scoped>
    	h1{
    		background-color: orange;
    	}
    
    	.hello-enter-active{
    		animation: atguigu 0.5s linear;
    	}
    
    	.hello-leave-active{
    		animation: atguigu 0.5s linear reverse;
    	}
    
    	@keyframes atguigu {
    		from{
    			transform: translateX(-100%);
    		}
    		to{
    			transform: translateX(0px);
    		}
    	}
    </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    3.16 过渡

    3.16.1 单个元素的过渡

    vue封装transition时,元素进场或者离场时会给内部的元素添加两对共六个样式,分别是

    1 进入的起点.hello-enter、2 离开的终点 .hello-leave-to

    3 进入的全过程.hello-enter-active、 4 离开的全过程 .hello-leave-active

    5 进入的终点.hello-enter-to、 6 离开的起点 .hello-leave

    <template>
    	<div>
    		<button @click="isShow = !isShow">显示/隐藏</button>
    		<transition name="hello" appear>
    			<h1 v-show="isShow">你好啊!</h1>
    		</transition>
    	</div>
    </template>
    
    <script>
    	export default {
    		name:'Test',
    		data() {
    			return {
    				isShow:true
    			}
    		},
    	}
    </script>
    
    <style scoped>
    	h1{
    		background-color: orange;
    	}
    	/* 进入的起点、离开的终点 */
    	.hello-enter,.hello-leave-to{
    		transform: translateX(-100%);
    	}
    	.hello-enter-active,.hello-leave-active{
    		transition: 0.5s linear;
    	}
    	/* 进入的终点、离开的起点 */
    	.hello-enter-to,.hello-leave{
    		transform: translateX(0);
    	}
    
    </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    3.16.2 多个元素的过渡

    多个元素过渡要使用transition-group 标签,并且其内部的元素要有key值标识

    <template>
    	<div>
    		<button @click="isShow = !isShow">显示/隐藏</button>
    		<transition-group name="hello" appear>
    			<h1 v-show="!isShow" key="1">你好啊!</h1>
    			<h1 v-show="isShow" key="2">尚硅谷!</h1>
    		</transition-group>
    	</div>
    </template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3.17 集成第三方动画

    安装animate.css库,命令为 npm i animate.css

    transition-group标签的名字要改为animate__animated animate__bounce

    对其内部的标签配置进入和离开的动画,进入动画配置为enter-active-class=“animate__swing”,离开动画leave-active-class=“animate__backOutUp”

    <template>
    	<div>
    		<button @click="isShow = !isShow">显示/隐藏</button>
    		<transition-group 
    			appear
    			name="animate__animated animate__bounce" 
    			enter-active-class="animate__swing"
    			leave-active-class="animate__backOutUp"
    		>
    			<h1 v-show="!isShow" key="1">你好啊!</h1>
    			<h1 v-show="isShow" key="2">尚硅谷!</h1>
    		</transition-group>
    	</div>
    </template>
    
    <script>
    	import 'animate.css'
    	export default {
    		name:'Test',
    		data() {
    			return {
    				isShow:true
    			}
    		},
    	}
    </script>
    
    <style scoped>
    	h1{
    		background-color: orange;
    	}
    </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    Vue封装的过度与动画总结

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

    2. 图示:

    3. 写法:

      1. 准备好样式:

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

        
           

        你好啊!

        • 1
        • 2
        • 3
      3. 备注:若有多个元素需要过度,则需要使用:,且每个元素都要指定key值。

  • 相关阅读:
    全面解析缓存应用经典问题
    MIT 6.828 Lab1(从引导扇区开始)
    linux控制台命令
    直流信号隔离测控光电转换器0-±10V1-5V转0-10V4-20mA导轨安装
    霍尔闭环电流传感器在电动观光旅游车上的应用
    改造Vue-admin-template登录
    Java对文件操作包括CSV文件读写、文件压缩、文件下载
    299. 猜数字游戏 Python
    SQL语句优化、mysql不走索引的原因、数据库索引的设计原则
    Linux搭建Apache(秒懂超详细)
  • 原文地址:https://blog.csdn.net/cjhxydream/article/details/125919687