Vue概念

一.软件架构模式

MVC模式简介

img

M–>model–>负责储存数据–>对象,数组等变量

V–>view–>用户所看到的界面(html,css)

C–>controller–>业务逻辑(事件交互 如何根据视图与用户的交互改变数据–>操作DOM对象进行事件的绑定)

  1. View 传送指令到 Controller
  2. Controller 完成业务逻辑后,要求 Model 改变状态
  3. Model 将新的数据发送到 View,用户得到反馈

eg: Backbone.JS

  1. 用户可以向 View 发送指令(DOM 事件),再由 View 直接要求 Model 改变状态。
  2. 用户也可以直接向 Controller 发送指令(改变 URL 触发 hashChange 事件),再由 Controller 发送给 View。
  3. Controller 非常薄,只起到路由的作用,而 View 非常厚,业务逻辑都部署在 View。所以,Backbone 索性取消了 Controller,只保留一个 Router(路由器) 。

MVP模式简介

img

M–>model–>负责储存数据–>对象,数据等变量

V–>view–>用户所看到的界面(html,css)

P–>presenter–> 包含着组件的事件处理,负责检索 Model 获取资料,和将获取的资料经过格式转换与 View 进行沟通。

  1. 各部分之间的通信,都是双向的。
  2. View 与 Model 不发生联系,都通过 Presenter 传递。
  3. View 非常薄,不部署任何业务逻辑,称为"被动视图"(Passive View),即没有任何主动性,而 Presenter非常厚,所有逻辑都部署在那里。

MVVM模式简介

MVVM 模式将 Presenter 改名为 ViewModel,基本上与 MVP 模式完全一致。

唯一的区别是,它采用双向绑定(data-binding):View的变动,自动反映在 ViewModel,反之亦然。Vue和Angular都采用这种模式。

img

二.VUE使用

img

1.条件渲染

1.v-if  -->如果值为false则目标不会被渲染到页面上 若已经渲染到DOM上,则会从DOM中去除

2.v-show -->display:none  会渲染到DOM上

2.列表渲染

v-for 添加key属性可以使被渲染出的元素具有唯一性

3.模板语法

形如 {{ H?a:b }} 可在其中添加简单的三元运算符

4.计算属性

在computed对象内定义计算规则并在view中调用 会将计算的结果保存  只要参数内容不修改,会调用保存的结果而不会重新计算
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div id="example">
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>

var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// 计算属性的 getter
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('')
}
}
})

5.侦听属性

在watch对象中定义需要监听数据的函数 数据改变就会执行该函数
watch对象中  对象的键名是要监听的数据变量名 键值是要执行的函数
1
2
3
4
5
watch:{
arr:function (val) {
console.log(val)
}
}

6.表单输入绑定

使用v-model进行对数据进行双向数据绑定 修饰符……

7.生命周期

Vue 实例生命周期

什么是vue生命周期?

  • Vue 实例从创建到销毁的过程,就是生命周期。也就是从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称这是 Vue 的生命周期。在整个Vue实例的生命周期中会执行这些钩子函数

beforeCreate

  • 实例初始化之后,this指向创建的实例,不能访问到data、computed、watch、methods上的方法和数据

beforeCreate与created之间

  • 在beforeCreate与created之间进行初始化事件,数据的观测 绑定data数据,methods方法等

created

  • 实例创建完成,可访问data、computed、watch、methods上的方法和数据,未挂载到DOM,不能访问到$el属性。$ref属性内容为空数组

created与beforeMount之间

  • 首先会判断对象是否有el选项。如果有的话就继续向下编译,如果没有el选项,则停止编译,也就意味着停止了生命周期,直到在该vue实例上调用vm.$mount(el)-----如果我们在后面继续调用vm.$mount(el),(挂载dom节点)可以发现代码继续向下执行了
    接下–>template参数选项的有无对生命周期的影响。
    (1).如果vue实例对象中有template参数选项,则将其作为模板编译成render函数。
    (2).如果没有template选项,则将外部HTML作为模板编译。
    (3).可以看到template中的模板优先级要高于outer HTML的优先级
    修改代码如下, 在HTML结构中增加了一串html,在vue对象中增加了template选项: 可以发现template中的内容会覆盖outer HTML中的内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<body>
<div id="app">
<!--html中修改的-->
<h1>{{message + '这是在outer HTML中的'}}</h1>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
template: "<h1>{{message +'这是在template中的'}}</h1>", //在vue配置项中修改的
data: {
message: 'Vue的生命周期'
}
</script>

这下就可以想想什么el的判断要在template之前了~是因为vue需要通过el找到对应的outer template。
在vue对象中还有一个render函数(渲染函数),它是以createElement作为参数,然后做渲染操作

1
2
3
4
5
6
new Vue({
el: '#app',
render: function(createElement) {
return createElement('h1', 'this is createElement')
}
})

可以看到页面中渲染的为this is createElement
因此优先级为render函数选项 > template选项 > outer HTML

beforeMount

  • 在挂载开始之前被调用,beforeMount之前,会找到对应的template,并编译成render函数 给Vue实例添加$el成员 此时的this.$el就是一个 DOM对象 但可以发现,此时 h1中还是通进行占位 因为此时还未挂载到页面上 此时仍是虚拟DOM的形式存在

mounted

  • 实例挂载到DOM上,此时可以通过DOM API获取到DOM节点,$ref属性可以访问 h1处不再是用占位。

beforeUpdate

  • 响应式数据更新时调用,发生在虚拟DOM打补丁之前

updated

  • 虚拟 DOM 重新渲染和打补丁之后调用,组件DOM已经更新,可执行依赖于DOM的操作

