vue.js之个人总结(看这一篇就够了)

一.
1、Vue参数对象属性

el:元素挂载的位置,值可以是CSS选择器或DOM元素
data:模型数据,值是一个对象(仅限于当前)
插值表达式{{msg}}

指令
指令的本质就是标签中的vue自定义属性
指令格式以“v-”开始,例如:v-cloak,v-text、v-html等
友情提醒:v-html尽量少用甚至不用,因为可能引发XSS(跨站脚本攻击,XSS)攻击。
常用指令
2、v-cloak
作用:解决浏览器在加载页面时因存在时间差而产生的闪动问题

原理:先隐藏元素挂载位置,处理好渲染后再显示最终的结果

注意:需要与CSS规则一起使用
示例:

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

<div v-cloak>
  {{ message }}
</div

3、v-once
作用:只渲染元素和组件一次,之后元素和组件将失去响应式(数据层面)功能
示例

<div id="app">
	<h3>{{message}}</h3>
	<!-- 动态修改message值,此绑定将不会发生改变 -->
	<div v-once>{{message}}</div>
</div>
<script src="./js/vue.js"></script>
<script type='javascript'>
  const vm = new Vue({
      el: '#app',
      data: {
          message: '你好世界'
      }
  })
</script>

4、v-bind

作用:动态地绑定一个或多个attribute(组件内:一次声明,多次使用)
示例

<body>
    <div id="app">
        <a :href="url" :target="type" :alt="alt">{{alt}}</a>
        <a :href="url">{{alt}}</a>
    </div>
</body>
<script src="./js/vue.js"></script>
<script>
    new Vue({
        el: '#app',
        data: {
            url: 'https://www.fliggy.com/',
            type: '_blank',
            alt: '飞猪官网'
        }
    })
</script>

5、v-on(重点)

作用:绑定事件监听器(事件绑定)
示例

<!-- 直接执行操作 -->
<!-- 常规写法 -->
<button v-on:click="num++"></button>
<!-- 缩写 -->
<button @click="num++"></button>

<!-- 事件处理函数调用:直接写函数名 -->
<button @click="say"></button>
<!-- 事件处理函数调用:常规调用 -->
<button @click="say('sth')"></button>

如果事件处理函数为自定义函数,则需要先进行定义,定义的方式如下:

...
data: {
    ...
},
methods: {
    functionName: function(arg1,arg2,arg3,...){
        // something to do
    },
    ....
}

注意:事件绑定v-on属性表达式中切记不能直接写业务逻辑,例如@click=“alert(‘123’)”。换言之,在行内上是不允许使用内置函数的,必须要调用自己定义的函数,然后你可以在自定义的函数内使用内置函数。

事件处理函数传参

<!-- 事件处理函数调用:直接写函数名 -->
<button @click="say"></button>

<!-- 事件处理函数调用:常规调用 -->
<button @click="say('hi',$event)"></button>

在不传递自定义参数的时候,上述两种用法均可以使用;但是如果需要传递自定义参数的话,则需要使用第2种方式。

事件对象的传递与接收注意点

  • 如果事件直接使用函数名并且不写小括号,那么默认会将事件对象作为唯一参数进行传递,可以在定义函数的位置直接定义一个形参,并且在函数内可以使用该形参
  • 如果使用常规的自定义函数调用(只要写了小括号),那么如果需要使用事件对象则必须作为最后一个参数进行传递,且事件对象的名称必须是“$event”

6、事件修饰符

含义:用来处理事件的特定行为

使用示例:

<!-- 停止冒泡 -->
<button @click.stop="doThis"></button>
<!-- 阻止默认行为 -->
<button @click.prevent="doThis"></button>
<!--  串联修饰符 -->
<button @click.stop.prevent="doThis"></button>

7、按键修饰符

按键修饰符:按键事件

在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符。

<!-- 只有在 `key` 是 `Enter` 回车键的时候调用 -->
<input v-on:keyup.enter="submit">

<!-- 只有在 `key` 是 `Delete` 回车键的时候调用 -->
<input v-on:keyup.delete="handle">

8、循环分支指令(重点)

作用:根据一组数组或对象的选项列表进行渲染。

指令:v-for

数组遍历使用示例:

<!-- 模板部分 -->
<ul>
    <!-- 直接取值 -->
    <li v-for='item in fruits'>{{item}}</li>
    <!-- 带索引 -->
    <li v-for='(item,index) in fruits'>{{item}}{{index}}</li>
