vue是一套用于构建用户界面的渐进式框架
。
Vue 被设计为可以自底向上
逐层应用。
Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。
Vue 也完全能够为复杂的单页应用提供驱动。
vue特性
数据驱动视图
在使用了vue 的页面中,vue 会监听数据的变化,从而自动重新渲染页面的结构。
**好处:**当页面数据发生变化时,页面会自动进行渲染
**注意:**数据驱动视图是单向的数据绑定
双向数据绑定
双向数据绑定可以辅助开发者在不操作DOM 的前提下,自动把用户填写的内容同步到数据源中。
vue的优点
一、vue作为一款轻量级JavaScript框架,门槛低,上手快,简单易学。
二、vue可以进行组件化开发,数据与结构相分离,使代码量减少,从而提升开发效率,易于理解 三、vue最突出的优势在于对数据进行双向绑定,使用虚拟DOM
四、相较于传统页面通过超链接实现页面跳转,vue会使用路由跳转不会刷新页面
五、vue是单页面应用,页面局部刷新,不用每次跳转都请求数据,加快了访问速度,提升了用户体验
六、响应式数据操作。
jQuery和vue的区别
vue和jQuery都是前端的js框架,jQuery是使用选择器进行选取DOM对象,对DOM进行各种操作,比原生JS更加方便选取和操作DOM,数据和界面是在一起的;
vue则将数据和界面完全分离,对数据进行操作时不用获取相应的DOM对象,通过viewmodel将view和model进行双向数据绑定(MVVM)
MVVM
是vue 实现数据驱动视图
和双向数据绑定
的核心原理。
MVVM是一种基于前端开发的架构模式。
核心是提供对View 和 Model 的双向数据绑定。
MVVM包括view视图层
、model数据层
、viewmodel层
。
Model
表示当前页面渲染时所依赖的数据源
。
View
表示当前页面所渲染的DOM 结构
。
ViewModel
表示vue 的实例
,它是MVVM 的核心。
各部分通信都是双向的。
MVVM工作原理
ViewModel层,就是View和Model层的粘合剂,作为MVVM 的核心,是它把当前页面的数据源(Model)和页面的结构(View)连接在了一起。
当数据源发生变化
时,会被ViewModel 监听到,VM 会根据最新的数据源自动更新页面的结构
当表单元素的值发生变化
时,也会被VM 监听到,VM 会把变化过后最新的值自动同步到Model 数据源
中
● 之间的通信是双向的。
● View 与 Model 不发生联系,都通过 vm 传递。
● 采用双向数据绑定
组件化,就是把页面拆分成多个组件,每个组件依赖的 CSS、JS、模板、图片等资源放在一起开发和维护。
组件化允许我们使用小型、独立和可复用
的组件构建大型应用。
组件是资源独立的,所以组件在系统内部可复用
,组件和组件之间可以嵌套
,如果项目比较复杂,可以极大简化代码量
,并且对后期的需求变更和维护也更加友好。
①导入vue.js 的script 脚本文件
②在页面中声明一个将要被vue 所控制的DOM 区域
③创建vm 实例对象(vue 实例对象)
//导入vue.js 的script 脚本文件
<script src="https://unpkg.com/vue@next"></script>
// 在页面声明一个要被vue控制的DOM区域
<div id="app"></div>
<script>
// 创建vm实例对象
const vm =new Vue({
//指定当前vm实例要控制页面的哪个区域
el:'#app',
// 指定model数据源
data:{
name:'zhangsan',
}
})
</script>
自己去搭建一个vue项目:
初始化项目
npm init
安装vue
#最新稳定版;
$ npm install -S vue@next
#安装编译工具
$ npm install -D @vue/compiler-sfc
创建src文件夹
创建入口文件src/main.js
import { createApp } from ‘vue’ //引入创建实例的方法
import App from ‘./App.vue’ //引入根组件
createApp(App).mount(‘#app’) //创建一个实例并挂载
创建根组件src/App.vue
安装cli-server
#npm i -D @vue/cli-service
配置package.json
“scripts”: {
“serve”: “vue-cli-service serve”,
},
启动项目
npm run serve
export default {
data() {
return{
name:"zhangsan"
}
},
}
组件是一个可复用的实例
,当你引用一个组件的时候,组件里的data是一个普通的对象,所有用到这个组件的都引用的是同一个data
,就会造成数据污染
。
将data封装成函数
后,在实例化组件的时候,我们只是调用了data函数生成的数据副本
,避免了数据污染
,保证了每个组件实例上data数据的独立性。
vue3.0 AST (抽象语法树)对象根节点其实是一个虚拟节点,它并不会映射到一个具体节点,另外它还包含了其他的一些属性,这些属性在后续的 AST 转换的过程中会赋值,并在生成代码阶段用到。
在3版本中,我们可以放置多个根节点
,而在2版本中必须有且只有一个根节点
。
vue每个组件都是独立的,每个组件都有一个属于它的生命周期,从一个组件创建
、数据初始化
、挂载
、更新
、销毁
,这就是一个组件所谓的生命周期
。
每个组件在被创建时都要经历一系列的初始化过程,在这个过程中会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。
vue3新增了调试用的钩子函数(他们会检测是谁影响的vue实例的变化 ):
renderTracked 状态跟踪
只要页面有update
的情况,就会跟踪,然后生成一个event对象
,我们通过event对象来查找程序的问题所在。(监测页面的变化)
renderTriggered 目标跟踪
它不会跟踪每一个值,而是给你变化值
的信息,并且新值和旧值都会给你明确的展示出来。(监测页面中具体目标的变化)
指令
(Directives)是vue 为开发者提供的模板语法
,用于辅助开发者渲染页面的基本结构
。
vue 中的指令按照不同的用途可以分为如下6 大类:
①内容渲染
指令
②属性绑定
指令
③事件绑定
指令
④双向绑定
指令
⑤条件渲染
指令
⑥列表渲染
指令
内容渲染指令用来辅助开发者渲染DOM 元素的文本内容
数据绑定最常见的形式就是使用双大括号的文本插值 {{ }}
Message:{{msg}}
双大括号会将数据解释为普通文本,而非 HTML 代码。
为了输出真正的 HTML,需要使用v-html
指令
{{html_str}} //普通文本 今天天气很好,小没哭了
//会生成HTML结构
Mustache {{ }} 语法不能在 HTML attribute 中使用,
可以使用v-bind:
指令,v-bind 可以省略为 :
如果绑定的值是 null
或 undefined
或false
,那么该 attribute 将不会被包含在渲染的元素上。
对于布尔 attribute
(它们只要存在就意味着值为 true),它就会存在。
{{ name }}
{{ arr }}
{{ obj }}
{{name}}
message
message
{{ name.split("").reverse().join("") }}
{{ obj.age > 18 ? "成年" : "未成年" }}
v-if 指令用于条件性地渲染
一块内容。这块内容只会在指令的表达式返回 truthy 值的时候被渲染。
v-show指令也是用于条件性展示元素
的选项(控制块的显示与隐藏);
v-show 不支持 元素,也不支持 v-else
用 v-for 指令基于一个数组来渲染一个列表
;
v-for 指令需要使用item in items
形式的特殊语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名;
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,需要为每项提供一个唯一 key attribute;
在 < template> 中使用 v-for: (在需要使用v-for语句的标签外部嵌套template标签,将v-for写在template标签内)
< template> 主要的作用是:在模板中我们不希望把复杂的逻辑写在标签上时,可以在外层套用< template>,可以将逻辑写在< templdate>标签上。
学号
姓名
性别
年龄
班级
//
{{ v.id }}
{{ v.name }}
男
女
{{ v.age }}
{{ v.class }}
当v-for 与 v-if 处于同一节点,v-for 的优先级比 v-if 更高,这意味着 v-if 将没有权限访问 v-for 里的变量
{{v.name}}
操作元素的 class 列表和内联样式是数据绑定的一个常见需求。
因为它们都是 attribute,所以可以用 v-bind 处理它们:只需要通过表达式计算出字符串结果即可。
表达式结果的类型除了字符串之外,还可以是对象或数组。
class 对象/数组语法
style 对象/数组语法
今天天气很好,小没哭了
今天天气很好,小没哭了
今天天气很好
今天天气真好
一种是冷启动
,一种是热启动
。
冷启动
指的是用户首次打开或小程序被微信主动销毁后再次打开的情况,此时小程序需要重新加载启动。
假如用户已经打开过某小程序,然后在一定时间内(五分钟)再次打开该小程序,此时无需重新启动
,只需将后台态的小程序切换到前台,这个过程就是热启动
;
使用 v-on :指令
(通常缩写为 @ 符号
) 来监听 DOM 事件
,并在触发事件时执行一些 JavaScript。
用法为 v-on:click=“methodName(方法名)” 或使用快捷方式 @click=“methodName”
当代码只有一行时,我们可以直接把代码写在v-on中
许多事件处理逻辑会更为复杂, v-on 还可以接收一个需要调用的方法名称
。
< div id="a1" @click="fn1">
可以在内联 JavaScript 语句中调用方法提供参数
在内联语句处理器中访问原始的 DOM 事件,用特殊变量$event
把它传入方法,$event
是事件的默认内置 事件对象
可以通过$event 对触发事件的元素进行dom操作
c(e){
e.target,style.background='red'
}
事件处理程序中可以有多个方法
,这些方法由逗号运算符分隔:
多个方法之间用逗号隔开,且每个方法名后都必须有小括号
<template>
<div id="header">
<button v-on:click='hahaha'>哈哈哈</button>
<button @click="add(1,2)">add</button>
<button @click="num++">添加{{num}}</button>
<button @click="c(1,$event)">删除</button>
<button @click="one($event),two($event)">两个方法</button>
</div>
</template>
<script>
export default {
data() {
return {
num:0
};
},
methods: {
hahaha(){
console.log('hahaha');
},
add(a,b) {
console.log(a+b);
},
c(a,$event){
console.log($event);
},
one($event){
console.log($event);
},
two($event){
console.log($event);
},
}
}
</script>
在事件处理程序中调用 event.preventDefault() (取消事件的默认行为,比如链接跳转,表单提交等)或 event.stopPropagation() (阻止事件冒泡) 是非常常见的需求。
方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。
Vue.js 为 v-on 提供了事件修饰符。
修饰符是由点开头的指令后缀来表示的。
.stop 阻止事件传播
触发子元素点击事件时会产生冒泡,触发子元素之后也会触发父元素
.prevent 阻止事件默认行为
表单默认提交到1.php中,阻止默认行为,则不会提交
.capture 父级事件优先处理
点击子元素冒泡,正常情况下先触发子元素再触发父元素,父级优先处理则先触发父元素后触发子元素
.self 不由子元素触发
使父元素不能被子元素冒泡触发
.once 事件只触发一次
只能触发一次,触发一次之后不能再触发
.passive 会执行默认方法。
每次事件产生,浏览器都会去查询一下是否有preventDefault阻止该次事件的默认动作。我们加上passive就是为了告诉浏览器,不用查询了,我们没用preventDefault阻止默认动作。能够提升移动端的性能。
<template>
<div id="header">
<!-- <div id="a1" @click.capture="fn1"> -->
<!-- 优先触发父元素 -->
<!-- <div id="a1" @click.self="fn1"> -->
<!-- 只能自己触发 -->
<div id="a1" @click.once="fn1">
<!-- 只能触发一次 -->
<div id="a2" @click.stop="fn2"></div>
<!-- .stop阻止事件传播 -->
</div>
<form action="login.php" @submit.prevent="onsubmit">
<!-- 事件默认要提交到login.php中,.prevent阻止事件默认行为 -->
<input type="submit" value="登录">
</form>
</div>
</template>
<script>
export default {
data() {
return {
num:0
};
},
methods: {
fn1(){
console.log('f1');
},
fn2(){
console.log('f2');
},
onsubmit(){
console.log('提交');
}
}
}
</script>
<style >
#a1{
width: 200px;
height: 200px;
background-color: red;
}
#a2{
width: 100px;
height: 100px;
background-color: blue;
}
</style>
.enter
.tab
.delete (捕获“删除”和“退格”键)
.esc
.space
.up
.down
.left
.right
.ctrl
.alt
.shift
.meta
.exact 修饰符允许你控制由精确的系统修饰符组合触发的事件。
.left
.right
.middle
用v-model
指令在表单 < input>、< textarea> 及 < select> 元素上创建双向数据绑定(表单值与属性的双向绑定,即表单元素中更改了值会自动的更新属性中的值,属性中的值更新了会自动更新表单中的值)。
它会根据控件类型自动选取正确的方法来更新元素。
v-model 负责监听用户的输入事件来更新数据,并在某种极端场景下进行一些特殊处理。
注:
v-model 会忽略所有表单元素的 value、checked、selected attribute 的初始值而总是将当前活动实例的数据作为数据来源。
应该通过 JavaScript 在组件的 data 选项中声明初始值。
v-model 在内部为不同的输入元素使用不同的 property 并抛出不同的事件:
● text 和 textarea 元素使用 value property 和 input 事件;
● checkbox 和 radio 使用 checked property 和 change 事件;
● select 字段将 value 作为 prop 并将 change 作为事件。
文本 (Text)
多行文本框(textarea)
复选框(checkbox)
单选框(radio)
选择框(select)
多选选择框:
表单示例
<template>
<div class="home">
<!-- 文本 -->
<!-- 添加.lazy修饰符,转换为change事件 输入框内发生改变就会更新 -->
<div>用户名:<input type="text" v-model.lazy="form_data.username"></div> {{form_data.username}}
<div>密码:<input type="password" v-model.trim="form_data.password"></div>
<!-- input输入框类型为text,输入的数据为数值类型时,展示为字符串类型,.number使用户输入值转为数值类型 -->
<div>年龄:<input type="text" v-model.number="form_data.age"></div>
<!-- 多行文本框 -->
<div>简介:<textarea v-model="form_data.text"></textarea></div>
<!-- 单个复选框 会自动将值转换为true或false,可以通过true-value和false-value改变复选框的值-->
<div>VIP: <input type="checkbox" v-model="form_data.vip" true-value="yes" false-value="no"></div>
<!-- 多个复选框 每个v-model的值相同,值以数组的形式接收, -->
<div>爱好:
<input type="checkbox" v-model="form_data.hobby" value="吃饭"/>
<input type="checkbox" v-model="form_data.hobby" value="睡觉"/>
<input type="checkbox" v-model="form_data.hobby" value="打豆豆"/>
</div>
<!-- 单选框 v-model的值需要相同,默认选中时,将属性值设为值某个value的值 -->
<div>性别:
<input type="radio" v-model="form_data.sex" value="男"/>
<input type="radio" v-model="form_data.sex" value="女"/>
</div>
<!-- 单选选择框 指定默认选中值时 将属性值设置为某个value值 -->
<div>籍贯:
<select v-model="form_data.jg">
<!-- 设置默认选项 增强用户体验 设置disabled属性 使用户不能选择该选项 防止用户误选-->
<option value="" disabled>请选择籍贯</option>
<option value="a" >西安</option>
<option value="b">天津</option>
<option value="c">北京</option>
<!-- 存在优先级,value存在则优先显示value中的值,value没有写则显示标签里的值 -->
</select>
</div>
//双向数据绑定 在页面上展示整个表单的数据
{{form_data}}
</div>
</template>
<script>
export default {
data(){
return{
form_data:{
hobby:[],
sex:'男', //控件默认选中值
jg:'', //值为空,默认值为第一个选项
}
}
},
name:'Home',
components:{
}
}
</script>
.lazy 你可以添加 lazy 修饰符,从而转为在 change 事件
.number 自动将用户的输入值转为数值类型
.trim 如果要自动过滤用户输入的首尾空白字符
模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。
通常计算属性里都是计算相关的函数
,函数里头可以写大量的逻辑
,最后返回计算出来的值,即我们可以把这些计算的过程写到一个计算属性中去,然后让它动态的计算。
对于任何包含响应式数据的复杂逻辑,都应该使用计算属性。
{{getName}}
{{getSex}}
{{getTime}}
可以通过在表达式中调用方法来达到同样的效果。
可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。
计算属性是基于它们的响应依赖关系缓存
的,计算属性把新的数据缓存下来了。计算属性只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要当其他的依赖数据没有发生改变,多次访问 publishedBookMessage 计算属性会立即返回之前的计算结果(调用的是缓存的数据),而不必再次执行函数,极大的提高了我们程序的性能。
如果写在methods里,数据根本没有缓存的概念,所以每次都会重新计算。
当需要在数据变化时执行异步
或开销较大
的操作时,提供了一个更通用的watch
侦听属性,来响应数据的变化
.
handle:watch中需要具体执行的方法
deep:默认为false,将deep设为true时,进行深度监听,一般用来监听对象中某个属性的变化,用普通监听,只能监听到引用地址的改变
,数组字符串一般不需要进行深度监听。
immediate:默认为false,在进入页面时,第一次绑定值,不会立刻执行监听,只有数据发生改变才会执行handler中的操作,在选项参数中指定 immediate: true
将立即以表达式的当前值触发回调
普通属性的侦听
watch: {
question(newQuestion, oldQuestion) {
}
}
表单对象数据的侦听
//监测对象数据的变化
watch: {
obj:{
handler: function (val) {
console.log(val)//数据对象
},
deep:true//对象内部的属性,需要开启deep
}
}
<template>
<div class="home">
<div>用户名:<input type="text" v-model="form_data.username"></div>
<div>密码:<input type="password" v-model="form_data.password"></div>
{{form_data}}
</div>
</template>
<script>
export default {
data(){
return{
form_data:{},
username:""
}
},
watch:{
username(new_v,old_v){
console.log(new_v,old_v);
}
}, //普通属性侦听
watch:{
form_data:{
handler: function(v){
console.log(v);
}, //表单对象数据侦听
deep:true //深度监听
},
},
}
</script>
相同点
watch和computed都是监听数据
,都是当依赖的数据发生改变
时,被依赖的数据就自动发生改变
。
不同点
多个数据改变一个数据
,一般用于计算一些比较复杂的场景,比如购物车计算价格,就是多对一监听一个数据从而改变多个数据
,通过观察一个数据的变化去改变其他数据,比如搜索框提示列表,就是一对多计算
,watch用于观察
return
缓存性
,当依赖的数据没有发生变化,就会从缓存中取出数据,所以computed的性能比watch要好一点