1. 基本的设计模式
基本的设计模式之MVC模式
MVC是目前应用最广泛的软件架构之一, 一般MVC是指:Model(模型),Controller(控制器),View(视图),这主要是基于分层的目的.
View一般都是通过Controller来和Model进行联系的。Controller是Model和View的协调者,View和Model不直接联系。基本联系都是单向的。

所有的逻辑都在C层,不可避免的会造成C层非常复杂,如果项目越来越大,C层的代码会更加臃肿,维护起来也非常麻烦
基本的设计模式之MVP模式
MVP是从经典的MVC模式演变而来的,它们的基本思想有相通的地方:Controller/Presenter(发布层)负责逻辑的处理,Model提供数据,View负责显示。
在MVP中,Presenter完全把View和Model进行了分离,主要的程序逻辑在Presenter里实现。而且,Presenter与具体的View是没有直接关联的,而是通过定义好的接口进行交互,从而使得在变更View的时候可以保持Presenter不变。

基本的设计模式之MVVM模式
相比前面两种模式,MVVM只是把MVC的Controller和MVP的Presenter改成了ViewModel。
View的变化会自动更新到ViewModel, ViewModel的变化也会自动同步到View上显示。这种自动同步是因为ViewModel中的属性实现了Observer(观察者模式 ),当属性变更时都能触发对应的操作.

2. 什么是Vue?
某种意义上来讲, Vue.js不是一个框架-----它只聚焦视图层,是一个构建数据驱动的web界面的库(当然, 按照目前的发展来看,vue有完善的生态圈, 早可以成为框架)。Vue.js通过简单的API提供高效的数据绑定和灵活的组件系统. Vue内置的额外方法库较少, 比如Router, ajax,表单验证等等一些额外的功能得由我们自行引入
1. Vue的一些基本特性
1.1 轻量化: 生产环境的Vue可以做到才30多KB, 这个代码量非常之小, 是jQuery生产版本体量的几分之一 1.2 数据绑定: 非常方便的讲js控制的数据与页面内容进行绑定, 省去了我们大量的同步设置环节 1.3 指令: 我们可以通过内置指令v-* 和一些自定义的指令来实现我们要实现的业务功能 1.4 方便拓展: 虽说我们vue内置的方法不多,但是可以很方便的去引入一些其他的组件库
2.vue的使用
2.1 vue的引入
直接导入vue.js的框架源码
<script src="./js/vue.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.2.0-beta.1/vue.cjs.js"></script>
2.2 vue的实例创造
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name=viewport
content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no,minimal-ui">
<title>Document</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="app"></div>
<div id="test"></div>
<script>
let vm1 = new Vue({
el: "#app",
data: {
msg: "毛毛大帅逼"
}
})
let vm2 = new Vue({
el: "#test",
data: {
msg: '强哥大帅逼'
}
})
</script>
</body>
</html>
实例创造通过调用new Vue()构造函数来创造,el表示绑定的元素,data表示绑定的数据对象
2.3 vue的插值
文本插值是最基本的形式,使用双大括号{{}}(类似于Mustache,所以本文中称作Mustache标签)
<body>
<div id="app">{{msg}}</div>
<div id="test">{{msg}}</div>
<script>
let vm1 = new Vue({
el: "#app",
data: {
msg: "毛毛大帅逼"
}
})
let vm2 = new Vue({
el: "#test",
data: {
msg: '强哥大帅逼'
}
})
</script>
</body>
例子中的标签{{msg}}将会被相应的数据对象msg属性的值替换掉,当msg的值改变时,文本中的值也会联动地发生变化。
2.4 Vue的表达式插值
Mustache标签也接受表达式形式的值,表达式可由JavaScript表达式构成。表达式是各种数值、变量、运算符的综合体。简单的表达式可以是常量或者变量名称。表达式的值是其运算结果:
- js表达式
a. {{ msg/100 }} //在原始值上除以100 b. {{true?1:0}}//值为真,则渲染出1,否则渲染出0 c. {{ msg.split(“ , ”) }} //把值对应的字符串进行处理
- 无效示例
a. {{ var a = 1 }} // 这是一条语句, 不是表达式 b. {{ if (ok) { return message } }} //控制流程的代码也是没有用的

2.5 Vue的计算属性
模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护
<div>{{msg.split('').reverse().join('')}}</div>
在这个地方,模板不再是简单的声明式逻辑。你必须看一段时间才能意识到,这里是想要显示变量msg的翻转字符串。当你想要在模板中多次引用此处的翻转字符串时,就会更加难以处理。所以针对这样的复杂的处理逻辑, 我们引入了计算属性这一技术来实现
<script>
let vm = new Vue({
el: "#app",
data: {
msg: "毛毛大帅逼111",
num1: 120,
num2: 1,
str1: '真',
str2: '假'
},
computed: {
reverse_msg: function () {
return this.msg.split('').reverse().join('')
}
}
})
</script>