</ul>

<!-- JavaScript部分 -->
......
data: {
	fruits: ['apple','pear','banana','orange']
}
......

细节:key的作用,提高性能,不影响显示效果(如果没有id,可以考虑使用索引替代),切记key的值不能重复,只要遵循不重复的原则即可,值是什么无所谓。

示例:

<ul>
    <li :key='item.id' v-for='(item,index) in fruits'>{{item}}</li>
</ul>

9、分支指令

作用:根据表达式的布尔值(true/false)进行判断是否渲染该元素

v-if
v-else
v-else-if

上述三个指令是分支中最常见的。根据需求,v-if可以单独使用,也可以配合v-else一起使用,也可以配合v-else-if和v-else一起使用。

v-show

v-show是根据表达式之真假值,切换元素的 display CSS属性(是根据表达式的布尔值来判断是否显示该元素)。

使用示例:

<!-- 模板部分 -->
<div v-if="score >= 90">
  优秀
</div>
<div v-else-if="score >= 80 && score < 90">
  良好
</div>
<div v-else-if="score >= 70 && score < 80">
  一般
</div>
<div v-else>
  不及格
</div>
<!-- v-show -->
<div v-show='flag'>测试v-show</div>

<!-- JavaScript部分 -->
......
data: {
	score: 88,
	flag:false
}
......

v-if系列与v-show的区别是什么?

v-if:控制元素是否渲染

v-show:控制元素是否显示(已经渲染,display:none;)

10、样式绑定

10.1、class样式绑定

-对象语法(用于控制开关切换)

<style>
/* CSS片段 */
.active {
	color: red;
}
</style>

<!-- HTML片段 -->
<div :class="{active: isActive}">class样式</div>

<script type='text/javascript'>
// JavaScript片段
data: {
	isActive: true
}
</script>

数组写法

<style>
/* CSS片段 */
.active {
	color: red;
}
</style>

<!-- HTML片段 -->
<div v-bind:class="[activeClass]">数组写法</div>

<script type='text/javascript'>
// JavaScript片段
data: {
	activeClass: 'active'
}
</script>

10.2、style样式处理

对象语法

<!-- HTML片段 -->
<div :style="{color: redColor, fontSize: '20px'}">对象写法</div>

<script type='text/javascript'>
// JavaScript片段
data: {
	redColor: 'red'
}
</script>

数组写法

<!-- HTML片段 -->
<div :style="[color, fontSize]">数组写法</div>

<script type='text/javascript'>
// JavaScript片段
data: {
	color: {
		color: 'red'
	},
	fontSize: {
		'font-size': '20px'
        // fontSize: '20px'
	}
}
</script>

10、v-model(重点)

作用:表单元素的绑定,实现了双向数据绑定,通过表单项可以更改数据。
在这里插入图片描述
v-model会忽略所有表单元素的value、checked、selected特性的初始值,而总是将Vue实例的数据作为数据来源,应该在data选项中声明初始值。

<div id='app'>
    <textarea v-model="message"></textarea>
</div>

<script type='text/javascript'>
new Vue({
	el: '#app',
	data: {
		message: '我是多行文本内容'
	}
})
</script>

注意:在多行文本框中使用插值表达式无效(此时,其只能接受数据,不能改变数据)

多个复选框上的使用(特殊)

<div id='app'>
    <input type="checkbox" value="html" v-model="checkedNames">
    <input type="checkbox" value="css" v-model="checkedNames">
    <input type="checkbox" value="js" v-model="checkedNames">
</div>

<script type='text/javascript'>
new Vue({
	el: '#app',
	data:{
    	// 如果数组中有对应的value值,则此checkbox会被选中
		checkedNames:[]
	}
})
</script>

注意:此种用法需要input标签提供value属性,并且需要注意属性的大小写要与数组元素的大小写一致

修饰符

.lazy:默认情况下Vue的数据同步采用input事件,使用.lazy将其修改为失去焦点时触发

.number:自动将用户的输入值转为数值类型(如果能转的话)【作用:如果收集到的数据需要用于数学计算,则省去自行转化数据类型的操作】

.trim:自动过滤用户输入的首尾空白字符

11、自定义指令 - directive
指令优先级:
自定义指令分为:全局指令和局部指令,当全局指令和局部指令同名时以局部指令为准。

全局与局部有什么区别?

vue工程化的时候是有区别的
全局的适用于整个项目的(常用)【根组件】
局部的适用于当前组件的

