原理上:proxy和defineProperty
vue 在实例初始化的时候遍历data中的所有属性,并使用Object.defineProperty把这些属性全部转化成getters/setter。这样当追踪数据发生变化时,setter会被自动调用,但是这样做有问题,在添加或者是删除对象的属性时,vue检测不到,因为添加或者是删除的对象没有在初始化进行响应式处理,只能通过$set来调用Object.defineProperty处理,然而vue3的proxy直接代理整个对象而非对象属性,这样只需做一层代理就可以监听同级结构下的所有属性变化,包括新增属性和删除属性。
使用上:安装时的不同;创建项目的不同;目录文件夹的不同。
Vue作为前端主流的框架之一,其基本的使用步骤如下
1、引入
初级阶段可以通过官网下载开发版本 官网,在相应的JS代码段引入。
2、示例如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="hello">
//响应式原理的体现 输出 "hello shixue"
hello {
{
name}}
//输出一个无须列表 包含data中的moives所有数据
<ul>
<li v-for="item in movies">{
{
item}}</li>
</ul>
//实现了一个基本的计数功能
当前计数:{
{
counter}}
<button @click=increament>+</button>
<button @click=decreament>-</button>
</div>
**<script src="vue.js"></script>**
<script>
var app = new Vue({
el: "#hello",
data: {
name: 'shixue',
movies: ['明天会好的','你的姐姐','你的婚礼'],
counter: 0
},
methods: {
increament() {
this.counter++ //实例化对象的this指的是这个创建的这个实例化对象app 这里app已经被挂载到div上了,按钮可以生效。
},
decreament() {
this.counter--
}
}
})
</script>
</body>
</html>
3、Vue实例化对象的组成
1>el: 表示要挂载到哪一个HTML元素上。是字符串型的HTML元素
2>data: 用于显示在浏览器页面的基本数据对象。是对象或者是函数形式,组件中必须使用函数形式,原因如下:JS的对象是引用数据类型,当不同的实例想要引用该对象时,只要有一个实例更改了对象,其他实例中的对象也会更改。但vue中更多的是组件的复用,这就要求每个组件要有自己的数据,所以data采用函数形式而不是对象形式。数据采用函数值返回,可在不同的实例中得到不同的返回值,即每个组件有自己的数据空间,不会干扰其他的组件。
3>methods: 相当于实例化对象的方法。是函数形式
4、viewmodel中methods的基本数据得在data函数中声明之后 才会通过双向绑定送到DOM否则的话,不会在用户界面显示出来,也就是只有view的内容才会显示在用户界面。解决方法:通过vue的全局api $set
()把viewmodel中methods想要输出的属性手动改成一个响应式的。比如以下代码。
<div id="hello">
<ul>
<li v-for="value in obj" :key="value">{
{
value}}</li>
</ul>
<button @click="addObjB">添加 obj.b</button>
</div>
<script src="vue.js"></script>
<script>
var app = new Vue({
el: "#hello",
data() {
return {
obj: {
a: 'obj.a'
}
}
},
methods: {
addObjB() {
//this.$set(data属性,’属性名‘,’属性值‘) 就把该data属性值 和属性名变成动态响应式
this.$set(this.obj, 'b', 'obj.b')
console.log(this.obj);
}
}
})
</script>
这里,我们使用计数器案例分析
<div id="hello">
当前计数:{
{
counter}}
<button @click=increament>+</button>
<button @click=decreament>-</button>
</div>
<script src="vue.js"></script>
<script>
var app = new Vue({
el: "#hello",
data: {
counter: 0
},
methods: {
increament() {
this.counter++
},
decreament() {
this.counter--
}
}
})
</script>
MVVM(Model-view-viewmodel)是一种软件架构设计模式,目的是实现用户界面开发和业务逻辑或后端开发相分离。在计数器案例中,View(视图层)就是浏览器页面,即DOM元素;Model(数据层)是计数器中obj,即data数据;View-Model(视图模型层)是创建的实例化对象。
响应式原理:首先,View-Model根据Data Binding将Model的obj传给DOM元素,显示在用户界面;之后,View-Model根据DOM Listening把监听到的点击事件传给Model,通过methods中的方法,改变obj中的数据,obj更新后的数据在显示在页面中。
MVVM设计模式的优点:
1>、实现了用户界面和业务逻辑的分离,提高View或者是Model的复用性。一个viewmodel可以被多个view绑定,当view中的数据改变的时候,model中的数据必然会改变,这样当想改变整个项目中某一个view的数据时,只需更改model数据即可;同理,一个viewmodel也可以被多个view绑定,提高viewmodel的复用性
2>、实现的DOM数据的自动更新,利用双向绑定,当数据更新后视图自动更新。
MVVM设计模式的缺点:
1>、BUG很难调试,因为是双向绑定的,所以当代码出现bug时不知道是view的问题还是model的问题。双向绑定使得某个位置的bug很容易传送到别的地方。并且数据绑定的声明是指令式的放在view中的,不能利用断点调试错误。
2>、大型项目中的view比较多,viewmodel的建立和维护成本高。
1、Mastache语法 { {}}
作用:用于显示model中的内容,实现数据的双向绑定
<div id="shixue" v-once>
<h2>{
{
message}}</h2>
</div>
<script src="vue.js"></script>
<script>
var app = new Vue({
el: '#shixue',
data: {
message: '你好, 石雪'
}
})
</script>
2、v-once语法
作用:DOM内容只被渲染一次,即使model数据改变,view数据也不会变,适用于内容不允许徐更改的时候
在console中可以改变model的数据,但加了这个属性之后,view永远不会更改
<div id="shixue" v-once>
<h2 v-once>{
{
message}}</h2>
</div>
<script src="vue.js"></script>
<script>
var app = new Vue({
el: '#shixue',
data: {
message: '你好, 石雪'
}
})
</script>
3、v-html语法
作用:当model中的数据为 HTML 代码时 能被DOM正确解析,不会显示HTML代码。后边跟 字符串
<div id="shixue" v-once>
<h2>{
{
message}}</h2> //百度
<h2 v-html="message"></h2> //百度
</div>
<script src="vue.js"></script>
<script>
var app = new Vue({
el: '#shixue',
data: {
message: '百度'
}
})
</script>
4、v-text语法
作用:和{ {}}一样 后边跟字符串
<div id="shixue" v-once>
<h2 v-text="message"></h2>
</div>
<script src="vue.js"></script>
<script>
var app = new Vue({
el: '#shixue',
data: {
message: 'shixue'
}
})
</script>
5、v-pre语法
作用:该元素及其子元素不会被编译用于显示原本的Mastache内容。
<div id="shixue" v-once>
<h2 v-pre=>{
{
message}}</h2>
</div>
<script src="vue.js"></script>
<script>
var app = new Vue({
el: '#shixue',
data: {
message: 'shixue'
}
})
</script>
6、v-cloak语法
作用:该属性在HTML元素解析完之前有,显示Mastache原本内容,解析完之后该属性就消失了。
<div id="shixue" v-once>
<h2 v-cloak>{
{
message}}</h2>
//在6秒之前显示 {
{message}} 6秒之后显示 shixue
</div>
<script src="vue.js"></script>
<script>
setTimeout(() => {
var app = new Vue({
el: '#shixue',
data: {
message: 'shixue'
}
})
}, 6000);
1、作用
实现DOM Listener,实现用户和界面的交互,比如点击按钮 拖拽事件 键盘事件等。
2、基本使用
<div id="shixue">
<h1>{
{
counter}}</h1>
<button @click="add()">+1</button> //引用函数
<button @click="counter++">+1</button> //直接改data数据
</div>
<script src="vue.js"></script>
<script>
var app = new Vue({
el: "#shixue",
data: {
counter: 0
},
methods: {
add() {
this.counter++
}
}
})
</script>
3、HTML中函数调用时的参数问题
<div id="shixue">
<h1>{
{
counter}}</h1>
<button @click="add1()">按钮1</button> //按钮1
<button @click="add1">按钮1</button> //按钮1
<button @click="add2()">按钮2</button> //按钮2 undefined
<button @click="add2">按钮2</button> //按钮2 MouseEvent
<button @click="add3(5)">按钮3</button> //按钮3 5 undefined
<button @click="add3">按钮3</button> //按钮3 MouseEvent undefined
<button @click="add3(5, $event)">按钮3</button> //按钮3 5 MouseEvent
<button @click="add3()">按钮3</button> //按钮3 undefined
</div>
<script src="vue.js"></script>
<script>
var app = new Vue({
el: "#shixue",
data: {
counter: 0
},
methods: {
add1() {
console.log('按钮1');
this.counter++
},
add2(increament) {
console.log('按钮2',increament);
this.counter++
},
add3(num, event) {
console.log('按钮3', num, event);
},
}
})
</script>
注释:
1>、函数没有参数时,小括号写和不写是一样的。
2>、函数有一个参数时,小括号不写 默认传入 函数参数;小括号写了不传参数 undefined;小括号写了传了参数完全正确。
3>、函数有两个参数并且有event时,小括号不写输出MouseEvent但参数未定义;
小括号只写参数,输出参数和undefined; 小括号只写事件,输出事件但参数undefined;小括号都写,参数和事件被正确调用。
4、v-on的修饰符
<div id="app">
<div @click="divClick">
<button @click.stop="btnClick">按钮</button>
//.stop是阻止冒泡 只进行btnClick 不进行divClick
</div>
<a href="http://www.baidu.com" @click.prevent="aClick">百度一下</a>
//.prevent是阻止默认事件,像下边这样的就是点击百度一下之后不会进入百度界面
<input type="text" @keyup.enter="onEnter">
//点击 enter 才有效
<input type="text" @keyup.13="onEnter">
//点击 13 才有效
<button @click.once="btnClick"></button>
//只允许被点击一次 第二次无效
</div>
<script src="vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
},
methods: {
divClick() {
console.log('divClick');
},
btnClick() {
console.log('btnClick');
},
aClick() {
console.log('aClick');
},
onEnter() {
console.log('enter被点击');
}
}
})
</script>
1、作用
绑定从服务器请求过来的动态数据,某些属性。 比如a的href属性,img的src属性,css, style。语法糖 :
{ {}} 是用来绑定内容的。
v-html 是解析内容中有HTML代码的,这种情况下,HTML的标签一般是h p等然而model的数据有HTML代码,所以需要对HTML代码解析。
2、绑定a的href属性和 img的src属性
<div id="shixue">
<a :href="link">vue官网</a>
<img :src="urllink" alt="">
</div>
<script src="vue.js"></script>
<script>
var app = new Vue({
el: '#shixue',
data: {
link: 'http://www.baidu.com',
urllink: 'https://cn.vuejs.org/images/logo.png'
}
})
</script>
3、绑定class常见案例
案例一:点击按钮,变换颜色。
<style>
.active {
color: red
}
</style>
<div id="shixue">
<h1 :class="{'active': isActive}">{
{
message}}</h1>
<button @click="isChange">点击变换颜色</button>
</div>
<script src="vue.js"></script>
<script>
var app = new Vue({
el: '#shixue',
data: {
message: '今天是个好日子!',
isActive: true
},
methods: {
isChange() {
this.isActive = !this.isActive
}
}
})
</script>
案例二:点击哪一个列表,哪一个变换颜色。
<style>
.active {
color: red
}
</style>
<div id="shixue">
<ul>
<li v-for="(item, index) in moives"
:class="{'active':index===currentIndex}" //实现列表的第一个数据显示红色
@click="itemClick(index)">{
{
item}}</li> //实现动态切换列表颜色
</ul>
</div>
<script src="vue.js"></script>
<script>
var app = new Vue({
el: "#shixue",
data:{
moives: ['你的名字', '你的婚礼', '明天会好的'],
currentIndex: 0
},
methods: {
itemClick(index) {
this.currentIndex = index
}
}
})
</script>
案例三:class中放多个样式 以对象形式存在
<style>
.active {
color: red
}
.line {
text-decoration: underline
}
</style>
<div id="shixue">
<h1 :class="{'active': isActive, 'line': isLine}">{
{
message}}</h1>
</div>
<script src="vue.js"></script>
<script>
var app =