通过上面的数据可以了解到, 在创造vue实例的时候传进去的数据对象和计算属性,最后都是直接成为了实例的属性并且,计算属性并不是把方法给保存了,而是会直接执行这个函数,并把函数的返回结果给保存下来,同样的逻辑, 咱们如果要想修改数据的话,只需直接对vm.msg进行修改即可

注意:不要直接修改vm.reverse_msg(它只有读取的接口),这个数据依赖于vm.msg,只要修改了vm.msg,则它就会自动修改的
2.6Vue的计算属性的setter
计算属性默认只有 getter(只能读取不能设置) ,不过在需要时你也可以提供一个 setter :
<body>
<div id="app">
{{name}}-->{{age}}
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
msg: "毛毛大帅逼",
age: 18
},
computed: {
name: {
get: function () {
return this.msg + ";官方认证"
},
set: function (newValue) {
this.msg = newValue
}
}
},
watch: {
msg: function (val) {
this.age = 20
}
}
})
</script>
</body>
3. vue的方法
我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。
<body>
<div id="app">
<div>这是使用了计算属性的时候:{{reverse_msg}}</div>
<div>这是使用了vue实例方法的时候:{{reverse_msg_met()}}</div>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
msg: "毛毛大帅逼111",
},
computed: {
reverse_msg: function () {
return this.msg.split('').reverse().join('')
}
},
methods: {
reverse_msg_met: function () {
return this.msg.split('').reverse().join('')
}
}
})
</script>
</body>
然而,不同的是计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要msg 还没有发生改变,多次访问reversedMsg 计算属性会立即返回之前的计算结果,而不必再次执行函数。
相比之下,调用方法将总会再次执行函数。
4.Vue的侦听属性
Vue 提供了一种更通用的方式来观察和响应Vue 实例上的数据变动:侦听属性。
<body>
<div id="app">
{{msg}}的年龄是{{age}}
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
msg: "毛毛大帅逼",
age: 18
},
watch: {
msg: function (val) {
this.age = 20
}
}
})
</script>
</body>
4.1 Vue的侦听器的应用
<body>
<div id="app">
<p>
are you ok?
<input type="text" v-model="question">
</p>
<p>答案:{{answer}}</p>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
question: '',
answer: '',
},
watch: {
question: function (val) {
this.answer = val
}
}
})
</script>
</body>
watch很是适合用作与这种ajax的信息监测
3. vue的基本指令
指令 (Directives)是带有 v- 前缀的特殊特性。指令特性的值预期是单个JavaScript 表达式
指令的职责是: 当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM

3.1 Vue的指令之v-once
上面有介绍过,如何将一个vue实例中的data对象中的数据渲染到dom元素中, 但是如果我们只想在网页加载时,只渲染一次数据, 后期即便是data中的数据变化了, 我们也不要再次进行渲染, 那么我们可以用v-once指令
<body>
<div id="app">
{{question}}
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
question: '你好吗?',
answer: '',
},
})
</script>
</body>
//在控制台输入vm.question = 'ok'时,数据会渲染的dom元素中
<body>
<div id="app" v-once>
{{question}}
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
question: '你好吗?',
answer: '',
},
})
</script>
</body>
//使用once后,在控制台输入vm.question = 'ok'时,数据不会渲染的dom元素中
3.2Vue的指令之v-html
双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,我们可以使用 v-html 指令:
<body>
<div id="app">
{{elecode}}
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
elecode: '<h1>你好,世界</h1>'
},
})
</script>
</body>
页面显示:

<body>
<div id="app" v-html='elecode'>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
elecode: '<h1>你好,世界</h1>'
},
})
</script>
</body>
页面显示:

3.3 v-if, v-else, v-show
3.3.1 v-if
v-if指令可以完全根据表达式的值在DOM中生成或移除一个元素。如果v-if表达式赋值为false,那么对应的元素就会从DOM中移除;否则,对应元素的一个克隆将被重新插入DOM中。 记住, 这个是直接决定是否在网页进行渲染, 而不是元素是否显示
<body>
<div id="app">
<div v-if='toggle'>
{{msg}}-->{{age}}
</div>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
msg: '强哥大帅逼',
age: 18,
toggle: false
},
})
</script>
</body>

检查dom元素,完全没有,说明没有渲染
<div style="display: none;">哈哈哈</div>
我们发现页面也没有显示出来

