1)vue简介
vue基于MVVM模式
MVVM(vue没有完全遵循 MVVM 模式)
m model
数据模型,data[数据state]
v view
视图,模板,template
数据绑定?事件绑定?
v-bind(绑定属性) v-on(绑定事件) {{}} 解析
vm viewModel(封装dom)
1)目标
1.基本应用
2.原理及源码解读
2)学习
1.vue直接在html中应用(推荐)
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.9/vue.js"></script>
2.vue在脚手架中应用(官方,第三方)
webpack
3.npm install vue
2)vue实例(根实例,组件实例)
模块化,一切皆模块
一个模块是html/css/js的一个完整功能单元
自定义标签
vue实例(vm)代理了data,methods中变量的访问
vm.状态(data中声明的属性)
vm.方法(methods中声明的方法)
1)根实例
new Vue({
el:"",
data:{
},
methods:{
foo(){
this
}
},
created(){
this
},
生命周期钩子函数,监听器,过滤器等等...
})
根组件(模块)
let options={
data:{},
methods:{
},
created(){
this(都指向当前vue实例)
}
}
let vm=new Vue(options)
2)组件实例
.vue文件 vue组件
Vue.component('',{
data:function(){
return {}
},
created(){
this
}
})
组件(模块)
let options={
data:function(){
return {}
},
methods:{
},
created(){
}
}
Vue.component('my-info',options)
<my-info/>
<my-info/>
<my-info/>
1.data:
在根组件中一定为对象{},
在普通组件中为函数function(){},并且这个函数返回一个对象
2.el/template
模板:
el:表示通过选择器指定一个模板;
template:表示通过字符串创建一个模板
3.components
组件 -- 注册局部组件(组件 -- 模块化)
4.methods
定义函数,可以用来作为事件处理函数
methods: {
函数名() {
alert(1);
}
}
事件绑定:
<form v-on:click="函数名">
<form @click="函数名">
5.数据驱动
在vue中当data【状态(react)】数据发生变化时,会引起视图的改变
data中数据如何访问:
1)模板 通过{{}}访问
2)函数、生命周期钩子、监听器、计算属性...
this 指向当前vue实例,vue实例代理了data中的数据
思考:
为什么一个组件的更新只更新数据发生变化的部分而非全部更新?
AST 抽象语法树
Diff算法
6.this
1)代理data/methods
2)this.$refs
this.$m
3)渲染
将状态显示到视图中 model -> view
1.双大括号
可以存在任意变量或者表达式
变量/属性:
{{ msg }} //data:{msg:'hello'}
计算属性:
{{ students_male }}
方法:
{{ foo() }} //methods:{foo(){}}
{{ getStudentMale() }}
表达式:
{{ JSON.stringify(obj) }} //data:{obj:{}}
{{ msg?msg:'hello' }} //data:{mag:''}
{{ msg.toUpperCase() }}
2.指令 (自定义的属性)
1)v-on:eventType.事件修饰符
<form v-on:submit.prevent="事件处理函数">
<form v-on:submit.stop="">
<form v-on:submit.once="">
简写:
<form @submit.once="">
eventType 事件类型
dom类型:click,submit,hover...
自定义类型:dd(组件通信)
2)v-bind:属性名='属性值'
<img src=""/> 常量
<img v-bind:src=""/> 变量,表达式
简写:
<img :src=""/> 变量,表达式
3)v-for="" 循环渲染
<ul>
<li v-for="item in arr" :key="item.id"></li>
</ul>
将数组或集合中的数据展示出来
v-for="item in arr" v-bind:key="唯一值"
在列表渲染的时候,在重复的元素上务必添加一个key,表示唯一值
利于Diff算法对dom操作进行优化(效率偏低,但是准确度高)
4)条件渲染 布尔类型
v-if=""
v-else-if=""
v-else
满足条件的元素才会渲染
v-show=""
所有元素都渲染,通过display:none来控制是否显示;
频繁切换显示状态时使用
v-if和v-show的区别
1)v-if不存在dom树中,当满足条件时,再创建dom节点插进去
2)v-show存在dom树中通过display来控制显示与隐藏
5)v-model 【通常应用在表单元素中】
双向数据绑定(模型影响视图,视图也能影响模型)
1.将msg值作为input的默认值
2.用户如果操作了表单,v-model会将表单元素中的值映射到msg中
<input v-model="msg'>
v-bind:model="" 【通常应用在form元素中】
6)v-html
解析html标签
4)生命周期
beforeCreate
数据劫持 data -> vue
created
vue实例创建完毕,可以通过this来直接访问data,methods中的属性
beforeMount
此时具有渲染函数,template 模板-->产生 渲染函数 render
虚拟dom树已经构建,但是数据还未绑定到dom树中
mounted 生命周期构造函数
已经完成了初步绑定,render完成渲染
数据已经绑定到dom树中,虚拟dom树也已经插入到模板中
执行ajax
------------数据改变-----------------
beforeUpdate
在重新渲染之前执行
updated
完成了重新渲染
-------------------------------------
beforeDestroy
在销毁之前,释放资源
destroyed
销毁后
先创建Vue实例对象,再创建虚拟dom节点,再把实例中的数据与虚拟dom节点中的数据绑定在一起
5)双向数据绑定
v-model(表单)
6)事件
v-on:click="事件处理函数"
v-on:click.事件修饰符="事件处理函数"
v-on:click.事件修饰符="事件处理函数(传参)"
7)计算属性与监听器
1.计算属性 computed (缓存)
1)定义
像函数一样定义,但是无法接收参数
{
data:{
students:[]
},
computed:{
students_male(){
//对data中数据进行计算后输出
return this.students.filter()
}
}
}
2)调用
就像属性一样被调用,不加括号
{{ students_male }}
3)特性
1.多次调用同一个计算属性,计算属性函数会执行一次
2.当被计算的属性发生变化,计算属性函数会重新执行
4)计算属性和方法的区别
1.计算属性:具有缓存的作用;只计算一次;不能传参;调用不加括号{{ students_male }}
2.方法:methods可以传参,调用加括号
2.监听器 watch
浅监听:
watch:{msg:function(newValue,oldValue){}}
深监听:
watch:{obj:{handler(){},deep:true}}
1)定义
{
data:{
msg:'',
obj:{}
},
watch:{
//浅监听
msg(newVal,odlVal){
},
//深监听
obj(newVal,oldVal){
}
}
}
8)脚手架vue-cli
>cnpm install -g @vue/cli
>vue create cms-ui
9)DOM引用
vue提供给我们获取dom对象的方式
<div ref="container">
this.$refs.container
应用:图表渲染,antv,echarts,地图
10)模块化(组件)
vue中模块是最小组成单元
1.定义组件
vue参数的定义过程
let briupList={
template:`
<div>
<div v-for="">
{{}}
</div>
</div>
`,
//组件定义时data为函数
data(){
return {
}
},
methods:{}
}
2.注册组件
1)全局注册
将组件注册到Vue上,所有组件均可用
Vue.component('briup-list',briupList)
2)局部注册
将组件注册到某个组件内部,只有该组件才能使用这个组件
let ArticlePage={
template:``,
data(){
return {}
},
components:{
'briup-list':briupList
}
}
3.参数传递
1.组件内部如何接受传递的参数?
1)形参
let briupList={
props:['data']
}
2)形参,类型限制
let briupList={
props:{
data:Array
}
}
3)形参,类型限制,校验
let briupList={
props:{
data:{
type:Array,
default:[],
//validator校验器
validator:function(val){
}
}
}
}
2.如何传递参数?如何传递number/boolean
参数传递实际上就是属性绑定
4.插槽
1)简单插槽
2)具名插槽
component:article-page
<div>
<slot name="header"></slot>
<slot></slot>
<slot name="footer"></slot>
</div>
调用:
<article-page>
<div slot="header"></div>
<div></div>
<div slot="footer"></div>
</article-page>
3)作用域插槽 (day03 1-component.html)
scope:作用域
作用域插槽可以通过回调函数的思想来理解
父组件调用子组件,子组件在执行过程中又返回调用父组件的内容【插槽】
在调用过程中通过v-bind为这个插槽传递参数
在父组件中通过slot-scope="scope"中的scope来获取传递过来的参数,进行自定义渲染
子组件component:briup-list
<ul>
<li v-for="item in data">
<slot v-bind:row="item"></slot>
</li>
</ul>
父组件component:article-page
<briup-list>
<div slot-scope="scope">
{{scope.row.xxx}}
</div>
</briup-list>
参数传参与插槽:
1.props通过属性传参
2.slot通过模板传参 slot插槽,相当于占位符,来接收子模版
5.事件发射 $emit
$emit可以触发监控在当前组件上的指定事件
briup-info
<div>
{{msg}}
<button @click="clickHandler">关闭</button>
</div>
methods:{
closeHandler(){
this.$emit('close',msg)
}
}
article-page
<briup-info @close="close"></briup-info>
methods:{
close(num){
close(num){
alert(num);
}
}
}
11)组件通信
父组件 子组件
v-bind:xxx='' --> props:['xxx] /props:{}
<div slot=""></div> <--> <slot v-bind:xxx='xxx'></slot>
@close="close" <-- this.$emit('close')
:data="article" 单向数据流原则 articles
12)render函数
render 在beforeMount之后mounted之前
ast 抽象语法树
将模板编译(解析)为一个虚拟节点(节点描述)
{
render(h){
return h(tag,{},child)
}
props:{}
}
13)指令
v-on, v-bind, v-for, v-if, v-show ...
1.全局注册
Vue.directive('focus', {
inserted: function (el) {
el.focus()
}
})
2.局部注册
new Vue({
directives: {
focus: {
inserted: function (el) {
el.focus()
}
}
}
})
14)过滤器
时间 - 时间戳,当前时间到格林威治标准时间的时间差
new Date().getTime();
1634010195568 转换为任意格式--> 2021-12-12 11:40
1.全局注册
Vue.filter('formatTime', function (val) {
return moment(val).format('YYYY-MM-DD hh:mm')
})
Vue.filter('formatDate', function (val) {
return moment(val).format('YYYY-MM-DD')
})
2.局部注册
new Vue({
filters:{
formatDate(val){
return moment(val).format('YYYY-MM-DD')
}
}
})
15)插件
MyPlugin.install = function (Vue, options) {
Vue.myGlobalMethod = function () {
// 逻辑...
}
// 2. 添加全局资源
Vue.directive('my-directive', {
bind (el, binding, vnode, oldVnode) {
// 逻辑...
}
...
})
// 3. 注入组件选项
Vue.mixin({
created: function () {
// 逻辑...
}
...
})
// 4. 添加实例方法
Vue.prototype.$myMethod = function (methodOptions) {
// 逻辑...
}
}