Vue基础及架构模式
前端框架angularMVC模式,双向数据绑定,依赖注入reactvirtual DOM(虚拟DOM,即为与DOM一样的对象,操作对象避免DOM的直接操作从而提高性能),性能上辗轧angularvue结合angular和react的优点,MVVM模式,高性能高效率框架架构模式MVC模式M: Model (数据) => 数据保存Model(模型)表示应用程序核心(比如...
前端框架
- angular
MVC模式,双向数据绑定,依赖注入 - react
virtual DOM(虚拟DOM,即为与DOM一样的对象,操作对象避免DOM的直接操作从而提高性能),性能上辗轧angular - vue
结合angular和react的优点,MVVM模式,高性能高效率框架
架构模式
MVC模式
- M: Model (数据) => 数据保存
Model(模型)表示应用程序核心(比如数据库记录列表)。
Model(模型)是应用程序中用于处理应用程序数据逻辑的部分。
通常模型对象负责在数据库中存取数据。 - V: View (视图) => 用户界面
View(视图)显示数据(数据库记录)。
View(视图)是应用程序中处理数据显示的部分。
通常视图是依据模型数据创建的。 - C: Controller (控制器) => 业务逻辑
Controller(控制器)处理输入(写入数据库记录)。
Controller(控制器)是应用程序中处理用户交互的部分。
通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。
MVC 分层有助于管理复杂的应用程序,因为您可以在一个时间内专门关注一个方面。例如,您可以在不依赖业务逻辑的情况下专注于视图设计。同时也让应用程序的测试更加容易。
MVC 分层同时也简化了分组开发。不同的开发人员可同时开发视图、控制器逻辑和业务逻辑。
MVC是一个框架模式,它强制性的使应用程序的输入、处理和输出分开。使用MVC应用程序被分成三个核心部件:模型、视图、控制器。它们各自处理自己的任务。最典型的MVC就是JSP + servlet + javabean的模式。
MVP
MVP是模型(Model)、视图(View)、主持人(Presenter)的缩写,分别代表项目中3个不同的模块。
- 模型(Model):
负责处理数据的加载或者存储,比如从网络或本地数据库获取数据等; - 视图(View):
负责界面数据的展示,与用户进行交互; - 主持人(Presenter):
相当于协调者,是模型与视图之间的桥梁,将模型与视图分离开来。
View与Model并不直接交互,而是使用Presenter作为View与Model之间的桥梁。其中Presenter中同时持有Viwe层以及Model层的Interface的引用,而View层持有Presenter层Interface的引用。当View层某个界面需要展示某些数据的时候,首先会调用Presenter层的某个接口,然后Presenter层会调用Model层请求数据,当Model层数据加载成功之后会调用Presenter层的回调方法通知Presenter层数据加载完毕,最后Presenter层再调用View层的接口将加载后的数据展示给用户。这就是MVP模式的整个核心过程。
MVVM
MVVM架构模式是MVP的演变
- Model
- View
- ViewModel 类似于MVP中的Presenter,唯一区别是它为双向绑定,View的变动自动反映在ViewModel,反之亦然。
- 核心:关注Model的变化,让MVVM框架利用自己的机制去更新DOM,让开发者从操作DOM的繁琐解脱。
安装引入
vue.js官网下载vue.js文件
script标签
<script src="vue.js"></script>
cdn
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
npm
npm install vue
Vue实例化过程
vue是一个构造函数,使用必须先实例化
<script src="libs/vue.js"></script>
<body>
<!-- View层 -->
<div id="app">
<!-- 这个html标签在vue实例化后被vue接管,此处的所有操作都更vue实例相关 -->
插值表达式(得到一个值的式,如三元运算、字符串split()等)
{{username}} - {{age}} = {{gender=='女'? 'female':'male'}}
页面中显示
zc- 18 = female
</div>
<script>
// model层
let model = {
username : "ck",
age : 18,
gender : '女'
}
// ViewModel层
// 是一个view的实例,在实例化过程中,vue会遍历data参数中的数据,写入实例的属性
let vm = new Vue({
// 利用Vue来管理#app这个标签,把div#app这个标签作用根节点
// Vue会重新生成这个元素的所有内容
el : "#app",
data : model
})
</script>
</body>
在浏览器中打开,F12或右击检查打开控制台输入
两种方式
model.username = 'zc'
vm.username = 'zc'
页面中的ck会变成zc,修改实例的属性,model数据与视图都做出响应;修改model另两个也会变。下面描述其原理
Vue响应式属性原理
let person1 = {
name : 'zc',
age : 20
}
let person2 = {
username : 'zc-k',
age : 22
}
1------------------------------------------------
Object.defineProperty(person2,'skill',{
enumberable : true,
get : function(){
console.log('getter');
} ,
set : function(){
console.log('setter');
}
});
浏览器控制台输入
person2.skill; // 获取值 执行get内容 打印getter
person2.skill = 'js'; // 设置值 执行set内容 打印setter
2------------------------------------------------
Object.defineProperty(person2,'skill',{
enumberable : true,
get : function(){
let res = person1.age - 1;
return res;
} ,
set : function(val){
person1.age = val;
}
});
浏览器控制台输入
person2.skill; // 操作了person1的age属性 现 age为17
person2.skill = 20; // 操作了person1的age属性 现 age为val(20)
这样就能够通过操作一个对象的属性去改变其他对象的属性
Vue就是通过这样的方法进行系列操作实现响应,就如操作了ViewModel同时改变View和Model的值
<script src="libs/vue.js"></script>
<body>
<div id="app">
{{username}}
</div>
<script>
// Vue在实例化时会遍历data中所有属性,并把他们设置成存储器属性
let model = {
username : "zc",
age : 18,
gender : '女'
}
let vm = new Vue({
el : "#app",
data : model
})
// 实例化后model中的属性被Vue转成存储器属性
console.log(model);
// 并把属性写入vm实例,所以操作model和vm都能有响应
console.log(vm);
// vm.$data即为model
console.log(vm.$data);
// vm.$el即为绑定的节点div#app
console.log(vm.$el);
</script>
</body>
Vue指令
指令解析
<script>
new Vue({
el : ".zc"
data : {
name : "zc"
}
})
</script>
前半部分如这里的v-text会在vue.js文件中找到解析
后半部分如这里的name会在对应的vue实例中data找到解析
<div class="zc" v-text="name"></div>
v-text
<div id="show">
两者效果一致,但{{}}形式会先加载{{}}再加载里面的的内容
网络差时,会出现大量的{{}},视图体验不好,建议使用v-text指令
<p v-text="name"></p>
<p>{{name}}</p>
</div>
<script>
let zc= new Vue({
el : "#show",
data : {
name : "zc"
}
})
</script>
v-html
<div id="show">
v-html 若内容包含标签结构,会进行标签解析
v-text 会直接将内容当作字符串显示
<p v-html="name"></p>
<p v-text="name"></p>
</div>
<script>
let zc= new Vue({
el : "#show",
data : {
name : `<span class="zc">zc</span>`
}
})
</script>
v-show & v-if
v-show 用法:
切换元素的 display CSS 属性。当条件变化时该指令触发过渡效果。
v-if 用法:
根据表达式的值的真假条件渲染元素。在切换时元素及它的数据绑定 / 组件被销毁并重建。如果元素是 ,将提出它的内容作为条件块。
当条件变化时该指令触发过渡效果。
<div id="show">
v-show 里面值或表达式为true时显示,为false隐藏,标签结构仍在
<p v-text="name" v-show="bool"></p>
<p v-html="name" v-show="false"></p>
</div>
<script>
let zc= new Vue({
el : "#show",
data : {
name : `zc`,
bool : true
}
})
</script>
<div id="show">
v-if 里面值或表达式为true时显示,为false移除节点,标签结构删除
<p v-text="name" v-if="bool"></p>
<p v-text="name" v-if="num>3"></p>
</div>
<script>
let zc= new Vue({
el : "#show",
data : {
name : `zc`,
bool : true,
num : 1
}
})
</script>
那么什么时候用v-show,什么时候用v-if?
状态经常不断变化用show,反之用if,因为if操作节点性能消耗高,而且if删除节点会把节点的绑定事件一并删除
v-if & v-else & v-else-if
<div id="show">
v-else 和 v-else-if 前一兄弟元素必须有 v-if 或 v-else-if
也就是说if、else if、else要连用,不能中断。
<p v-html="name" v-if="type === 'A'"></p>
<div v-else-if="type === 'B'">
BBBB
</div>
<div v-else>
AAAAA
</div>
</div>
<script>
let zc= new Vue({
el : "#show",
data : {
name : `zc`,
type : 'A'
}
})
</script>
v-for
<div id="show">
v-for 循环生成标签,for in可遍历数组对象
遍历数组时,con拿到数组内容,idx拿到数组下标
遍历对象时,con拿到对象的值, idx拿到对象的键
<div v-for="(con,idx) in contents" v-text="con" :data-idx="idx">
</div>
</div>
<script>
let zc= new Vue({
el : "#show",
数组
data : {
contents : ['zc','zc']
}
对象
data : {
contents : {
name : 'zc',
age : 18
}
}
})
</script>
v-on
<div id="show">
v-on事件绑定,v-on:简写为@
<div v-text="name" v-on:click="testclick">
<div v-text="name" @click="testclick">
</div>
</div>
<script>
let zc= new Vue({
el: "#show",
data: {
name: 'zc',
},
methods: {
testclick(){
console.log(this.name);
}
}
})
</script>
v-bind
<div id="show">
v-bind用于绑定 DOM 属性,v-bind简写为:
<div v-text="name" v-bind:data-name="name"></div>
<div v-text="age" :data-age="age"></div>
在绑定 class 或 style 特性时,支持其它类型的值,如数组或对象。
为true写入该类名,为false不写入该类名
<div :class="{
'zc' : true,
'zc' : false
}"></div>
<div :style="{ fontSize: 18 + 'px' }"></div>
</div>
<script>
let zc= new Vue({
el: "#show",
data: {
name: 'zc',
age: 18
}
})
</script>
v-model
<div id="show">
用 v-model 指令在表单 <input>、<textarea> 及 <select>
元素上创建双向数据绑定,会改变view和model层数据
<div v-text="name"></div>
<input v-model="name" />
</div>
<script>
let zc= new Vue({
el: "#show",
data: {
name: 'zc'
}
})
</script>
指令总结
更改一方改变另一方的指令图示
Vue实现tab切换
使用bootstrap.css
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="./libs/bootstrap.css">
<style>
.collapse{
display: block;
}
</style>
</head>
<body>
<div id="app" class="container">
<ul class="nav nav-tabs">
<li class="nav-item" v-for="(tab,idx) in tabs">
<!-- active:true 加active类名 active:false 不加 -->
<a class="nav-link" href="#" v-bind:class="{active:idx===currentIdx}"
@click="change(idx)">{{tab}}</a>
</li>
</ul>
<div class="collapse">
<!-- v-show=true 显示 v-show=false 隐藏 -->
<div class="card card-body" v-for="(con,idx) in contents" v-show="idx===currentIdx">
{{con}}
</div>
</div>
</div>
<script src="libs/vue.js"></script>
<script>
// Vue开发,不需要我们过多关注DOM节点操作,而是把精力放大数据和业务结构
/*
指令
v-for 遍历
v-bind 可以绑定任意属性
简写 :
v-show 显示,隐藏 建议操作节点频繁用
v-if 显示,移除节点 建议操作节点不频繁用
v-on 事件绑定
简写 @click
*/
let vm = new Vue({
el : '#app',
//数据
data : {
tabs : ['aa','bb','cc'],
contents : ['lemon','tian','xie'],
currentIdx : 0
},
//方法
methods : {
change(idx){
this.currentIdx = idx;
}
}
})
</script>
</body>
</html>
axios 安装
npm安装
npm install axios
第三方js库axois,使用ajax技术封装的接口,npm官方文档中axois的post请求会出问题,下面是解决说明链接
axois POST请求问题
https://github.com/Wscats/vue-tutorial/issues/16
配合vue使用
这里配合第三方模块axios、request使用
npm axois文档
文档中axois请求方法有then和catch,说明返回的是一个Promise
npm request文档
express脚手架中routes的index.js
var express = require('express');
var request = require('request');
var router = express.Router();
/* GET home page. */
router.get('/', function (req, res, next) {
res.render('index', {
title: 'Express'
});
});
router.get('/zc', async (req, res, next) => {
let getData = () => {
return new Promise((resolve, reject) => {
//利用request模块请求数据,是服务器代理解决跨域方式,是下下策
//开发时可以这么做,若上线时前后端继续分离,则要上线前端nodejs服务器和后端服务器
request('https://zc.com?xxx json数据链接', (err, response, body) => {
resolve(body)
})
})
}
let data = await getNews();
res.send({
status: 1,
data:JSON.parse(data)
});
});
module.exports = router;
express脚手架中javascripts的一个js文件
new Vue({
//拿到数据在#zc元素中以v-for方式拿到data渲染
el: "#zc",
data: {
dataArr: []
},
methods: {
async loadMore() {
let data = await axios.get('http://localhost:3000/zc', {
params: {
ID: 18 //此处传参无意义
}
})
console.log(data);
//把得到的对象拿到对象中数据位置属性名的对应内容存入数组
//concat() 方法用于连接两个或多个数组
//将原本的数组接上添加内容,返回合并后的数组:arr.concat(addcontent)
this.dataArr = this.dataArr.concat(data.data)
}
},
//生命周期函数,创建后执行created()函数
created() {
this.loadMore();
}
}
计算属性和侦听器
计算属性
<div id="zc">
data和computed的name同样这样调用,因此不能重名
<p v-text="dname"></p>
<p v-text="cname"></p>
</div>
<script>
new Vue({
el : "#zc",
//data存放默认固定的数据
data : {
dname : 'zc'
},
//computed计算属性,用于需要经过处理或计算等逻辑得到数据
//计算属性是特殊的data computed强于data
computed : {
cname(){
let str = 'kz';
return `zc` + str;
}
}
})
</script>
侦听器
<div id="zc">
<input v-model="name" />
<p v-text="name"></p>
</div>
<script src="../../js/vue.js"></script>
<script>
new Vue({
el: "#zc",
data: {
name: "zc"
},
// 监听name的变化,如果有变化,执行对应的函数
watch: {
name() {
console.log(this.name)
}
}
})
</script>
更多推荐
所有评论(0)