但是我们检查dom元素,发现元素是存在的,只是没有展示出来
3.3.2 V-else指令
顾名思义,v-else就是JavaScript中else的意思,它必须跟着v-if,充当else功能。代码示例如下:
<body>
<div style="display: none;">哈哈哈</div>
<div id="app">
<div v-if='toggle'>
{{msg}}-->{{age}}
</div>
<div v-else>
这里是v-else里面的内容
</div>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
msg: '强哥大帅逼',
age: 18,
toggle: false
},
})
</script>
</body>
页面显示:

3.3.3 V-else-if指令
v-else-if,顾名思义,充当v-if 的“else-if块”,可以连续使用:
<body>
<div id="app">
<div v-if="type === 'A'">
a
</div>
<div v-else-if="type === 'B'">
b
</div>
<div v-else-if="type === 'C'">
c
</div>
<div v-else>
这里是v-else里面的内容
</div>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
type: 'A'
},
})
</script>
</body>
类似于 v-else,v-else-if也必须紧跟在带v-if 或者 v-else-if的元素之后。
注意:这些个if或是else只会有一个生效
3.3.4 V-show指令
v-show指令是根据表达式的值来显示或者隐藏HTML元素。当v-show赋值为false时,元素将被隐藏。查看DOM时,会发现元素上多了一个内联样式style=“display:none”。
代码示例如下:
<body>
<div id="app">
<div v-show="toggle">
{{msg}}--->{{age}}
</div>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
msg: '强哥大帅逼',
age: 18,
toggle: false
},
})
</script>
</body>
3.3.5 V-if和V-show指令辨析
在切换v-if模块时,vue.js有一个局部编译/卸载过程,因为v-if中的模板可能包括数据绑定或子组件。v-if是真实的条件渲染,因为它会确保条件块在切换时合适地销毁与重建条件块内的事件监听器和子组件。
v-if是惰性的一一如果初始渲染时条件为假,则什么也不做,在条件第一次变为真时才开始局部编译(编译会被缓存起来)。
相比之下,v-show简单得多一一元素始终被编译并保留,只是简单地基于切换。
一般来说,v-if有更高的切换消耗,而v-show有更高的初始渲染消耗。
因此,如果需要频繁地切换,则使用v-show较好;如果在运行时条件不大可能改变,则使用v-if较好。
3.4 V-model指令
V-model使用
v-model指令用来在input、select、text、checkbox、radio等表单控件元素上创建双向数据绑定。根据控件类型v-model自动选取正确的方法更新元素。尽管有点神奇,但是v-model不过是语法糖,在用户输入事件中更新数据,以及特别处理一些极端例子。
单向数据绑定: 从数据模型(发生改变) 带视图(进行更新), 视图更新,数据模型不会发生改变
代码示例如下:
<body>
<div id="app">
姓名: <input type="text" v-model="name" placeholder="请输入姓名"><br>
性别: <input type="radio" value="男" v-model='sex'>
<label for="man">男</label>
<input type="radio" value="女" v-model='sex'>
<label for="woman">女</label><br>
兴趣:
<input type="checkbox" id="book" value="读书" v-model='interset'>
<label for="book">读书</label>
<input type="checkbox" id="swin" value="游泳" v-model='interset'>
<label for="swin">游泳</label>
<input type="checkbox" id="game" value="游戏" v-model='interset'>
<label for="game">游戏</label>
<input type="checkbox" id="song" value="唱歌" v-model='interset'>
<label for="song">唱歌</label><br>
你的职业:
<select v-model='work'>
<option value="法师">法师</option>
<option value="射手">射手</option>
<option value="战士">战士</option>
</select>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
name: '',
sex: '',
interset: [],
work: '法师'
},
})
</script>
</body>
改变属性:

