Vue核心知识
Vue简介
Vue
是一款渐进式JavaScript框架,作用是为了动态构建用户界面,该框架遵循MVVM模式,编码简洁,体积小,运行效率高。
Vue的基本使用
引入Vue
直接引入CDN
<script src="https://unpkg.com/vue@next"></script>
NPM方法
# 最新稳定版
$ npm install vue@next
Vue CLI 脚手架
// 安装脚手架
npm install -g @vue/cli
// 脚手架生成 vue 项目,同时会自动安装依赖
vue create vue-cli-demo
启动项目
$ cd my-project
$ cnpm install
$ cnpm run dev
实例的创建
Vue3中的应用是通过使用createApp函数来创建的,语法格式如下:
const app = createApp({
/*选项*/
})
实例的挂载
一个应用需要被挂载到一个DOM元素中,挂载时使用mount()
举例:以下代码使用mount(‘#hello-vue’)将应用HelloVueApp挂载到<div id="hello-vue"></div>
中。
<div id="hello-vue" class="demo">
{{ message }}//插值语法
</div>
<script>
const HelloVueApp = {
data() {
return {
message: 'Hello Vue!!'
}
}
}
Vue.createApp(HelloVueApp).mount('#hello-vue')
</script>
data属性
组件的data选项是一个函数。Vue会在创建新组件实例的过程中调用此函数。他应该返回一个对象,然后Vue会通过响应性系统将其包裹起来,并以$data的形式存储在组件实例中。
const app = Vue.createApp({
data() {
return { count: 4 }
}
})
//mount 不返回应用本身,它返回的是根组件实例。
const vm = app.mount('#app')
console.log(vm.$data.count) // => 4
console.log(vm.count) // => 4
面试题:vue中的data属性为什么必须是函数?
- JavaScript中的对象是引用类型的数据,当多个实例引用同一个对象时,只要一个实例对这个对象进行操作,其他实例中该对象数据也会发生变化。
- 在Vue中,更多的是想要复用组件,那就需要每个组件都有自己的数据,这样组件之间才不会相互干扰。
- 组件的数据不能写成对象的形式,而是要写成函数的形式。数据以函数返回值的形式定义,这样当每次复用组件的时候,就会返回一个新的data,也就是说每个组件都有自己的私有数据空间,它们各自维护自己的数据,不会干扰其他组件的正常运行。
模板语法
所谓的模板就是动态的Html页面,包含了一些JS语法代码,在Vue中使用插值语法
和指令
(以v-开头的自定义属性标签)
插值语法
语法格式:{{XXX}}
,作用就是向页面输出数据,可以调用对象的方法,例如:
{{XXX.toUpperCase()}}
指令
强制数据绑定 v-bind(:)
下面代码中img标签的src属性不会获取到data中定义的imgSrc属性的值,这个时候就需要使用强制数据绑定。
强制数据绑定,功能是指定变化的属性值,完整写法是:v-bind:src='imgSrc'
,一般采用简洁写法::src='imgSrc'
<body>
<div id="app">
<p>{{msg}}</p>
//可以调用对象的方法
<p>{{msg.toUpperCase()}}</p>
//<img src="imgSrc" alt="">//这样写无法获取到data中定义的imgSrc属性的值
//应该写为
<img :src="imgSrc" alt="">
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const app=createApp({
data: {
msg: 'Hello Word',
}
})
app.mount('#app')
</script>
</body>
绑定事件监听 v-on:click(@click)
绑定事件监听指令的作用就是绑定指定事件名的回调函数,完整写法:v-on:click='xxx'
或者v-on:click='xxx(参数)'
再或者v-on:click.enter='xxx'
,简洁写法就是:@click='xxx'
,使用@
符号;
<body>
<div id="app">
<button v-on:click = 'test1'>test1</button>
<button v-on:click = 'test2(msg)'>test2</button>
<button @click = 'test'>test</button>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const app=createApp({
data: {
msg: 'Hello Word',
imgSrc: 'http://image.luokangyuan.com/1.jpg'
},
methods: {
test1() {
alert(123)
},
test2(content) {
alert(content)
},
test() {
alert(123)
}
}
})
app.mount('#app')
</script>
</body>
事件修饰符
使用方式很简单,在绑定事件后面加上修饰符就可以
.stop
:停止事件冒泡
举例:
<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>
.prevent
:阻止事件的默认事件和默认行为
举例:
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
.keyCode
:keyCode是键盘对应的按键,当键盘弹起时触发事件,也可以直接使用按键名称
举例:
<!-- 按下Alt + C 清除输入框内容 -->
<input @keyup.alt.67="clear" />
capture
:给元素添加一个监听器,当元素发生冒泡时,先触发带有该修饰符的元素。若有多个该修饰符,则由外而内触发。
capture举例:
<div id="content">
<div id="obj1" v-on:click.capture="doc">
obj1
<div id="obj2" v-on:click.capture="doc">
obj2
<div id="obj3" v-on:click="doc">
obj3
<div id="obj4" v-on:click="doc">
obj4
<!--。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。点击obj4的时候,弹出的顺序为:obj1、obj2、obj4、obj3;
由于1,2有修饰符,故而先触发事件,然后就是4本身触发,最后冒泡事件。
-->
</div>
</div>
</div>
</div>
</div>
v-once一次性插值
一次性插值
,数据改变时插值处的内容不会更新
<span v-once>{{msg}}</span>
v-html
使用 v-html 指令用于输出 html 代码
<div id="example1" class="demo">
<p>使用双大括号的文本插值: {{ rawHtml }}</p>
<p>使用 v-html 指令: <span v-html="rawHtml"></span></p>
</div>
<script>
const RenderHtmlApp = {
data() {
return {
rawHtml: '<span style="color: red">这里会显示红色!</span>'
}
}
}
Vue.createApp(RenderHtmlApp).mount('#example1')
</script>
HTML属性中的值应使用v-bind指令
<!-- 完整语法 -->
<a v-bind:href="url"></a>
<!-- 缩写 -->
<a :href="url"></a>
对于布尔属性,常规值为 true 或 false,如果属性值为 null 或 undefined,则该属性不会显示出来。
举例:
<button v-bind:disabled="isButtonDisabled">按钮</button>
以上代码中如果 isButtonDisabled 的值是 null 或 undefined,则 disabled 属性甚至不会被包含在渲染出来的 元素中。
表达式
Vue.js 提供了完全的 JavaScript 表达式支持。
<div id="app">
{{5+5}}<br>
{{ ok ? 'YES' : 'NO' }}<br>
{{ message.split('').reverse().join('') }}
<div v-bind:id="'list-' + id">hello</div>
</div>
<script>
const app = {
data() {
return {
ok: true,
message: 'RUNOOB!!',
id: 1
}
}
}
Vue.createApp(app).mount('#app')
</script>
表达式会在当前活动实例的数据作用域下作为 JavaScript 被解析。有个限制就是,每个绑定都只能包含单个表达式,所以下面的例子都不会生效:
<!-- 这是语句,不是表达式:-->
{{ var a = 1 }}
<!-- 流控制也不会生效,请使用三元表达式 -->
{{ if (ok) { return message } }}
计算属性和监视
计算属性computed
计算属性
在处理一些复杂逻辑是是很有用的
语法模式:{ [key: string]: Function | { get: Function, set: Function } }
举例:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<p>原始字符串: {{ message }}</p>
<p>计算后反转字符串: {{ reversedMessage }}</p>
</div>
<script>
const app = {
data() {
return {
message: 'RUNOOB!!'
}
},
computed: {
// 计算属性的 getter
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('')
}
}
}
Vue.createApp(app).mount('#app')
</script>
使用计算属性实现双向绑定
const app = createApp({
data() {
return { a: 1 }
},
computed: {
// 仅读取
aDouble() {
return this.a * 2
},
// 读取和设置
aPlus: {
// getter 回调函数,当需要读取当前属性值时回调,根据相关的数据计算并返回当前属性的值
get() {
return this.a + 1
},
// setter 回调函数,监视当前属性的变化,当属性值发生改变时回调,更新相关的属性数据
set(v) {
this.a = v - 1
}
}
}
})
const vm = app.mount('#app')
console.log(vm.aPlus) // => 2
vm.aPlus = 3
console.log(vm.a) // => 2
console.log(vm.aDouble) // => 4
computed vs methods
可以使用 methods 来替代 computed,效果上两个都是一样的。
但是
- computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。
- 而使用 methods ,在重新渲染的时候,函数总会重新调用执行。
监视属性watch()
监听属性
,就是监测指定的属性是否发生变化,如果发生了,回调函数自动调用,进行相关操作,如果没发生变化,则监视属性也不会被触发。
语法格式:
{ [key: string]: string | Function | Object | Array}
举例:
watch:{
sum:{
// 深度监视,因为watch默认只是浅层监视
depp:true,
// 在初始化完成之后就触发监听
immediate:true,
// 监视属性的回调
handler(newValue, oldValue){
console.log('求和的值变化了',"变化后的值是"+newValue, '变化前的值是'+oldValue);
}
// 该回调会在任何被侦听的对象的 property 改变时被调用,不论其被嵌套多深
c: {
handler:function(val, oldVal) {
console.log('c changed')
},
deep: true // 深度监视,因为watch默认只是浅层监视 有时候对象的属性发生变化了也需要监听到,则需要将deep设置为true
},
// 侦听单个嵌套 property
'c.d': function (val, oldVal) {
// do something
},
methods VS watch VS computed
class与style绑定
在某些页面中,某些元素的样式是动态发生变化的,class和style绑定就是用来实现改变样式效果的技术,其中class绑定中,表达式可以是字符串,可以是对象,也可以是数组。
v-bind:class
可以简写为 :class
。
v-bind:style
可以简写为style
。
举例:
点击更新按钮样式发生改变
<head>
<meta charset="UTF-8">
<title>class和style绑定</title>
<style>
.aClass{color: red}
.bClass{color: blue}
</style>
</head>
<body>
<div id="app">
<h1>class绑定</h1>
<p :class="a">我是字符串</p>
<p :class="{aClass: isA,bClass: isB}">我是对象</p> <!--class绑定的是对象。当为true才会留下-->
<h1>style绑定</h1>
<p :style="{color: activeColor, fontSize: fontSize+'px'}">我是style强制绑定</p>
<button @click='update'>更新</button>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const app =createApp({
data: {
a: 'aClass',
isA: true,
isB: false ,// 以上是绑定class
activeColor: 'red', // 以下是绑定style
fontSize : 20
},
methods: {
update(){
this.a = 'bClass';
this.isA = false;
this.isB = true;// 以上是绑定class
this.activeColor = 'blue';
this.fontSize = 30;
}
}
})
app.mount('#app')
</script>
</body>
分支结构
在vue中条件渲染使用v-if
、v-else
、v-else-if
和v-show
指令。
举例:
v-if:
这里,v-if指令将根据表达式seen的值(true或false)来决定是否插入p元素。
因为v-if是一个指令,所以必须将他添加到一个元素上。如果是多个元素,可以包裹在元素上,并在上面使用v-if。最终的渲染结果将不包含元素。
<div id="app">
<p v-if="seen">现在你看到我了</p>
</div>
<script>
const app = {
data() {
return {
seen: true /* 改为false,信息就无法显示 */
}
}
}
Vue.createApp(app).mount('#app')
</script>
v-else-if
,v-else
:
<div v-if="type === 'A'">Type A</div>
<div v-else-if="type === 'B'">Type B</div>
<div v-else>Default Type</div>
v-show
:
<body>
<div id="app">
<p v-show = 'ok'>显示失败-v-show</p>
</button>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const app = createApp({
data: {
ok: false
}
})
app.mount('#mount')
</script>
</body>
v-if VS v-show
v-if是不会生成不应该显示的元素,v-show是通过css控制隐藏不应该显示的节点元素。
当需要频繁的切换的时候,使用v-show比较好,当条件不成立时,v-is的所有子节点也不会被解析;
具体区别如下表:
遍历
v-for
指令需要使用item in items
形式的特殊语法,除了遍历数组以外,v-for
还能遍历对象、数字。
v-for迭代数组
<!-- 遍历数组时 -->
<!-- 其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名,可选的第二个参数 index 为当前项的索引 -->
<ul>
<li v-for="(item, index) in items">
{{index}}: {{ item.message }}
</li>
</ul>
v-for迭代整数
<div id="app">
<ul>
<li v-for="n in 10">
{{ n }}
</li>
</ul>
</div>
v-for迭代对象
<!-- 在遍历对象时,会按 Object.keys() 的结果遍历 -->
<!-- 其中 object 是源数据对象,而 value 则是被遍历的对象值,可选的第二个参数 key 为当前值的键名,可选的第三个参数 index 为当前项的索引 -->
<div v-for="(value, key, index) in object">
{{ index }}.{{ key }}: {{ value }}
</div>
key
key的作用
key作为一个DOM节点的标识值,结合Diff算法可以实现节点的服用。
只有当key(或其他导致isSameNode判断为false)发生改变时,才会触发节点的重新渲染。否则Vue将会复用之前的节点,通过改变节点的属性来实现节点的更新。
<div v-for="item in items" v-bind:key="item.id">
使用id值作为key值和使用index值作为key值的区别
== 不推荐使用index作为key,因为这种做法会导致某些节点被错误的原地复用。==
具体描述:
使用index作为key和没写基本上没区别,因为不管数组顺序怎么颠倒,index都是0,1,2......这样排列的,导致Vue会复用错误的旧子节点,做很多额外的工作。而id值是唯一的,不存在这种问题。
v-if和v-for中key的设置
-
在Vue2中,建议在v-if、v-else-if、v-else的分支中使用key;Vue2中标签中不能使用key,若想使用,可以为其每个子节点分别设置key。
-
Vue3中我们不再建议在v-if、v-else-if、v-else的分支中继续使用key,因为没有为条件分支提供key时,也会自动生成唯一的key;Vue3中,key则应该被设置在标签上。
v-for与v-if的优先级
两者作用于同一元素上时,Vue3版本中的v-if总是优先于v-for,Vue2则相反
表单数据绑定v-model
表单的数据绑定使用v-model指令,举例:
<body>
<div id="app">
<form action="/xxx" @submit.prevent="handSubmit">
<span>用户名:</span>
<input type="text" v-model="userName">
<br>
<span>密码:</span>
<input type="password" v-model="pwd">
<br>
<span>性别:</span>
<input type="radio" id="wman" value="女" v-model="sex">
<label for="wman">女</label>
<input type="radio" id="man" value="男" v-model="sex">
<label for="man">男</label>
<br>
<span>爱好:</span>
<input type="checkbox" id="basket" value="basket" v-model="likes">
<label for="basket">篮球</label>
<input type="checkbox" id="footbal" value="foot" v-model="likes">
<label for="footbal">足球</label>
<input type="checkbox" id="pingpang" value="pingpang" v-model="likes">
<label for="pingpang">乒乓球</label>
<br>
<span>城市:</span>
<select name="" id="" v-model="cityId">
<option value="">未选择</option>
<option :value="city.id" v-for="(city,index) in allCitys" :key="index">{{city.name}}</option>
</select>
<br>
<span>个人介绍:</span>
<textarea name="" id="" cols="30" rows="10" v-model="desc"></textarea>
<br>
<input type="submit" value="注册">
</form>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const app = cretaeApp({
data: {
userName: '',
pwd: '',
sex: '男', // 默认选中性别男
likes: ['foot'], // 默认选中foot对应的多选框
allCitys: [{ id: 1, name: "北京" }, { id: 2, name: "成都" }, { id: 3, name: "上海" }, { id: 4, name: "宁波" }],
cityId: '',// 这里默认是空,则匹配未选择,如果默认选中成都,则写2即可
desc: ''
},
methods: {
handSubmit() {
console.log(this.userName, this.pwd, this.sex, this.likes, this.cityId, this.desc)
}
}
})
app.mount('#app')
</script>
</body>
修饰符
相关文章
- 手把手教你从零写一个简单的 VUE
- Vue_(Router路由)-vue-router路由的基本用法
- VUE - vue.runtime.esm.js?6e6d:619 [Vue warn]: Do not use built-in or reserved HTML elements as component i
- [Vue @Component] Define Props on a Vue Class with vue-property-decorator
- [Vue] Get up and running with vue-router
- vue.js3:div上添加右键菜单(vue@3.2.37)
- [Vue @Component] Define Props on a Vue Class with vue-property-decorator
- Vue.js3: 页面打开前实现图片全部预加载(vue@3.2.33)
- Electron使用指南 - [10] 构建 Vue 项目基本结构
- 一个典型的Vue应用的App.vue
- vue-tour快速入门:VUE项目中如何使用vue-tour新手引导指引插件?怎样使用?包含具体实例
- vue 的 render 函数的用法:new Vue({ render: h => h(App), }).$mount(‘#app‘)
- Vue+Element ui上传图片限制图片尺寸
- 关于购物车添加按钮的动画(vue.js)
- Springboot+Vue实现将图片和表单一起提交到后端,同时将图片地址保存到数据库、再次将存储的图片展示到前端vue页面
- vue、vuex、iview、vue-router报错集锦与爬坑记录
- Vue、Vuejs从入门到精通 | vue-router详解
- Vue项目保持用户登录状态(localStorage + vuex 刷新页面后状态依然保持)
- Vue(五)计算属性、过滤器、axios、vue 生命周期
- 前端必备技能知识:JS导出Blob流文件为Excel表格、Vue.js使用Blob的方式实现excel表格的下载(流文件下载)
- Vue组件间通信方式都有哪些?
- Vue中npm run dev 和 npm run serve区别
- Vue学习笔记——vue-router