自定义指令常用钩子函数有:

bind:在指令第一次绑定到元素时调用(在该环节中是获取不到父节点的,父节点是null),序号:1
inserted:被绑定元素插入父节点时调用(在该环节中是可以获取到父节点的),序号:2
update:数据更新时调用,序号:3(该环节会重复触发)

请注意:不管在定义全局还是局部自定义指令时,所提及的指令名均是不带v-前缀的名称。

全局自定义指令定义

// 无参(v-once/v-cloak)
Vue.directive('指令名',{
	钩子函数名: function(el[,....]){
        // 业务逻辑
    	// el参数是挂载到的元素的DOM对象
    	// <div v-abc>123</div>
    }
}

// 传参(v-text/v-html/v-model)
Vue.directive('指令名',{
	钩子函数名: function(el,binding[,....]){
    	let param = binding.value
        // 业务逻辑
    },
    ....
}

局部自定义指令定义

directives: {
  指令名: {
    // 指令的定义
    钩子函数名: function (el,binding) {
      // 业务逻辑
    }
  }
}

函数简写

在很多时候,我们可能想在 bind 和 update 时触发相同行为(如果只是其一,则还是单独分开声明),而不关心其它的钩子。那么这样写:

// 全局
Vue.directive('指令名', function (el,binding) {
  // 业务逻辑
})

// 局部
directives: {
  指令名: function (el,binding) {
      // 业务逻辑
  }
}

在自定义指令的方法中,不能像以前的methods中的方法一样使用关键词this,此时this关键词指向的是Window对象。

12、计算属性 - computed
模板中放入太多的逻辑(方法)会让模板过重且难以维护,使用计算属性可以让模板变得简洁易于维护。计算属性是基于它们的响应式依赖进行缓存的,计算属性比较适合对多个变量或者对象进行处理后返回一个结果值,也就是数多个变量中的某一个值发生了变化则我们监控的这个值也就会发生变化。

计算属性定义在Vue对象中,通过关键词computed属性对象中定义一个函数,并返回一个值,使用计算属性时和data中的数据使用方式一致。

示例

<div id="app">
    <!-- 当多次调用 cfn计算属性时只要里面的 num值不改变,它会把第一次计算的结果直接返回直到data中的num值改变 计算属性才会重新发生计算 -->
    <div>{{ cfn }}</div>
    <div>{{ cfn }}</div>
    <!-- 调用methods中的方法的时候  他每次会重新调用 -->
    <div>{{ fn() }}</div>
    <div>{{ fn() }}</div>
</div>
<script src="./js/vue.js"></script>
<script type="text/javascript">
    const vm = new Vue({
        el: "#app",
        data: {
            num: 10,
        },
        // 方法
        methods: {
            fn() {
                console.log("methods");
                return this.num;
            },
        },
        // 计算属性
        computed: {
            cfn() {
                console.log("computed");
                return this.num;
            },
        },
    });
</script>

注意:只要依赖的数据源不发生改变,计算属性里的对应方法就只被调用1次,其它时候被调用时则使用缓存。提高效率。

13、监听器 - watch

使用watch来侦听data中数据的变化,watch中的属性(watch是对象格式)一定是data 中已经存在的数据。

使用场景:数据变化时执行异步或开销比较大的操作。
在这里插入图片描述
参考代码

<div id="app">
    <p><input type="text" v-model='firstName' placeholder="" /></p>
    <p><input type="text" v-model='lastName' placeholder="" /></p>
    <p><input type="text" v-model='fullName' placeholder="全名" /></p>
</div>

<script src="./js/vue.js"></script>
<script type="text/javascript">
    const vm = new Vue({
        el: '#app',
        data: {
            firstName: '',
            lastName: '',
            fullName: ''
        },
        watch: {
            firstName: function(val) {
                this.fullName = val + ' ' + this.lastName
            },
            lastName: function(val) {
                this.fullName = this.firstName + ' ' + val
            }
        }
    })
</script>

注意点:

  • 声明监听器,使用的关键词是watch
  • 每个监听器的方法,可以接受2个参数,第一个参数是新的值,第二个参数是之前的值
    注意:当需要监听一个对象的改变时,普通的watch方法无法监听到对象内部属性的改变,此时就需要deep属性对对象进行深度监听。

使用对象的数据形式改写上述案例参考代码:

<div id="app">
    <p><input type="text" v-model='userinfo.firstName' placeholder="" /></p>
    <p><input type="text" v-model='userinfo.lastName' placeholder="" /></p>
    <p><input type="text" v-model='userinfo.fullName' placeholder="全名" /></p>
</div>

<script src="./js/vue.js"></script>
<script type="text/javascript">
    const vm = new Vue({
        el: '#app',
        data: {
            userinfo: {
                firstName: '',
                lastName: '',
                fullName: ''
            }
        },
        watch: {
            userinfo: {
                // handler是固定的写法
                handler(val) {
                    this.userinfo.fullName = val.firstName + ' ' + val.lastName
                    // 对象支持引用传值
                    val.fullName = val.firstName + ' ' + val.lastName
                },
                deep: true
            }
        }
    })
</script>

14、过滤器 - filter

作用:(变量修饰器,管道)格式化数据,比如将字符串格式化为首字母大写、将日期格式化为指定的格式等。

  • 过滤器可以定义成全局过滤器和局部过滤器。
  • 过滤器的本质就是一个方法,使用过滤器实际上就相当于方法调用,仅是书写形式上的差异(使用的时候需要用“|”,其也可以被称之为管道(linux中)或变量/数据修饰符)
    在这里插入图片描述
    声明语法:
// 全局过滤器
Vue.filter('过滤器名称',function(value[,arg1,arg2...]){
	//过滤器业务逻辑
	return ....
})

// 局部过滤器
el: '#app',
data: {},
filters: {
    过滤器名称: function(value[,arg1,arg2...]){
        return something
    },
    // ....
}

过滤器的处理函数中的第一个参数固定是绑定的待处理数据,后续可以根据需要添加自定义参数

使用语法:

<!-- 过滤器使用 -->
<div>{{msg | upper}}</div>

<!-- 过滤器允许连续使用,“前 → 后”按顺序执行 -->
<div>{{msg | upper | lower }}</div>

<!-- 过滤器支持在v-bind中使用 -->
<div v-bind:id='id | formatId'></div>

<!-- 过滤器支持传参 -->
<div>{{msg | mysub(1,2)}}</div>

案例:声明转字母为大写的全局过滤器和转字母为小写的局部过滤器并使用

<body>
    <div id="app">
        <h4>{{msg | toUpper}}</h4>
        <h4>{{msg | toLower}}</h4>
    </div>
</body>

<script src="./js/vue.js"></script>
<script type="text/javascript">
    // 全局过滤器:转字母为大写
    Vue.filter('toUpper',(val) => {
        return val.toUpperCase()
    })

    const vm = new Vue({
        el: '#app',
        data: {
            msg: 'HeLLo WoRld'
        },
        // 局部过滤器:转字母为小写
        filters: {
            toLower: (val) => {
                return val.toLowerCase()
            }
        }
    })
</script>

15、混入 - mixin

混入(mixins)是一种分发Vue组件中可复用功能的非常灵活的方式。混入对象可以包含任意组件选项。当组件(vue实例)使用混入对象时,所有混入对象(加的水)的选项将被混入该组件本身的选项(锅底)。【合并】

混入分为全局混入和局部混入。
在这里插入图片描述
示例:

局部混入(按需混入)

<script src="./js/vue.js"></script>
<script type="text/javascript">
    // 定义一个混入对象(局部混入)
    var myMixin1 = {
        created: function () {
            this.hello();
        },
        methods: {
            hello: function () {
                console.log("hello from mixin!");
            },
        },
    };
    
    // Vue实例
    const vm = new Vue({
        mixins: [myMixin],
    });
    
    // 等同于下面的形式
    const vm = new Vue({
        created: function () {
            this.hello();
        },
        methods: {
            hello: function () {
                console.log("hello from mixin!");
            },
        },
    });
</script>

全局混入(强制混入)

<script src="./js/vue.js"></script>
<script type="text/javascript">
    // 全局混入
    Vue.mixin({
        data: {}
        created: function () {
            var myOption = this.myOption;
            if (myOption) {
                console.log(myOption);
            }
        },
    });

    new Vue({
        data: {
            myOption: "hello!",
        },
    });
</script>

注意事项

  • 当组件和混入对象含有同名选项时,这些选项将以恰当的方式进行“合并”,合并策略:
    • data数据对象发生冲突时以组件数据优先(如果data中的数据同名,会以组件内的为准,不同名会合并生成新的data)
    • 同名钩子函数将合并为一个数组,都将被调用,并且混入对象的钩子将在组件自身钩子之前调用
    • 值为对象的选项,例如 methods、components 和 directives,将被合并为同一个对象。两个对象键名冲突时,取组件对象的键值对
  • 全局注册使用时需要格外小心!一旦使用全局混入,它将影响每一个之后创建的 Vue 实例

16、生命周期

每个 Vue 实例在被创建之前/之后都要经过一系列的初始化过程。例如需要设置数据监听、编译模板、挂载实例到 DOM,在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,目的是给予用户在一些特定的场景下添加他们自己代码的机会。

Vue生命周期的主要(一共是11个)阶段:

  • 挂载(初始化相关属性)
    beforeCreate①
    注意点:在此时不能获取data中的数据,也就是说this.msg得到的是undefined
    created②
    beforeMount③
    mounted【页面加载完毕的时候就是此时】④
    注意点:默认情况下,在组件的生命周期中只会触发一次
  • 更新(元素或组件的变更操作)
    beforeUpdate⑤
    updated⑥
    注意点:可以重复触发的,所以不要在更新的生命周期中去做数据的修改操作(例如ajax获取数据再改本地data数据),这样会陷入死循环中。
    销毁(销毁相关属性)
    beforeDestroy⑦
    注意点:销毁组件之前,如果有销毁复杂性的操作(例如定时器,复杂的动画操作等)的需求,则代码可以写在这里
    destroyed⑧

销毁(手动)使用this.$destroy()
在这里插入图片描述

虚拟DOM+diff算法的方式与传统DOM操作相比,有什么好处?

**传统DOM操作:**在一次操作中,往往会伴随多次个DOM节点更新,浏览器收到第一个DOM请求后并不知道还有若干次更新操作,因此会马上执行流程,最终执行若干次。在后续找DOM坐标的时候,可能因为前期更新DOM导致了后续需要寻找的DOM坐标发生了变化。而操作DOM频繁还会出现页面卡顿,影响用户体验。

**虚拟DOM+diff算法:**若一次操作中有若干次更新DOM的动作,虚拟DOM不会立即操作DOM,而是将这若干次更新的diff内容保存到本地一个JS对象中,最终将这个JS对象一次性放到DOM树上,再进行后续操作,避免大量无谓的计算量。

17、拦截器
目的:在请求发出去之前/收到响应之后做一些操作

请求拦截器
在这里插入图片描述
示例代码:

axios.interceptors.request.use(function(config){
    // 在请求发出去之前进行一些信息设置
    return config;
},function(err){
    // 处理响应的错误信息
});

响应拦截器
在这里插入图片描述
示例对象:

axios.interceptors.response.use(function(res){
    // res为axios对象
    return res.data;
},function(err){
    // 处理响应的错误信息
});

18、Vue组件

1、什么是组件

组件 (Component)是 Vue.js 最强大的功能之一,组件是一个自定义元素或称为一个模块,包括所需的模板(HTML)、逻辑(JavaScript)和样式(CSS)。

组件化开发的特点:

  • 标准
  • 分治
  • 重用
  • 组合

组件也是有全局(component)与局部(components)之分。

2、组件的注册及使用

在使用组件时需要注意以下几点:

  • 构造 Vue 实例时传入的各种选项大多数都可以基于原格式在组件里使用,只有一个例外:data必须是函数,同时这个函数要求必须返回一个对象

示例:

data: function(){
    return {
        msg: '你好世界'
    }
}

组件模板template

  • 必须是单个根元素
<!-- 单个根元素 -->
<div>
    <ul>
        <li></li>
    </ul>
    <ul>
        <li></li>
    </ul>
</div>

<!-- 不符合单个根元素的情况 -->
<p></p>
<p></p>
    • 支持模板字符串形式
  • 组件名称命名方式
    • 短横线方式(推荐)
      • my-component
    • 大驼峰方式(只能在其他组件模板字符串中使用,不能在HTML模板中直接使用)
      • MyComponent

大驼峰式组件名不能在HTML模板中直接使用,如果需要在HTML模板中使用,需要将其进行特定规则转化:

  • 首字母从大写转为小写
  • 后续每遇到大写字母都要转化成小写并且在转化后的小写字母前加-

例如,WoDeZuJian这个大驼峰组件名在HTML中使用的时候需要写成wo-de-zu-jian

2.1、全局组件

全局组件注册形式如下:

// 声明全局组件
Vue.component('组件名',{
    data: function(){
        return {
            
        }
    },
    template: `组件模版内容`
})

上述示例中,component()的第一个参数是组件名(实则可以看作是HTML标签名称),第二个参数是一个对象形式的选项,里面存放组件的声明信息。全局组件注册后,任何Vue实例都可以使用。

例如,有以下代码:

// 声明一个全局的HelloWorld组件
Vue.component('HelloWorld', {
  	data: function(){
    	return {
      		msg: 'HelloWorld'
    	}
  	},
  	template: '<div>{{msg}}</div>'
});

2.2、局部组件

局部组件定义后只能在当前注册它的Vue实例中使用,其是通过某个 Vue 实例/组件的实例选项 components 注册。

例如,有以下代码:

var Child = {
  	template: '<div>A custom component!</div>'
}
new Vue({
  	components: {
    	// <my-component/> 将只在父组件模板中可用
    	'my-component': Child,
        // <child/>
        Child
  	}
})

2.3、组件的使用

在HTML模板中,组件以一个自定义标签的形式存在,起到占位符的功能。通过Vue.js的声明式渲染后,占位符将会被替换为实际的内容,下面是一个最简单的模块示例:

示例:

<div id="app">
    <my-component></my-component>
</div>

3、组件间传值
3.1、父→子传值

  • 父组件以属性的形式绑定值到子组件身上(传)
    ** 子组件通过使用属性props接收(收)**
    • props是单向绑定的(只读属性):当父组件的属性变化时,将传导给子组件,但是反过来不会
    • props属性支持两种常见的写法形式
      • 数组(推荐)
        • 优点:书写简单
        • 缺点:不能设置默认值、数据类型
      • 对象
        • 优点:可以设置数据默认值与数据类型
        • 缺点:写法复杂
<body>
    <div id="app">
        <child :day='day'></child>
	</div>
</body>

<script src="./js/vue.js"></script>
<script type="text/javascript">
    var child = {
        // props形式一:数组形式
        props: ['day'],
        // props形式二:对象形式
        props: {
            day: {
                default: '日',
                type: String
            }
        },
        template: '<p>星期{{day}}</p>'
    }
    const vm = new Vue({
        el: '#app',
        data: {
            day: '五'
        },
        components: {
            child
        }
    })
</script>

3.2、子→父传值

  • 子组件模版内容中用 e m i t ( ) 定 义 自 定 义 事 件 , emit()定义自定义事件, emit()emit()方法至少有2个参数
    • 第一个参数为自定义的事件名称(不要和内置的事件重名,例如click、change等)abc
    • 第二个参数为需要传递的数据(可选,如果传可以是任何格式的数据)
  • 父组件模板内容中的子组件占位标签上用v-on(或@)绑定子组件定义的自定义事件名,监听子组件的事件,实现通信

示例代码:每点击子组件按钮给父组件字体加9像素

<body>
    <div id="app">
        <child @anlarge-text='bigger'></child>
        <p :style="{fontSize: fontSize + 'px'}">{{msg}}</p>
    </div>
</body>

<script src="./js/vue.js"></script>
<script type="text/javascript">
    // 子组件
    var child = {
        template: `<button @click="$emit('anlarge-text',9)">点我给父组件字体加9px</button>`,
    }
    // 根组件(父)
    const vm = new Vue({
        el: '#app',
        data: {
            msg: 'hello vue',
            fontSize: 12
        },
        components: {
            child
        },
        methods: {
            bigger: function (n){
                this.fontSize += n
            }
        }
    })
</script>

3.3、EventBus

EventBus又被称之为中央事件总线

在Vue中通过单独的事件中心来管理非父子关系组件(兄弟)间的通信:
在这里插入图片描述

核心步骤 (一共四步)

一,建立事件中心

const eventBus = new Vue()

二, 传递数据

eventBus.$emit('自定义事件名',传递的数据)

三,接收数据

eventBus.$on('自定义事件名'[,callback])

四,销毁事件中心

eventBus.$off('自定义事件名')

案例

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
        <title>Examples</title>
        <meta
            name="viewport"
            content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"
        />
        <meta name="description" content="" />
        <meta name="keywords" content="" />
        <link href="" rel="stylesheet" />
    </head>
    <body>
        <div id="app">
            <laoliu></laoliu>
            <hr />
            <laoyang></laoyang>

            <hr />
            <button @click="gg">离开游戏</button>
        </div>
        <script src="./js/vue.js"></script>
        <script>
            // 1,建立事件中心
            const eventBus = new Vue();

            // 人物:老刘
            Vue.component("laoliu", {
                data: function () {
                    return {
                        hp: 100, // 老刘的血量
                        damage: 8, // 老刘的武力值
                    };
                },
                template: `<div>
                        <div>老刘(心悦会员3级)当前的hp是:{{hp}}</div>
                        <button @click="wlb">发动闪电五连鞭</button>
                    </div>`,
                methods: {
                    // 技能:五连鞭
                    wlb: function () {
						// 2,传递数据
                        eventBus.$emit("mbg", this.damage);
                    },
                },
                created() {
					// 3,接收数据
                    eventBus.$on("gdl", (val) => {
						console.log(val)
                        if (this.hp - val < 0) {
                            alert("老刘冲钱, 满血复活!");
                            this.hp = 100;
                        } else {
                            this.hp -= val;
                        }
                    });
                },
            });

            // 人物:老杨
            Vue.component("laoyang", {
                data: function () {
                    return {
                        hp: 100, // 老杨的血量
                        damage: 12, // 老杨的武力值
                    };
                },
                template: `<div>
                        <div>老杨当前的hp是:{{hp}}</div>
                        <button @click="cqj">发动大力出奇迹</button>
                    </div>`,
                created() {
                    // 让老杨自己拿本本记录hp的扣减情况
                    eventBus.$on("mbg", (val) => {
                        if (this.hp - val < 0) {
                            this.hp = 0;
                            alert("Game over!老刘获胜!");
                        } else {
                            this.hp -= val;
                        }
                    });
                },
                methods: {
                    cqj: function () {
                        eventBus.$emit("gdl", this.damage);
                    },
                },
            });
            new Vue({
                el: "#app",
                data: {},
                methods: {
                    gg: function () {
						// 4,销毁事件中心
                        eventBus.$off("mbg");
                        eventBus.$off("gdl");
                    },
                },
            });
        </script>
    </body>
</html>

3.4、ref(子→父)(了解)

父去取子的数据信息。

ref属性被用来给元素或子组件注册引用信息,引用信息将会注册在父组件的 $refs 对象上。如果在普通的 DOM 元素上使用ref属性,则引用指向的就是 DOM 元素;如果ref属性用在子组件上,引用就指向子组件实例。

  • ref放在标签上,拿到的是原生节点。ref放在组件上 拿到的是组件实例
  • 原理:在父组件中通过ref属性(会被注册到父组件的$refs对象上)拿到组件/DOM对象,从而得到组件/DOM中的所有的信息,也包括值
<!-- 普通DOM -->
<p ref="p">hello</p>
<!-- 子组件 -->
<child-comp ref="child"></child-comp>

<script>
new Vue({
    el: '#app',
    data: {

    },
    mounted: function(){
        console.log(this.$refs.p);
        console.log(this.$refs.child);
        this.$refs.comp.msg = '123' // 修改值
    }
})
</script>

ref属性这种获取子元素/组件的方式虽然写法简单,容易上手,但是其由于权限过于开放,不推荐使用,有安全问题。(不仅可以获取值,还可以获取其他所有的元素/组件的数据,甚至可以修改这些数据。)

4、动态组件

通过使用保留(自定义组件的时候名称不能写这个保留的名称)的 元素,动态地绑定到它的is 特性,我们让多个组件可以使用同一个挂载点(挂载点就是component元素的位置),并动态切换。

语法:

<component :is="xxxxx">
    
</component>
<component :is="xxxxx">
    
</component>

keep-alive的作用:

keep-alive可以将已经切换出去的非活跃组件保留在内存中。如果把切换出去的组件保留在内存中,可以保留它的状态,避免重新渲染。

5、组件插槽(难点)

插槽也是组件传值的一种方式。

组件的最大特性就是重用,而用好插槽能大大提高组件的可重用能力。
插槽的作用:父组件向子组件传递内容。

通俗的来讲,插槽无非就是在子组件中挖个坑,坑里面放什么东西由父组件决定。

插槽类型有:

  • 单个(匿名)插槽
  • 具名插槽
  • 作用域插槽

5.1、匿名插槽

匿名插槽一般就是使用单个插槽(因为单个插槽就一个,所以不需要指定具体的名字)

示例代码

<body>
    <div id="app">
        <!-- 插槽内容 -->
        <alert-box>发生了一点错误。</alert-box>
    </div>
</body>

<script src="./js/vue.js"></script>
<script type="text/javascript">
    // 定义一个全局的组件,组件名:alert-box
    Vue.component("alert-box", {
        template: `
                <div class='demo-alert-box'>
                    <strong>Error:</strong>
                    <slot></slot>
                </div>
		`
    });

    const vm = new Vue({
        el: "#app",
    });
</script>

注意:子组件的slot标签中允许书写内容,当父组件不往子组件传递内容时,slot中的内容才会被展示出来。

5.2、具名插槽

多个插槽。

slot 元素可以用一个特殊的特性 name 来进一步配置如何分发内容。多个插槽可以有不同的名字,具名插槽将匹配内容片段中有对应 slot 特性的元素(填坑的内容会根据名字去匹配slot)。

<body>
    <div id="app">
        <app-layout>
            <h1 slot="header">这里可能是一个页面标题</h1>

            <p>主要内容的一个段落。</p>
            <p>另一个主要段落。</p>

            <p slot="footer">这里有一些联系信息</p>
        </app-layout>
    </div>
</body>

<script src="./js/vue.js"></script>
<script type="text/javascript">
    Vue.component("app-layout", {
        // <!-- layout.html -->
        template: `
            <div class="container">
                <header>
                	<slot name="header"></slot>
                </header>
                <main>
                	<slot></slot>
    			</main>
                <footer>
                	<slot name="footer"></slot>
                </footer>
            </div>
            `
    });

    const vm = new Vue({
        el: "#app",
    });
</script>

具名插槽存在的意义就是为了解决在单个页面中同时使用多个插槽。

5.3、作用域插槽

应用场景:父组件对子组件的内容进行加工处理(子传父)

作用域插槽是一种特殊类型的插槽,(子)作用域插槽会绑定了一套数据,父组件可以拿这些数据来用,于是,情况就变成了这样:例如,样式父组件说了算,但父组件中内容可以显示子组件插槽绑定的数据。

示例代码

<body>
    <div id="app">
        <child>
            <div slot-scope="props">
                <div>父组件</div>
                <h3>{{ props.text }}</h3>
            </div>
        </child>
    </div>
</body>

<script src="./js/vue.js"></script>
<script type="text/javascript">
    Vue.component('child', {
        data: functiion(){
        	return {
        		msg: "我是子组件中的内容"
    		}
    	},
        template: `
            <div>
            	<slot :text="msg"></slot>
            </div>
			`
    })
    const vm = new Vue({
        el: '#app'
    })

案例:使用作用域插槽来实现子传父的效果。




19、Vue-cli
Vue-CLI ≠ Vue,Vue-CLI就是一个Vue工具。
1、单文件组件

在很多 Vue 项目中,我们使用 Vue.component 来定义全局组件,紧接着用 new Vue({ el: '#container '}) 在每个页面内指定一个容器元素。这种方式在很多中小规模的项目中运作的很好,在这些项目里 JS 只被用来加强特定的视图。但当在更复杂的项目中,或者你的前端完全由JS驱动的时候,下面这些缺点将变得非常明显:

  • 所有的组件都放同一个html文件中
  • 没有构建步骤,不能使用npm来管理项目
  • 缺乏语法高亮和提示
  • 没有针对单个组件的css样式支持

针对于上述的问题,vue框架发布了vue-cli项目生成工具,Vue-cli是一个基于 Vue.js 进行快速开发的完整系统, 致力于将 Vue 生态中的工具基础标准化。它确保了各种构建工具能够基于智能的默认配置即可平稳衔接,这样你可以专注在撰写应用上,而不必花好几天去纠结配置的问题。

2、工具安装
网址:http://npmjs.com

## 安装
npm install -g @vue/cli

## 安装成功后,检查
vue --version
vue -V
#  Vue和VueCLI是两回事

## 卸载
npm uninstall -g @vue/cli

如果需要安装其他版本,可以使用npm install -g @vue/cli@版本号的方式进行指定版本。
如果最新版安装不成功,可以尝试以下3种方式去解决:

  • 断网,使用热点共享流量去执行安装命令
  • 安装其他版本
  • 切换一下npm镜像源,切换成taobao

3、创建项目

# 首先需要进入到对应的目录中(英文目录不要有空格及中文),执行如下命令
# 如果当前你的终端工作路径带有中文或者空格,你可以使用`cd 路径`形式进行路径切换,切换到符合要求的路径中
vue create 项目名称(创建时会自己以对应的项目名称生成目录)
## 例
vue create myproject
# 上述命令中,可以允许变的就是`myproject`部分

— 感 谢 支 持 —…

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值