v-model会忽略所有表单元素的value、checked、selected特性的初始值而总是将Vue 实例的数据作为数据来源。你应该通过JavaScript 在组件的 data 选项中声明初始值。
v-model事件
在内部为不同的输入元素使用不同的属性并抛出不同的事件:
- text 和 textarea 元素使用 value 属性和 input 事件;
- checkbox 和 radio 使用 checked 属性和 change 事件;
- select 字段将 value 作为 prop 并将 change 作为事件。
不使用v-model实现双向绑定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name=viewport
content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no,minimal-ui">
<title>Document</title>
<script src="./js/vue.js"></script>
<style>
</style>
</head>
<body>
<div id="app">
姓名: <input type="text" v-bind:value='name' @input='fn' placeholder="请输入姓名"><br>
{{name}}
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
name: '',
sex: '',
interset: [],
work: '法师'
},
methods: {
fn: function (event) {
console.log(event.target.value);
this.name = event.target.value
}
}
})
</script>
</body>
</html>
v-model选择框
多个元素使用v-model
多重元素的v-model设置也可以生效的, 两个可以输入的元素的, 任何一个输入,另一个都发生相应的变化
姓名: <input type="text" v-model='name' placeholder="请输入姓名"><br>
<p>你的名字{{name}}</p>
<p>{{msg}}</p>
<p>p你的名字<br>{{name}}</p>
<textarea v-model='name'></textarea><br>
{{name}}
单个复选框
单个复选框,绑定到布尔值:
<br>你结婚了吗?
<input type="checkbox" id="checkbox" v-model="marry">
<label for="checkbox">{{marry}}</label>
多个复选框
多个复选框,绑定到同一个数组:
<br>你的老婆是?<br>
<input type="checkbox" id="checkbox1" value="石原里美" v-model='marryed'>
<label for="checkbox1">石原里美</label>
<input type="checkbox" id="checkbox2" value="新垣结衣" v-model='marryed'>
<label for="checkbox2">新垣结衣</label>
<input type="checkbox" id="checkbox3" value="斋藤飞鸟" v-model='marryed'>
<label for="checkbox3">斋藤飞鸟</label>
<input type="checkbox" id="checkbox4" value="长泽雅美" v-model='marryed'>
<label for="checkbox4">长泽雅美</label>
<br> {{marryed}}
单选按钮
<br>你的老婆是?只能选一个否则重婚罪坐牢!!!<br>
<input type="radio" id="checkbox1" value="石原里美" v-model='marryed'>
<label for="checkbox1">石原里美</label>
<input type="radio" id="checkbox2" value="新垣结衣" v-model='marryed'>
<label for="checkbox2">新垣结衣</label>
<input type="radio" id="checkbox3" value="斋藤飞鸟" v-model='marryed'>
<label for="checkbox3">斋藤飞鸟</label>
<input type="radio" id="checkbox4" value="长泽雅美" v-model='marryed'>
<label for="checkbox4">长泽雅美</label>
<br> {{marryed}}
select选择框
<br>你的老婆是?只能选一个否则重婚罪坐牢!!!<br>
<select v-model='marryed_sel'>
<option value="石原里美">石原里美</option>
<option value="新垣结衣">新垣结衣</option>
<option value="斋藤飞鸟">斋藤飞鸟</option>
<option value="长泽雅美">长泽雅美</option>
</select>
<br> {{marryed_sel}}
如果 v-model表达式的初始值未能匹配任何选项,元素将被渲染为“未选中”状态。在 iOS 中,这会使用户无法选择第一个选项。因为这样的情况下,iOS 不会触发 change事件。因此,更推荐提供一个值为空的禁用选项。
<option value="" disabled='disabled'>请选择名字</option>
v-model修饰符
lazy
在默认情况下,v-model在每次 input事件触发后将输入框的值与数据进行同步(除了上述输入法组合文字时)。你可以添加 lazy 修饰符,从而转变为使用change 事件进行同步:
<body>
<div id="app">
姓名: <input type="text" v-model='name' placeholder="请输入姓名"><br>
姓名_lazy: <input type="text" v-model.lazy='name' placeholder="请输入姓名"><br>
<p>你的名字{{name}}</p>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
name: '',
}
})
</script>
</body>
number
如果想自动将用户的输入值转为数值类型,可以给v-model 添加 number修饰符:
<body>
<div id="app">
姓名: <input type="text" v-model='name' placeholder="请输入姓名"><br>
姓名_lazy: <input type="text" v-model.lazy='name' placeholder="请输入姓名"><br>
姓名_number: <input type="text" v-model.number='name' placeholder="请输入姓名"><br>
姓名_type_number: <input type="number" v-model='name' placeholder="请输入姓名"><br>
<p>你的名字类型{{typeof name}}</p>
<p>你的名字{{name}}</p>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
name: '',
}
})
</script>
</body>
trim
如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符:
<body>
<div id="app">
姓名: <input type="text" v-model='name' placeholder="请输入姓名"><br>
姓名_lazy: <input type="text" v-model.lazy='name' placeholder="请输入姓名"><br>
姓名_number: <input type="text" v-model.number='name' placeholder="请输入姓名"><br>
姓名_type_number: <input type="number" v-model='name' placeholder="请输入姓名"><br>
姓名_trim: <input type="text" v-model.trim='name' placeholder="请输入姓名"><br>
<p>你的名字类型{{typeof name}}</p>
<p>你的名字{{name}}</p>
</div>
<script>
let vm = new Vue({
el: "#app",
data: {
name: '',
}
})
</script>
</body>
|