跟着 coderwhy老师学习的
邂逅Vuejs
认识Vuejs
- Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。
-
什么是渐进式框架呢?表示我们可以在项目中一点点来引入和使用Vue,而不一定需要全部使用Vue来开发整个
项目;
-
源码使用TypeScript来进行重写:
在Vue2.x的时候,Vue使用Flow来进行类型检测;
在Vue3.x的时候,Vue的源码全部使用TypeScript来进行重构,并且Vue本身对TypeScript支持也更好了;
-
使用Proxy进行数据劫持
-
删除了一些不必要的API:
移除了实例上的$on, $off 和 $once;
移除了一些特性:如filter、内联模板等;
-
包括编译方面的优化:
生成Block Tree、Slot编译优化、diff算法优化;
-
由Options API 到 Composition API:
在Vue2.x的时候,我们会通过Options API来描述组件对象;
Options API包括data、props、methods、computed、生命周期等等这些选项;
存在比较大的问题是多个逻辑可能是在不同的地方:
比如created中会使用某一个method来修改data的数据,代码的内聚性非常差;
Composition API可以将 相关联的代码 放到同一处 进行处理,而不需要在多个Options之间寻找;
-
Hooks函数增加代码的复用性:
在Vue2.x的时候,我们通常通过mixins在多个组件之间共享逻辑;
但是有一个很大的缺陷就是 mixins也是由一大堆的Options组成的,并且多个mixins会存在命名冲突的问题;
在Vue3.x中,我们可以通过Hook函数,来将一部分独立的逻辑抽取出去,并且它们还可以做到是响应式的;
安装vue
1.CDN引入
<script src="https://unpkg.com/vue@next"></script>
2.下载引入
下载Vue的源码,可以直接打开CDN的链接:
打开链接,复制其中所有的代码;
创建一个新的文件,比如vue.js,将代码复制到其中;
3.npm安装
4.直接通过Vue CLI创建项目,并且使用它
Vue的使用
<div id="app">
<h2>Hello World</h2>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const why = {
template: '<h2>Hello World</h2>'
}
const app = Vue.createApp(why);
app.mount("#app")
</script>
vue的生命周期/MVVM
-
MVC和MVVM都是一种软件的体系结构
MVC是Model – View –Controller的简称,是在前期被使用非常框架的架构模式,比如iOS、前端;
MVVM是Model-View-ViewModel的简称,是目前非常流行的架构模式;
-
通常情况下,我们也经常称Vue是一个MVVM的框架。
Vue官方其实有说明,Vue虽然并没有完全遵守MVVM的模型,但是整个设计是受到它的启发的。
template写法
<script type="x-template" id="why">
<div>
<h2>{{message}}</h2>
<h2>{{counter}}</h2>
<button @click='increment'>+1</button>
<button @click='decrement'>-1</button>
</div>
</script>
<template id="why">
<div>
<h2>{{message}}</h2>
<h2>{{counter}}</h2>
<button @click='increment'>+1</button>
<button @click='decrement'>-1</button>
<button @click="btnClick">按钮</button>
</div>
</template>
注意点
-
methods 里面的方法 为什么不能写成箭头函数?
写成箭头函数以后,就会找上层的作用域,上层的作用域就是 script 指向的就是 window
vue3.x 中,this不再是指向的 实例,而是一个 proxy
-
vscode 新建代码片段
具体的步骤如下:
第一步,复制自己需要生成代码片段的代码;
第二步,https://snippet-generator.app/在该网站中生成代码片段;
第三步,在VSCode中配置代码片段;
基础语法
插值表达式(胡子语法|插值语法等)
<div id="app"></div>
<template id="my-app">
<!-- 1.mustache的基本使用 -->
<h2>{{message}} - {{message}}</h2>
<!-- 2.是一个表达式 -->
<h2>{{counter * 10}}</h2>
<h2>{{ message.split(" ").reverse().join(" ") }}</h2>
<!-- 3.也可以调用函数 -->
<!-- 可以使用computed(计算属性) -->
<h2>{{getReverseMessage()}}</h2>
<!-- 4.三元运算符 -->
<h2>{{ isShow ? "哈哈哈": "" }}</h2>
<button @click="toggle">切换</button>
<!-- 错误用法 -->
<!-- var name = "abc" -> 赋值语句 -->
<!-- <h2>{{var name = "abc"}}</h2>
<h2>{{ if(isShow) { return "哈哈哈" } }}</h2> -->
</template>
<script src="../js/vue.js"></script>
<script>
const App = {
template: '#my-app',
data() {
return {
message: "Hello World",
counter: 100,
isShow: true
}
},
methods: {
getReverseMessage() {
return this.message.split(" ").reverse().join(" ");
},
toggle() {
this.isShow = !this.isShow;
}
}
}
Vue.createApp(App).mount('#app');
</script>
插值操作
- v-once:
该指令后面不需要跟任何表达式(比如之前的v-for后面是由跟表达式的)
该指令表示元素和组件(组件后面才会学习)只渲染一次,不会随着数据的改变而改变,性能优化。
<div id="app"></div>
<template id="my-app">
<h2>{{counter}}</h2>
<div v-once>
<!-- 这两个 h2 标签是 div 的子元素,所以他俩都不会再重新渲染 -->
<h2>{{counter}}</h2>
<h2>{{message}}</h2>
</div>
<button @click="increment">+1</button>
</template>
<script src="../js/vue.js"></script>
<script>
const App = {
template: '#my-app',
data() {
return {
counter: 100,
message: "abc"
}
},
methods: {
increment() {
this.counter++;
}
}
}
Vue.createApp(App).mount('#app');
</script>
- v-text v-html v-pre 数据填充的三个指令:
1、v-text 填充纯文本
2、v-html 填充HTML片段
如果我们展示的内容 本身 是 html 的,那么 vue 并不会进行 特殊的解析,
如果我们希望解析这个内容,则可以 给他加一个 v-html 指令
3、v-pre 填充原始信息
显示原始信息,跳过编译过程
<div id="app"></div>
<template id="my-app">
<h2 v-text="message"></h2>
<!-- 等价于下面的代码 -->
<h2>{{message}}</h2>
<div>{{msg}}</div>
<div v-html="msg"></div>
<h2 v-pre>{{message}}</h2>
<!-- 这里最后会 输出 {{message}} -->
</template>
<script src="../js/vue.js"></script>
<script>
const App = {
template: '#my-app',
data() {
return {
message: "Hello World",
msg: '<span style="color:red; background: blue;">哈哈哈</span>'
}
}
}
Vue.createApp(App).mount('#app');
</script>
-
v-cloak:
v-cloak指令用法
插值表达式存在的问题:“ 闪动 ”
如何解决此问题:使用 v-cloak 指令
解决此问题的原理:先隐藏,替换好值之后再显示最终的值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
[v-cloak] {
display: none;
}
</style>
</head>
<body>
<div id="app"></div>
<template id="my-app">
<h2 v-cloak>{{message}}</h2>
</template>
<script src="../js/vue.js"></script>
<script>
const App = {
template: '#my-app',
data() {
return {
message: "Hello World"
}
}
}
Vue.createApp(App).mount('#app');
</script>
</body>
</html>
v-bind
-
v-bind控制标签属性
v-bind指令,让普通的标签属性的值为 data中的属性名
v-bind指令简写为冒号动态的绑定一个或者多个属性也是可以的
<!-- vue2 template模板中只能有一个根元素 -->
<!-- vue3 是允许template中有多个根元素 -->
<template id="my-app">
<!-- 1.v-bind的基本使用 -->
<img v-bind:src="imgUrl" alt="">
<a v-bind:href="link">百度一下</a>
<!-- 2.v-bind提供一个语法糖 : -->
<img :src="imgUrl" alt="">
<img src="imgUrl" alt="">
</template>
v-bind动态绑定class(对象)
<div id="app"></div>
<template id="my-app">
<div :class="className">哈哈哈哈</div>
<!-- 对象语法: {'active': boolean} -->
<div :class="{'active': isActive}">呵呵呵呵</div>
<button @click="toggle">切换</button>
<!-- 也可以有多个键值对 -->
<div :class="{active: isActive, title: true}">呵呵呵呵</div>
<!-- 默认的class和动态的class结合 -->
<div class="abc cba" :class="{active: isActive, title: true}">
呵呵呵呵
</div>
<!-- 将对象放到一个单独的属性中 -->
<div class="abc cba" :class="classObj">呵呵呵呵</div>
<!-- 将返回的对象放到一个methods(computed)方法中 -->
<div class="abc cba" :class="getClassObj()">呵呵呵呵</div>
</template>
<script src="../js/vue.js"></script>
<script>
const App = {
template: "#my-app",
data() {
return {
className: "why",
isActive: true,
title: "abc",
classObj: {
active: true,
title: true
},
};
},
methods: {
toggle() {
this.isActive = !this.isActive;
},
getClassObj() {
return {
active: true,
title: true
}
}
},
};
Vue.createApp(App).mount("#app");
</script>
v-bind动态绑定class(数组)
<div id="app"></div>
<template id="my-app">
<div :class="['abc', title]">哈哈哈哈</div>
<div :class="['abc', title, isActive ? 'active': '']">哈哈哈哈</div>
<div :class="['abc', title, {active: isActive}]">哈哈哈哈</div>
</template>
<script src="../js/vue.js"></script>
<script>
const App = {
template: '#my-app',
data() {
return {
message: "Hello World",
title: "cba",
isActive: true
}
}
}
Vue.createApp(App).mount('#app');
</script>
v-bind动态绑定style(对象)
<div id="app"></div>
<template id="my-app">
<!-- :style="{cssPropertyName: cssPropertyValue}" -->
<div :style="{color: finalColor, 'font-size': '30px'}">哈哈哈哈</div>
<div :style="{color: finalColor, fontSize: '30px'}">哈哈哈哈</div>
<div :style="{color: finalColor, fontSize: finalFontSize + 'px'}">哈哈哈哈</div>
<!-- 绑定一个data中的属性值, 并且是一个对象 -->
<div :style="finalStyleObj">呵呵呵呵</div>
<!-- 调用一个方法 -->
<div :style="getFinalStyleObj()">呵呵呵呵</div>
</template>
<script src="../js/vue.js"></script>
<script>
const App = {
template: '#my-app',
data() {
return {
message: "Hello World",
finalColor: 'red',
finalFontSize: 50,
finalStyleObj: {
'font-size': '50px',
fontWeight: 700,
backgroundColor: 'red'
}
}
},
methods: {
getFinalStyleObj() {
return {
'font-size': '50px',
fontWeight: 700,
backgroundColor: 'red'
}
}
}
}
Vue.createApp(App).mount('#app');
</script>
v-bind动态绑定style(数组)
<div id="app"></div>
<template id="my-app">
<div :style="[style1Obj, style2Obj]">哈哈哈</div>
<img :src="" alt="">
<a :href=""></a>
<div :class></div>
</template>
<script src="../js/vue.js"></script>
<script>
const App = {
template: '#my-app',
data() {
return {
message: "Hello World",
style1Obj: {
color: 'red',
fontSize: '30px'
},
style2Obj: {
textDecoration: "underline"
}
}
}
}
Vue.createApp(App).mount('#app');
</script>
v-bind动态绑定属性名称
<div id="app"></div>
<template id="my-app">
<div :[name]="value">哈哈哈</div>
</template>
<script src="../js/vue.js"></script>
<script>
const App = {
template: '#my-app',
data() {
return {
name: "cba",
value: "kobe"
}
}
}
Vue.createApp(App).mount('#app');
</script>
v-bind属性直接绑定一个对象
<div id="app"></div>
<template id="my-app">
<div v-bind="info">哈哈哈哈</div>
<div :="info">哈哈哈哈</div>
</template>
<script src="../js/vue.js"></script>
<script>
const App = {
template: '#my-app',
data() {
return {
info: {
name: "why",
age: 18,
height: 1.88
}
}
}
}
Vue.createApp(App).mount('#app');
</script>
事件绑定v-on
v-on:事件名=“事件函数名或者处理程序”
修饰符
.stop - 调用 event.stopPropagation()。
.prevent - 调用 event.preventDefault()。
.capture - 添加事件侦听器时使用 capture 模式。
.self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
.{keyAlias} - 仅当事件是从特定键触发时才触发回调。
.once - 只触发一次回调。
.left - 只当点击鼠标左键时触发。
.right - 只当点击鼠标右键时触发。
.middle - 只当点击鼠标中键时触发。
.passive - { passive: true } 模式添加侦听器
基本使用
<style>
.area {
width: 200px;
height: 200px;
background: red;
}
</style>
</head>
<body>
<div id="app"></div>
<template id="my-app">
<!-- 完整写法: v-on:监听的事件="methods中方法" -->
<button v-on:click="btn1Click">按钮1</button>
<div class="area" v-on:mousemove="mouseMove">div</div>
<!-- 语法糖 -->
<button @click="btn1Click">按钮1</button>
<!-- 绑定一个表达式: inline statement -->
<button @click="counter++">{{counter}}</button>
<!-- 绑定一个对象 -->
<div class="area" v-on="{click: btn1Click, mousemove: mouseMove}"></div>
<div class="area" @="{click: btn1Click, mousemove: mouseMove}"></div>
</template>
<script src="../js/vue.js"></script>
<script>
const App = {
template: '#my-app',
data() {
return {
message: "Hello World",
counter: 100
}
},
methods: {
btn1Click() {
console.log("按钮1发生了点击");
},
mouseMove() {
console.log("鼠标移动");
}
}
}
Vue.createApp(App).mount('#app');
</script>
参数传递
<template id="my-app">
<!-- 默认传入event对象, 可以在方法中获取 -->
<button @click="btn1Click">按钮1</button>
<!-- $event可以获取到事件发生时的事件对象 -->
<button @click="btn2Click($event, 'coderwhy', 18)">按钮2</button>
</template>
<script src="../js/vue.js"></script>
<script>
const App = {
template: '#my-app',
data() {
return {
message: "Hello World"
}
},
methods: {
btn1Click(event) {
console.log(event);
},
btn2Click(event, name, age) {
console.log(name, age, event);
}
}
}
Vue.createApp(App).mount('#app');
</script>
事件修饰符
<template id="my-app">
<div @click="divClick">
<button @click.stop="btnClick">按钮</button>
</div>
<input type="text" @keyup.enter="enterKeyup">
</template>
<script src="../js/vue.js"></script>
<script>
const App = {
template: '#my-app',
data() {
return {
message: "Hello World"
}
},
methods: {
divClick() {
console.log("divClick");
},
btnClick() {
console.log('btnClick');
},
enterKeyup(event) {
console.log("keyup", event.target.value);
}
}
}
Vue.createApp(App).mount('#app');
</script>