vue基础知识
什么是vue?
单页面应用框架,数据驱动视图,数据实现双向绑定
vue的数据流是什么?
单向数据流
vue语法
{{}} 小胡子语法(mustache语法):将vue实例上的数据绑定在dom上
作用:
1.解析变量
2.js运算
3.使用js对象的方法
vue的指令有哪些?
指令:带有v-开头的特殊属性,主要用来操作DOM
1 v-text:v-text = "值",值需要在数据中声明,作用类似于{{}}语法,给DOM元素添加一些字符
2 v-html:v-html = "值",值需要在数据中声明
* 区别: v-text:可以解析文本
v-html:可以解析html元素
3 v-show:v-show="表达式",根据表达式的真假值控制元素的显示与隐藏
v-show="false"时会给元素添加一个display:none的属性
4 v-if:v-if="表达式",根据表达式的真假值控制元素是否存在
v-if="false"时,dom元素不存在
重点:v-if与v-show的区别:
v-show 控制元素的display样式
v-if 控制DOM元素的删除与添加
频繁切换使用v-show,使用v-if浪费性能
5 v-else: 不能单独使用,必须跟在v-if或者v-else-if后面
6 v-else-if:不可单独使用,必须放在v-if或者v-else-if后面
js中的if(){}else if(){}else{}
7 v-for:遍历数组或者对象,
问题:v-for 中除了 in 还有那种写法?of
遍历数组:v-for="(item,index) in arr" 前面是两个变量,分别是属性值,下标
遍历对象:v-for="(value,key,index) in obj" 前面是三个变量,分别是属性值,属性名,下标
8 v-on:绑定事件
语法:v-on:不带on的事件名称(click) = "函数名"
简写:@事件名称="函数名"
函数名一定要在methods里面声明,methods是挂载方法的
如果需要传参 v-on:不带on的事件名称(click) = 函数名(param1,param2.....),通过函数接收
9 v-model:v-model="自定义名"
只能给表单元素绑定指令,不能绑定普通元素,
表单元素会忽略value属性,把vue实例上的数据作为数据的初始来源
10.v-slot:插槽,配合 template 使用
11 v-bind:给元素或者组件动态绑定一个或多个属性
语法:v-bind:属性名=值
简写::属性名=值
当前this:在实例中this指向当前vm实例,在组件中this指向当前组件
v-bind:class
1.绑定字符串:<div :class="isClass"></div>
2.绑定对象:<div :class="{red: isRed}"></div>
red为key,key是类名,isRed是布尔值,这个布尔值决定是否绑定key
3.绑定数组:<div :class="[classA,classB]"></div>
数组中的每一项都是类名,需要在data中初始化
4.数组与对象的组合:<div :class="[classA,{classB:isB,classC:isC}]">
v-bind:style:动态绑定样式
:style="{width:sWidth+'px',height:sHeight+'px',background:sColor}"
另一种方式,自定义:
<div v-bind="{id:'aaa','other-attr':'otherProp'}">
v-bind:title 鼠标悬停几秒钟查看此处动态绑定的提示信息
修饰符:写在事件名称后面 用.表示
事件修饰符:
@click.prevent: 阻止默认事件
@click.stop:取消冒泡
@click.once:只触发一次回调
@click.left :点击鼠标左键时触发
@click.right :点击鼠标右键时触发
@click.middle:点击鼠标中键时
键盘修饰符:
@keyup.13 == @keyup.enter
@keyup.esc
自定义指令
自定义指令定义方法:
全局定义:Vue.directive("名字",{关于对象的钩子和逻辑})
钩子函数:
1.bind:在绑定元素初始渲染时执行
2.inserted:在DOM元素插入到页面时执行
3.update:在更新时候执行的函数
钩子的参数:
1.el:绑定的DOM元素
2.binding
Vue.directive("color",{ inserted(el){ el.style.color = "red"; } }) 自定义指令使input自动聚焦 Vue.directive('focus',{ inserted(el){ el.focus() } })
局部定义:在配置对象中写directives{"名字":{关于对象的钩子和逻辑}}
var vm = new Vue({ el:"#app", directives:{
'focus':{
inserted(el,binding){
// 从binding下面获取是否存在修饰符
var sColor = binding.modifiers.color
if(sColor){
var value = binding.value
console.log(value)
el.style.boxShadow = `1px 1px 1px 1px ${value}`
}
el.focus()
}
},
}
})
注意:名字定义时不加v-,在使用时加上v-
组件缓存
keep-alive 缓存组件运行状态
keep-alive没有任何属性,缓存组件所有包含的组件状态,
include:用来匹配要缓存的组件,
exclude:排除不要缓存的组件
max:指定缓存组件的个数
动态加载组件
使用内置组件component,用is属性动态加载组件
```html <template> <component is="home" /> </template> ``` ```js import home from"./home" export default = { components:{ home } } ```
vue的计算属性
computed,与el,data,methods同级
属性名--函数名
属性值--函数的返回值
依赖普通属性(data中的数据),计算属性也会被挂载到当前实例上,也可使用{{}}
函数与计算属性的区别:
用函数去实现每次得到返回结果都会执行函数,计算属性只会执行一次,然后把结果存在缓存中,以后使用会从缓存中直接获取,不再执行逻辑,提高性能
computed:计算属性 与 watch:监听 区别
- computed:计算属性有缓存,所以监听的数据发生改变时,会对比缓存值,若新值与旧值一致,则不会触发更新
- watch:监听无缓存,只要被监听的数据发生了变化就会被执行
- computed 监听一个数据还要返回一个数据,但是 watch 只是监听
监听属性
监听属性:watch 监听数据的变化
msg(newVal,oldVal){}
监听的数据写成函数,新值与旧值作为函数的参数
对象在每一个属性都有一个setter/getter
分别演化成:
setter:set(){}:set函数在属性值发生变化之后执行 set(){ return value } getter:get(){}:get函数在获取属性的时候执行
深度监听
vue在运行时,对于非基本数据类型只会监听引用,添加deep:true,会给每一层数据绑定一个监听器,如果有一个值变化都会做出响应
watch:{ msg(newVal,oldVal){ console.log("我是新值"+newVal) console.log("我是旧值"+oldVal) }, "obj.a.b":{ // 处理函数handler(固定) handler:function(newVal,oldVal){ console.log("我是新值"+newVal) console.log("我是旧值"+oldVal) }, deep:true,//深度监听 } }
vue 组件实例组成部分
name:组件名称
data:数据
components:局部注册组件
computed:计算属性
watch:监听
methods:方法的集合
filter:自定义过滤函数
directive:自定义指令
mixins:混入,我们将公共的一些实例上的配置做成一个单独的 mixins 文件,
引入进来后,和我们实例上的配置做一个合并,说白了就是给组件功能的扩展
生命周期
defineProperty
Object.defineProperty(obj,attr,desc):该方法接收三个参数
参数:
obj:要修改或定义属性的对象
attr:要修改或者新增的属性名
desc:描述符(对象){}
(1)、属性描述符:
value:描述属性值
writable:描述属性是否可以被修改
布尔值,若为true表示可修改,为false表示不可修改
enumerable:描述属性是否可以被枚举(for in 遍历)
布尔值 true:可以被枚举 false:不可以被枚举
configurable:描述属性是否可以被删除
布尔值:true:可以被删除 false:不可以被删除
(2)、存取器描述符 setter和getter
get(){
获取属性时执行
}
set(){
属性值发生变化时执行
}
注意:存储器描述符不能和value、writable同时使用
挂载元素的方法
1.$el
2.调用实例的方法:$mount("#app")
style的作用域
默认全局,在style上加scoped使css只在当前组件生效
递归组件
一个组件接受父组件传递过来的数据,进行自我调用,必须有结束条件和name属性
MVC与MVVM
MVC:单向
M:Model 模型, 数据层
V:View 用户界面 视图层
C:controller 控制器 大量的逻辑都放在controller里面
MVVM:一种模式或思想,vue框架的思想符合mvvm模式,双向
M:Model 模型, 数据层
V:View 用户界面 视图层
VM:实例化的vue对象
vm:处理数据,不关心处理数据的过程,只关心数据的变化
生命周期
生命周期钩子:vue实例从创建、运行到销毁,伴随着一些事件,这些事件叫生命周期钩子,也叫生命周期函数
8个周期:
beforeCreate:在实例创建之前运行,el还没有挂载到DOM,实例上的数据、方法还未初始化
$el:实例上的属性,挂载元素
$data:实例上的属性,数据属性
$mount():实例上的方法,把实例挂载到DOM上 多
created:实例创建完成,数据和方法已经被初始化,vue实例还未挂载到DOM上($el未找到) 多
beforeMount:实例挂载到DOM之前执行的函数,此时的DOM是虚拟的还不能使用
mounted:实例挂载DOM完成,DOM已经渲染完成,可以对DOM进行操作
做Ajax请求
beforeUpdate:数据更新前执行的函数
updated:数据更新完成执行的函数,更新数据时执行
beforeDestroy:实例销毁之前执行的钩子,清除定时器和轮询接口
destroyed:销毁成功以后执行的钩子
数据双向绑定(核心底层封装)
2.x原理:Object.defineProperty
3.x原理:es6的proxy封装
拦截对象的属性,使用Object.defineProperty把每个属性转成setter和getter的形式,当属性值变化时执行setter,通知vue把数据重新渲染到页面 var obj = { str:"hello", num:11111, a:{ b:45 } } function render(){ console.log("数据变化了,该重新渲染到页面了") } // 定义一个观察者 function observer(obj){ // 容错处理 if(typeof obj !== 'object' || obj == null){ return obj } // 遍历对象,把对象每个属性添加一个监听 for(let attr in obj){ // 把每个属性转成getter和setter // obj:监听对象 attr:监听属性 obj[attr]:监听的值
defineReactive(obj,attr,obj[attr]) } } observer(obj) function defineReactive(data,key,value){ Object.defineProperty(data,key,{ get(){ // 获取属性时执行 return value }, set(newVal,oldVal){ // 监听到属性值发生变化时执行 render() value = newVal } }) }
组件
一个组件模板只能有一个根元素
钩子函数与template同级
1.什么是组件?
页面中可以复用的局部功能界面
2.组件化开发的好处
2.1.协同开发
2.2.可以复用
2.3.便于维护
3.组件的组成部分
html结构 css样式 数据 逻辑
4.创建组件
a.全局注册
Vue.component("组件名称",{关于组件的配置})
组件名称命名:
1.pascal命名法:MyComponentName
2.烤串命名法:a-b-c 必须小写
Vue.component("my-component", {
//定义组件模板-
template: `
<div>
<h3>我是组件</h3>
<button @click="show">组件按钮</button>
<custome-component></custome-component>
</div>
`
})
b.局部注册,在components配置项里面写
components:{ "组件名称":{ 组件配置 }, components:{} } components: {
'custome-component': {
template: `
<div>
<h3>我是局部注册的组件</h3>
<child-component></child-component>
</div>
`,
data() {
return {
msg: "我是局部注册数据"
}
},
components: {
"child-component": {
template:
`<div>孙子组件</div>`
}
}
} }
5.使用组件
把组件名称当作一个自定义的元素放在想放的位置
6.关于组件中data的问题
组件中的data必须是一个函数,不能写成{}的形式,
组件中的数据可以复用,都要返回自己独立的拷贝,当修改一个组件的数据,其他组件数据不会被修改,
7.组件的this指向当前组件,在组件上声明的方法和属性都挂载到当前组件上
内置组件
<template>
<div>
<h3>内置组件</h3>
<p>1.component</p>
<!-- component组件必须给一个:is属性。这个属性是用来加载组件的 -->
<!-- 动态加载组件 -->
<button @click="name='z'">显示组件1</button>
<button @click="name='x'">显示组件2</button>
<button @click="name='y'">显示组件3</button>
<p>2.keep-alive 缓存组件运行状态</p>
<!-- keep-alive没有任何属性,缓存组件所有包含的组件状态,
include:用来匹配要缓存的组件,
exclude:排除不要缓存的组件
max:指定缓存组件的个数
-->
<keep-alive exclude="z">
<component :is="name" />
</keep-alive>
</div>
</template>
<script>
import Com1 from '../components/neizhi/com1'
import Com2 from '../components/neizhi/com2'
import Com3 from '../components/neizhi/com3'
export default {
components: {
z: Com1,
x: Com2,
y: Com3
},
data() {
return {
name: 'z'
}
}
}
</script>
通信方法
1、父组件向子组件传递数据
父组件使用v-bind动态绑定数据
绑定语法:v-bind:自定义属性名 = value(要传递给子组件的数据)
子组件接收:子组件通过props接收父组件传递过来的数据
接收方式:
1.props:['自定义属性名'] 该值是父组件传递过来的数据
2.props:{
key(要接收的数据):{ type:String 定义接收的数据类型,type:[String,Number] 验证, 防止他人修改 default:value 定义默认值,如果父组件传值则使用父组件的值默认值不生效, 如果没传可自己设置默认值,如果默认值不是基本数据类型要写出函数返回的形式 default:function(){ return { msg:100 } } required:布尔值 true:必传,default失效 false:不必传 } }
2、子组件向父组件传递数据
子组件使用$emit()向上广播事件
$emit('自定义事件名'(必填),value(可选))
父组件监听自定义事件,使用v-on:"自定义事件名"="函数名"
<div id="app"> <parent-com :num = "num" @change-num='receive'></parent-com>
</div> var vm = new Vue({
el:"#app",
data:{
num:1
},
methods:{
receive(newNum){
this.num = newNum
}
},
components:{
'parent-com':{
template:
`<div>
<p>我是父级组件:{{num}}</p>
<button @click="change">修改父级数据</button>
</div>`,
// props:['num'],
props:{
num:{
type:Number,
default:2
}
},
methods:{
change(){
this.$emit('change-num',200)
}
}
}
}
})
3、$attrs 批量向下传递数据:
$attrs:是组件固有的,用来描述该组件身上的所有属性集合的对象
向下批量传递,使用v-bind="$attrs",在父级里给子级标签设置
$listeners 批量向下传递方法
$listeners 是组件上的方法,用来保存组件身上的方法
继续向下传递 v-on="$listeners"
4、Provide和Inject
对象类型
依赖注入,强制注入,可以扩展更深层的数据传递,在任何后代组件中都可以使用
优点:跨组件获取数据
使用provide或inject实例选项,provide:设置 inject:接收
provied:{属性名:属性值}
inject:['属性名']
注入过来的数据成为组件上的属性
5、ref的使用
ref:string类型,主要用来给元素或者子组件注册引用信息,引用信息会注册在父组件的$refs对象上
$refs:类型是Object对象,持有所有已经注册过ref的子组件
如果在普通DOM元素上使用,那么引用的注册信息指向DOM元素
如果在组件上使用,那么引用指向的是组件实例对象,那么可以获取到组件上的属性或方法
6、EventBus
原理:创建一个vue实例,调用实例上的方法
方法:
发送:$emit("自定义事件名称",value)
监听:$on("自定义事件名称",function(value){
函数的参数是发送时候的值
})
能实现各组件之间的通信(父子,兄弟,跨组件)
实现方法:在main.js中创建全新的vue实例
Vue.prototype.$bus=new Vue()
7、$parent $children
$parent: 当前组件的直接父组件(无直接父组件则指向本身)
$children:当前组件的直接子组件,子组件会被当作数组展示,若无子组件就是空数组
在mounted中直接打印this.$parent
浙公网安备 33010602011771号