前言:学习了Vue全解之后,也陆续做了两个项目,一个是高仿的C-node社区,一个是一个记账的web-app,做完之后,深觉应该回过头来整理Vue的知识,果然,在整理的时候又发现了很多需要注意的点!!温故而知悉!😄😄😄
Vue全解(上)
一、Vue实例
1.1. 创建实例并且访问
访问Vue实例的属性,都是以$开头的,比如 app.$el
访问data中的实例,直接用app.msg
1.2 生命周期钩子
created Vue实例创建完成,还未挂载
mounted 刚刚挂载
beforeDestory 实例销毁之前,用于解绑
1.3 文本插值
{{ xxx }},或者三元运算符,但是不能写表达式if什么的
<span v-text="apple"></span>
二、指令和事件
v-html:解析HTML
<span v-html="banana"></span> //banana是实例data中的一个对象
//以下是vue实例的内容
let app= new Vue({
el:'#app',
data:{
date:new Date(),
apple:"苹果",
banana:'<span style="color: yellow">香蕉</span>',
className:'transred',
count:0
},
methods:{
add(){
this.count+=1
}
}
})
v-bind:绑定活的属性
比如当某个div的class不是写死的时候,而是从data中获取来的,这个时候这个属性就是活的了,可以从其他组件传过来,可简写为 :
<div v-bind:class="className"></div>
<div :class="className"></div>
// Vue实例data中的 className:'transred'
<style>
.transred{
background-color: red;
}
</style>
v-on: 绑定事件监听
当我们点击按钮时,按钮上的数字+1,点一次+一次,可用@代替
<h3>v-on指令:绑定事件监听</h3>
<button v-on:click="add">{{ count }}</button>
<button @click="add">{{ count }}</button>
三、计算属性
所有vue实例中的数据,都可以在计算属性中直接使用。
getter 和setter 属性,如果默认啥也不写,就直接接function函数,那么他就是getter属性
如果是调用方法的话,只要页面重新渲染,方法就会执行,不许要渲染就不需要重新执行
计算属性:计算属性变与不变,只取决于依赖的数据变化。
何时使用:使用哪一种取决你你是否需要缓存,
当遍历大数组和做大量计算时,应当使用
计算属性,除非你不希望得到缓存。
四、v-bind以及class与style的绑定
应用场景: DOM 元素经常会动态地绑定一些 class 类名或 style 样式
4.1 了解bind指令
v-bind的复习
- 链接的 href 属性和图片的 src 属性都被动态设置了,当数据变化时,就会重新渲染。
- 在数据绑定中,最常见的两个需求就是元素的样式名称 class 和内联样式 style 的动态绑定,它们也是 HTML的属性,因此可以使用 v-bind 指令。我们只需要用 v-bind计算出表达式最终的字符串就可以,不过有时候表达式的逻辑较复杂,使用字符串拼接方法较难阅读和维护,所以 Vue.js 增强了对 class 和 style 的绑定。
4.2 绑定 class 的几种方式
4.2.1 对象语法
- 给 v-bind:class 设置一个对象,可以动态地切换 class,* 值对应true ,false
- 当 class 的表达式过长或逻辑复杂时,还可以绑定一个计算属性,这是一种很友好和常见的
- 用法,一般当条件多于两个时, 都可以使用 data 或 computed
<div :class="{ divStyle:isActive}">
//对象的第一个键名代表class名,第二个代表是否显示的布尔值
4.2.2 数组语法
当需要应用多个 class 时, 可以使用数组语法 , 给:class 绑定一个数组,应用一个 class列表:
- 数组语法绑定class类
<div :class="['css类名1','css类名2']">数组语法</div>
- 数组中嵌套对象
<div :class="['css类名1', 'css类名2', {css类名3: true|false}]"> 数组中嵌套对象</div>
注意对象里面的css类名不用加单引号,和上一节用法是一致的
- 我们利用数组语法,实现需求:为文字增加颜色,并点击按钮实现颜色的切换。
4.3 绑定内联样式
使用 vbind:style (即:style ) 可以给元素绑定内联样式,方法与 :class 类似,也有对象语法和数组语法,看起来很像直接在元素上写 CSS:
演示
绑定style,实现点击按钮,字号变大
效果展示
注意 : css 属性名称使用驼峰命名( came!Case )或短横分隔命名( kebab-case)
五、Vue中的内置指令
5.1基本指令
5.1.1 v-cloak 的用法
一般与display:none进行结合使用作用:解决初始化慢导致页面闪动的最佳实践
5.1.2 v-once 的用法
定义它的元素和组件只渲染一次
<span v-onve>{{oncedata}}</span>
5.1.3 v-if、v-show的用法
实现一个简单的需求:当分数大于90为优秀,大于80小于90为良好,以此类推。最后条件不包含的情况(else)为不及格。
<div id="app">
语文分数
<label>
<input type="text" v-model.number="gride" placeholder="请输入成绩进行判断">
</label>
<p v-if="gride>=90">优秀</p>
<p v-else-if="(gride>=60)&&(gride<90)">良好</p>
<p v-else-if="gride>=0">未及格</p>
<p v-else>未输入</p>
{{gride}}
</div>
不像if-elseif-else条件判断可以做多组条件判断,v-show只能做互斥条件判断(像是硬币正反面,要么是正面,要么是反面)。通常用于切换页面内容的显示。
v-if 和 v-show 的区别?
v-show指令能实现的效果,v-if系列指令都能实现。二者在实现原理上区别呢?
- v-if系列指令,每次执行都会重新创建DOM节点,重新渲染节点元素。注意下面动态图中,左侧每次输入分数变化时,右侧的div节点都重新创建。
- v-show指令不影响DOM节点的创建(Dom节点一定会被创建),只是通过css样式“display:none”控制该dom节点是否显示出来。注意下面动态图中,不会去重新创建h1节点,只是改变样式。
所以对于需要频换切换的页面元素v-show的性能会更好一些。
5.4 v-for 遍历数组-对象-数值序列
方应杭曾经说过:我与重复不共戴天!!!
v-for一定是写在要便利的元素上,v-for后接等号
六、Vue中表单的绑定
6.1 v-model
一、本节说明
前面的章节我们学习了v-bind指定,可以通过模型数据去影响视图。我们都知道VUE是支持双向数据绑定的,那么视图是如何影响数据的呢?那就要学到我们这一节的内容v-model。v-model可以将表单输入绑定到对应的模型数据。
二,效果分析
我们通过v-model实现一个简单的需求
- 通过表单input绑定模型数据message,表单数据变化data.message也发生变化
- 然后通过Mustache表达式,将变化之后的message数据显示到视图页面上
三、 深入理解
v-model实际上是一个语法糖,也就是简写,他实际上包含了两个操作:
- v-bind绑定value属性
- v-on监听表单元素的输入事件,并改变数据
所以,下面的两种写法实现的效果是一致的。
6.2 v-model绑定多选框和单选框
在绝大多数的表单操作中,我们不只要收集文本输入的数据,我们还可能用到单选和多选。通常,实现单选和多选有以下的方式:
- 第一种:input标签type=radio实现单选和type=checkbox实现的多选
- 第二种:select标签-option标签实现的单选与多选
6.3 v-model绑定select
上一小节我们使用 v-model 指令,绑定input标签type=radio和type=checkbox,分别实现了单选和多选的视图向模型数据的绑定。 这一节我们使用select标签和option标签,结合v-model实现单选和多选的视图向模型数据的绑定。
- v-model绑定模型数据mvp,实现单选效果
- v-model绑定模型数据allDefensiveTeam,结合multiple属性实现多选效果
- 多选选项的模型数据为数组类型
- 可以为单选及多选设置默认值,即:默认的勾选项
6.4 v-model的修饰符
v-model.lazy修饰符:默认情况下,input输入会实时影响v-model绑定的数据。加上lazy修饰符,只有当输入框失去焦点会输入回车的时候,才会去改变v-model绑定的数据。v-model.number修饰符:默认情况下,输入框中输入的无论是数字还是字母,都会被当做字符串处理。加上number修饰符,输入内容会被当做数值类型处理。v-model.trim修饰符:可以自动去掉输入内容左右两边的空格
<label>
<input type="text" v-model.lazy="name">
</label>
<h3>球星的名字是: {{name}},typeof识别的类型为: {{typeof name}}</h3>
7.组件化开发
7.1 组件的使用方法
- 注册组件
- 全局组件,权限太大,容错降低
Vue.component('my-component',{
template:`<div>我是全局组件的内容</div>`
})
- 局部注册
const bpp= new Vue({
el:'#bpp',
components:{
'son-component':{
template: `<div>我是子组件bpp的局部组件</div>`
}
}
})
4.html受限
<table>里面的标签只能有<tr> <td> <tbody>,如果我们在里面加上我们的子组件,会发现,这个组件没在<table>里面,反而跳到了他的前面
5.当遇到table标签的时候,使用is组件突破限制
7.2 使用组件的奇技淫巧
- 推荐使用小写字母加
-进行命名(必须)child,my-componnet命名组件 - template中的内容必须被一个DOM元素包括 ,也可以嵌套
- 在组件的定义中,除了template之外的其他选项—data,computed,methods
- data必须是一个方法
7.3 父组件给子组件传递消息
- 在组件中使用
props来从父亲组件接收参数,注意,在props中定义的属性,都可以在组件中直接使用 props来自父级,而组件中datareturn的数据就是组件自己的数据,两种情况作用域就是组件本身,可以在template,computed,methods中直接使用props的值有两种,一种是字符串数组,一种是对象,本节先只讲数组- 可以使用
v-bind动态绑定父组件来的内容
<body>
<div id="app">
<child-component :msg1="message"></child-component>
<child-component msg2="小可爱是谁呀"></child-component>
</div>
<script>
const app = new Vue({
el:"#app",
data:{
message:'我是来自父组件的数据'
},
components:{
'child-component':{
props:['msg1','msg2'],
template:`
<h3>{{msg1}}</h3>
<h3>{{msg2}}</h3>
`
}
}
})
</script>
</body>
7.4关于props的单项数据流
解释 : 通过 props 传递数据 是单向的了, 也就是父组件数据变化时会传递给子组 件,但是反过来不行。
一种是父组件传递初始值进来,子组件将它作为初始值保存起来,在自己的作用域下可以随意使用和修改。这种情况可以在组件 data 内再声明一个数据,引用父组件的 prop
- 步骤一:注册组件
- 步骤二:将父组件的数据传递进来,并在子组件中用props接收
- 步骤三:将传递进来的数据通过初始值保存起来,再去使用。
另一种情况就是 prop 作为需要被转变的原始值传入。这种情况用计算属性就可以了
- 步骤一:注册组件
- 步骤二:将父组件的数据传递进来,并在子组件中用props接收
- 步骤三:将传递进来的数据通过计算属性进行重新计算
7.5 传递数据的数据验证
验证的 type 类型可以是:
StringNumberBooleanObjectArrayFunction
7.7 组件通信
7.7.1子组件给父组件传
经典案例:父组件的余额,子组件里面的按钮可以修改余额
案例解析:
当子组件中的按钮被点击的时候,得使用%emit 触发 change事件,并把需要传递的数据跟上
直接甩代码(重点的步骤我都画了线)
- 第一步:自定义事件(直接在父组件里面,change事件就是我自定义的事件)
- 第二步:在子组件中用$emit触发事件,第一个参数是事件名,后边的参数是要传递的数据
- 第三步:在自定义事件中用一个参数来接受,如上图接收的数据value就是子组件传递过来的count
7.7.2子组件之间的传递
要从组件A传数据给B组件
-
第一步:在根组件的data中定义一个bus中介
-
第二步:当我们点击A组件中的按钮时,A组件执行一个方法,这个方法里面就包含着:
首先
this.$root会拿到这个bus中介,然后bus中介就去提交这个lalala事件,并且触发这个事件,lalala被触发之后就会把this.xxx这个数据给传递过去,传到哪呢,先传到根组件中!!
handle(){
this.$root.bus.$emit('lalala',this.aaa)
}
- 第三步:然后在B组件中,Vue实例创建的时候,就要去监听这个lalala事件,然后在这个事件中接收一个参数,这个参数就是传过来的数据
created(){
this.$root.bus.$on('lalala',function (value){
return( alert(value))
})
}
7.7.3父链$parent
Vue.component('child-component',{
template:'<button @click="setFatherData">通过点击我修改父亲的数
据</button>',
methods:{
setFatherData:function () {
this.$parent.msg = '数据已经修改了'
}
}
})
7.7.4子链$refs
提供了为子组件提供索引的方法,用特殊的属性ref为其增加一个索引,就像这样
const app = new Vue({
el:'#app',
data:{
msg:'数据还未修改',
formchild:'还未拿到'
},
methods:{
getChildData:function () {
//用来拿子组件中的内容 ---- $refs
this.formchild = this.$refs.a.msg;
}
}
})
7.7.5插槽的简单简绍和作用域
抽取共性,保留不同。将共性定义在组件里面,将差异暴露为插槽。这句话我们下文来重点理解。
1.单个插槽
直接演示
<body>
<div id="app">
<my-children> 我是父组件插入进来的内容!</my-children>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.5.16/vue.js"></script>
<script>
let app = new Vue({
el:"#app",
components:{
'my-children':{
template:`
<div style="border: 2px solid red;">\
<slot>\
如果父组件没有插入内容,就显示我
</slot>\
</div>`
}
}
})
</script>
</body>
效果就是:子组件的模板中标签包裹的内容,被替换为父组件使用子组件标签中间的内容————我是父组件插入进来的内容
2.具名插槽
具名插槽:顾名思义,就是有名字的插槽,有了名字之后,子组件就可以用多个不同名字的插槽,那父组件传内容的时候,就有了一一对应的关系!岂不美哉!!!
直接演示!
3.作用域插槽
- 第一步现在子组件中定一个slot,这个slot里面写上需要传递的数据,
- 然后再父组件的模板中,定义一个 slot-scop, 然后用我们后面的变量名.xxx 获取数据 只能拿到除了name 之外的 其他属性
4.组件的高级用法--动态组件
VUE给我们提供 了一个元素叫component
- 作用是: 用来动态的挂载不同的组件
- 实现:使用is特性来进行实现的
5. .sync
如果你想给一个初始的值,然后呢,你还想在它更新的时候。拿到最新的值,那一般就用 .sync
<template>
<div>
<Type :value="a" @update.value="a变化函数" />
</div>
</template>
可以直接写为
<Type :value.sync="a"/>
由于本人水平有限,如有描述不准确的地方请给我留言,欢迎交流~