vue
基础知识
理解MVVM、MVC、MVP
1.MVC(Model-View-Controller)是模型-视图-控制器
2. MVP(Model-View-Presenter)是模型-视图-表示器
3. MVVM(Model-View-ViewModel)是模型-视图-视图模型
MV系列框架中,M和V分别指Model层和View层,但其功能会因为框架的不同而变化。
Model层是数据模型,用来存储数据;
View层是视图,展示Model层的数据
VUE Cli项目搭建
1.(安装vue3) 下载vue脚手架(下载一次就行了 以后不用下载了)
npm i @vue/cli -g
2.vue-cli创建项目 (vue create 项目名)
vue create project
3.vue-cli创建时配置
Maually select features 手动选择特性
选中以下的项目
❯◉ Babel
用来解析es6转换es5的
◯ TypeScript
使用typescript语言开发
◯ Progressive Web App (PWA) Support
一是给项目添加一些webapp支持,比如在手机端支持发送到桌面图标
二是增加可离线支持
◯ Router
Vue中路由的跳转传参
◯ Vuex
Vue中全局状态的管理
◯ CSS Pre-processors
css预格式化处理,可以使用三种流行的CSS预处理器:Sass、LESS 和 Stylus
◉ Linter / Formatter
vue格式检查,代码检查
◯ Unit Testing
单元测试
◯ E2E Testing
端到端测试,与单元测试不同,测试整个应用
选3.x
vue基本语法
模板语法
`插值`
<div>{{ msg }}</div>
`js表达式`
1.所有的数据绑定中都支持完整的 JavaScript 表达式
2.绑定在表达式中的方法在组件每次更新时都会被重新调用,比如改变数据或触发异步操作
<div v-cloak>{{ bool ? "确定" : "取消"}}</div>
{{ message.split('').reverse().join('') }}
`v-cloak`
1.减少闪现问题
2.会保留在所绑定的元素上,直到相关组件实例被挂载后才移除
<div v-cloak>
{{ message }}
</div>
[v-cloak] {
display: none;
}
文本类指令
`v-html`
等同innerHTML
<div v-html="a1"></div>
`v-text`
将文本放在div中,相当于innerText
<div v-text="a1"></div>
1.v-text 用于渲染纯文本内容,不会解析任何 HTML 标签
2.v-html 则用于输出HTML内容,会将数据对象上的值设置为元素的 innerHTML,这意味着任何 HTML 标签都会被浏览器解析并显示为标签
`v-pre`
所有 Vue 模板语法都会被保留并按原样渲染
显示原始双大括号标签及内容。
<div v-pre>{{ a1 }}</div>
<div v-pre>{{ "<button></button>" }}</div>
data() {
return {
a1: `我叫小波,今年1岁`
}
}
属性绑定
如果一个属性的值是变量,boolean类型,number类型,对象,数组,null,undefined,使用绑定属性
给把绑定的东西做为当前元素的一个属性
`v-bind`
<div v-bind:class="id"></div>
<div :class="id"></div>
<div class="id"></div>
data() {
return {
id: "div1",
}
}
事件绑定
`v-on`
用来监听 DOM 事件,并在事件触发时执行对应的 JavaScript
用法:v-on:click="methodName" 或 @click="handler"
1.内联事件处理器 在设置的事件内就可以触发执行
事件被触发时执行的内联 JavaScript 语句
<button @click="count++">按钮{{ count }}</button>
2.方法事件处理器 在设置的事件内写成一个方法,在script内使用这个方法
一个指向组件上定义的方法的属性名或是路径
<button @click="clickHandler">按钮{{ count }}</button>
<button @click="clickHandler3(1,count)">按钮</button>
<button @click="clickHandler3(1,$event)">按钮</button>
methods: {
clickHandler(e) {
console.log("aaa");
this.count++;
}
clickHandler3(n, count) {
console.log(n, count);
}
}
`:value`
`v-model`
暂时仅用于表单的数据双向绑定
`事件修饰符`
1. .stop 在当前元素事件后加.stop会停止当前元素事件抛发
<a @click.stop="doThis"></a>
2. .prevent 提交事件将不再重新加载页面
<form @submit.prevent="onSubmit"></form>
3. .self 当设置后,只有点击当前元素自身才会触发,当前元素子元素不会冒泡给当前元素
<div @click.self="doThat"></div>
4. .once 点击事件最多被触发一次
<a @click.once="doThis"></a>
5. .capture 添加事件监听器时,使用 `capture` 捕获模式
例如:指向内部元素的事件,在被内部元素处理前,先被外部处理
6. .passive 滚动事件的默认行为 (scrolling) 将立即发生而非等待`onScroll` 完成
以防其中包含 `event.preventDefault()`
<div @scroll.passive="onScroll"></div>
<a @click.stop.prevent="doThat"></a>
<form @submit.prevent></form>
案例1
`.prevent :value v-model的使用`
<form @submit.prevent="submitHandler">
<input type="text" name="user" :value="formData.user">
<input type="password" name="password" :value="formData.password" autocomplete="">
<input type="text" name="user" v-model="formData.user">
<input type="password" name="password" v-model="formData.password" autocomplete="">
<button type="submit">提交</button>
</form>
data() {
return {
formData: { user: "", password: "" }
}
}
methods: {
submitHandler() {
console.log(this.formData)
}
}
案例2
`.self .stop的使用`
<div class="div1" @click="divClickHandler1">
<div class="div2" @click="divClickHandler2">
<div class="div3" @click.stop="divClickHandler3"></div>
</div>
</div>
methods: {
divClickHandler1() {
console.log("div1");
},
divClickHandler2() {
console.log("div2");
},
divClickHandler3() {
console.log("div3");
}
}
}
条件渲染
`v-if、v-else-if、v-else`
1.用于条件性地渲染一块内容,这块内容只会在指令的表达式返回真值时才被渲染
2.可以使用 v-else 为 v-if 添加一个“else 区块”
3.一个 v-else 元素必须跟在一个 v-if 或者 v-else-if 元素后面,否则它将不会被识别
`使用`
<div v-if="count == 0">0</div>
<div v-else-if="count == 1">1</div>
<div v-else-if="count == 2">2</div>
<div v-else>3</div>
<button @click="clickHandler2">按钮</button>
data() {
return {
count: 1
}
}
methods: {
clickHandler2() {
this.count = (this.count + 1) % 4
}
}
`v-show` 用法与v-if同样
<div v-show="first">3</div>
<button @click="clickHandler1">按钮</button>
data() {
return {
first: false
}
}
methods: {
clickHandler1() {
this.first = !this.first;
}
}
1.v-if是渲染时条件不满足不渲染当前元素,即页面中不存在该元素
2.v-else 和 v-else-if 可以在 <template> 上使用
3.v-show是条件不满足时给当前元素添加dispaly:none(隐藏),元素仍然存在
4.v-show不支持在 <template> 元素上使用,也不能和 v-else 搭配使用
5.如果需要频繁切换,则使用 v-show 较好;如果在运行时绑定条件很少改变,则 v-if 会更合适
列表渲染
`v-for`
1.基于一个数组(对象、字符串)来渲染一个列表
2.v-for 指令的值需要使用 item in items 形式的特殊语法,其中 items 是源数据的数组,而 item 是迭代项的别名
3.在 v-for 块中可以完整地访问父作用域内的属性和变量
4.v-for 也支持使用可选的第二个参数表示当前项的位置索引
`key的作用`
一般说key,只要说配合v-for的使用
key是Vue中的vnode标记的唯一id,通过key可以使diff操作更准确、更快速
`使用`
<ul>
<li v-for="(value, index) in list" :key="index">{{ value }}</li>
</ul>
<ul>
<li v-for="(value, key) in obj" :key="key">{{ value }}</li>
</ul>
data() {
return {
first: false,
count: 1,
list: ["A","B","C","D","E","F"],
obj: { a: 1, b: 2, c: 3 }
}
}
`vue3中,v-if的优先级高于v-for
vue2中,v-for的优先级高于v-if`
案例1
`渲染表格`
<table>
<thead>
<tr>
<!--
此处v-for 遍历的是data[0]
data[0] 是数值data里的第一项
data[0]是个对象 value是对象中的属性值 key是对象中的属性名
让列表格中渲染的是key属性名
-->
<th v-for="(value,key) in data[0]" :key="key">{{ key }}</th>
</tr>
</thead>
<tbody>
<!--
此处v-for遍历的是data data是个数组
item就是对应数组的值 index就是对应值的下标
-->
<tr v-for="(item,index) in data" :key="index">
<!--
此处v-for 遍历的是item
让表格中渲染的是value属性值
-->
<td v-for="(value,inx) in item" :key="inx">{{ value }}</td>
</tr>
</tbody>
</table>
data() {
return {
data: [
{ id: 1001, name: "商品1", price: 3001, num: 1, total: 3001 },
{ id: 1002, name: "商品2", price: 1233, num: 1, total: 4682 },
{ id: 1003, name: "商品3", price: 4321, num: 4, total: 16884 },
{ id: 1004, name: "商品4", price: 5421, num: 3, total: 4121 },
{ id: 1005, name: "商品5", price: 2343, num: 5, total: 1243 },
]
}
}
案例2
`点击按钮渲染列表 会背!!!`
<ul>
<li v-for="(value, index) in list" :key="index">{{ value }}<button @click="deleteHandler(index)">×</button>
</li>
</ul>
<form action="" @submit.prevent="addDataHandler">
<input type="text" v-model="inputText">
<button>添加</button>
</form>
<button @click="prevHandler">上一步</button>
<button @click="nextHandler">下一步</button>
<!-- 打印 current history 观察效果-->
<div>{{ current }}</div>
<div>{{history}}</div>
data() {
return {
list: [],
inputText: "",
current: -1,
history: []
}
}
methods: {
addDataHandler() {
if (this.inputText.trim().length === 0) return;
this.list = this.list.concat(this.inputText)
this.inputText = ""
this.history.push([...this.list])
this.current = this.history.length - 1
},
deleteHandler(index) {
this.list = this.list.toSpliced(index, 1)
this.history.push([...this.list])
this.current = this.history.length - 1
},
prevHandler() {
if (this.current - 1 < -1) return;
this.current--;
this.list = this.history[this.current]
},
nextHandler() {
if (this.current + 1 > this.history.lenght - 1) return;
this.current++;
this.list = this.history[this.current];
}
}
.lazy
`失焦后才会更新数据`
<input type="text" v-model.lazy="userText" @input="inputHandler" @change="changeHandler">
<input type="text" v-model="userText" @input="inputHandler">
inputHandler(){
console.log(this.userText)
},
changeHandler(){
console.log(this.userText,"change")
}
.number
<input type="text" v-model.number="userText" @input="inputHandler" @change="changeHandler">
changeHandler(){
console.log(this.userText,"change")
}
类与样式绑定
<template>
<div>
<div :class="div1"></div>
<div :class="{ div2, div3 }"></div>
<button @click="div3 = !div3">按钮</button>
<div :class="div4"></div>
<div :class="flag ? 'a b' : ''"></div>
<!-- 正常写法 -->
<div style="width:50px;height:50px;background-color: red;"></div>
<!-- 类与样式绑定写法 -->
<div :style="{ width: w, height: w, backgroundColor: color }"></div>
<!-- 变量绑定写法 -->
<div :style="divs"></div>
<div class="div1" :style="{ left: left + 'px' }"></div>
</div>
</template>
<script>
export default {
data() {
return {
div1: "div1 div2",
div2: true,
div3: false,
div4: ["div1", "div2"],
w: "50px",
color: "blue",
divs: {
width: "50px",
height: "50px",
backgroundColor: "green"
},
left: 0
}
},
mounted() {
setInterval(() => {
this.left++;
}, 16)
}
}
</script>
<style scoped>
.div1 {
width: 50px;
height: 50px;
background-color: green;
position: absolute;
}
</style>
`补充 mounted`
mounted生命周期函数是Vue实例在挂载完成后的执行函数
虚拟dom第一次渲染真实dom的时候叫挂载成功,之后再虚拟dom给真实dom叫更新