beforeDestroy

  • 实例销毁之前调用。这一步,实例仍然完全可用,this仍能获取到实例

destroyed

  • 实例销毁后调用,调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁

8.组件基础

定义一个组件

调用Vue对象的component方法传入自定义组件名称,以及模板等,与根组件唯一区别是无el挂载点。之后就可以在html中通过 <hello></hello>形式调用组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
components:{
'hello':Vue.component('hello',{
template:'<h1 @click="change">{{hxh}}</h1>',
data(){
return {
hxh:'hello 浩哥'
}
},
methods:{
change(){
this.hxh = '123'
}
}
})
}

组件间通信(props)

1.父子组件

1>父传子
在子组件中添加props数组  存放与父组件通信的属性名称 父组件可以把内容通过在props中添加的属性传入子组件中

如果传给子组件的是一个方法,子组件也可以调用该方法。其中父组件方法的this指向父组件,而不是调用的组件。因此子组件调用该方法也可以操作父组件

1
2
3
 <hello :title='name'></hello>
也可以=>
<hello title='ruarua'></hello>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
data(){
name:ruarua
}
components:{
'hello':Vue.component('hello',{
props:['title'],
template:'<h1 @click="change">{{hxh+title}}</h1>',
data(){
return {
hxh:'hello 浩哥'
}
}
})
}

还可以使用更简单的方法来操作 如果在子组件打印this就会发现,this身上绑定了一个$parent属性,你会发现this.$parent === app.因此可以这样**@click=‘$parent.show(item)’**
但是为了降低耦合不建议这样操作
2>子传父

使用$emit方法将子组件的值抛出(this.$emit(‘foodshow’,data)),这个方法接收两个参数–>(‘自定义参数’,‘要抛出的变量’) 在父组件使用组件的位置用自定义事件接收 作为函数的一个参数传入方法中。

1
2
3
4
<div id="app">
<food name='water' @foodshow='show'></food>
<h1>{{food}}</h1>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
components:{
'food':Vue.component('food',{
props:['name'],
template:`<div><h1 v-for='item in foods' @click='show(item)'>{{name}}:{{item}}</h1></div>`,
data(){
return {
foods:['apple','banana','peach']
}
},
methods:{
show:function(data){
this.$emit('foodshow',data)
}
}
})
}

同样的,在父组件中有一个$children 但是为了降低耦合不建议这样操作

2.兄弟组件

v-model

原理

以input上的v-model为例

1
2
3
4
<input type="text" v-model='user($event)'>
getValue(event){
this.value = event.target.value
}

组件上

1
2
3
4
5
6
7
8
<custom-input
v-bind:value="searchText"
v-on:input="searchText = $event"
></custom-input>
等价于
<custom-input
v-model='searchText'
></custom-input>
1
2
3
4
5
6
7
8
9
Vue.component('custom-input', {
props:['value'],
template: `
<input
v-bind:value="value"
v-on:input="$emit('input',$event.target.value)"
>
`
})

插槽——slot

使用

如果你想在组件内添加一些元素

1
2
3
4
5
<custom-input v-model='text'>
<p>{{text}}</p>
</custom-input>
//只需要在template中添加插槽<slot></slot>
//但注意:插槽不能添加在根元素外部

后备内容

如果并未在组件添加元素

1
2
3
4
<slot>
<h1></h1>
</slot>
//slot中的内容将会被渲染到页面

具名插槽

如果你想添加多个插槽

1
2
3
4
5
6
7
8
9
<custom-input v-model='text'>
<template v-slot:name>
<p>HXH</p>
</template>
<template v-slot:age>
<p>18</p>
</template>
</custom-input>
//将你需要添加的元素用template标签包裹 并用v-slot:age的形式声明你想要传给的插槽
1
2
//通过<slot name='age'></slot>接收出入的元素
//没有name属性的template默认name='default'

作用域插槽

如果你希望在使用组件时能够操作组件内部的数据 **v-slot: === # **

1
2
3
4
5
6
<custom-input>
<template v-slot:default="data">
//v-slot:default="data" data是你自定义的props插槽名称 你可以在template元素内部调用子组件的某些数据
<h1 @click='show(data)'>{{data}}</h1>
</template>
</custom-input>
1
2
<slot :data='text'>//text是你能在父组件操作的数据
</slot>

动态组件

如果你想动态的把自定义组件渲染到页面上
在组件上添加is属性 **:is=‘com’ **com就是要渲染的组件

1
2
3
4
5
6
7
<div id="app">
<component :is="com"></component>
<button @click='show(1)'>java</button>
<button @click='show(2)'>python</button>
<button @click='show(3)'>javascript</button>
<button @click='show(4)'>nodejs</button>
</div>

在控制台打印vue实例可以看到 所有声明的组件都放在实例的$options对象的components属性上可以通过调用**this.$options.components[com1]**获取到要渲染的组件

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
let com1 = Vue.component('java', {
template: ` <h1>JAVA</h1>`
})
let com2 = Vue.component('python', {
template: ` <h1>PYTHON</h1>`
})
let com3 = Vue.component('javascript', {
template: ` <h1>JAVASCRIPT</h1>`
})
let com4 = Vue.component('nodejs', {
template: ` <h1>NODE-JS</h1>`
})
let app = new Vue({
el:'#app',
data:{
com:com1
},
methods:{
show(id){
this.com = this.$options.components['com'+id]
}
},
components:{
com1,com2,com3,com4
}
})

9.Vue-cli


Vue概念
https://jing-jiu.github.io/jing-jiu/2021/04/05/Framework/Vue2/vue概念/
作者
Jing-Jiu
发布于
2021年4月5日
许可协议