vue

Vue

vue基础

前端框架发展史

  1. 最早期的网页是静态网页
  2. 后来出现了新的创建动态HTML的方式(数据嵌入到html文件中)如:ASP、JSP和PHP

这时候的互联网,兴起了数据嵌入模板,模板直接写样式的开发模式,例如MVC模式,在此时,前端只是后端 MVC中的 V,所以那时候的所谓 “前端工程师” 还没有对应的概念,前端开发人员都喜欢自称 “切图仔”。

  • Model(模型层):提供/保存数据。
  • Controller(控制层):数据处理,实现业务逻辑。
  • View(视图层):展示数据,提供用户界面。
  1. 1995年网景公司推出了javascript,形成了前端的雏形:HTML为骨架,CSS为外貌,JavaScript为交互
  2. 1998年前后,ajax得到了相对的应用,从而促进了Web 从 1.0 的静态网页,纯内容展示向 Web 2.0(Web 2.0 时代:动态网页,富交互,前端数据处理) 模式迈进

这时候,前端不再是后端的模板,它可以独立得到各种数据

  1. 2006年jquery出现了,快速地风靡了全球
  2. MVVM模型框架出现
  • 2009 年 AngularJS 诞生、Node诞生。
  • 2011 年 React 诞生。
  • 2014 年 Vue.js 诞生。

如今,后端负责数据,前端负责其余工作越发明显化。它们之间的通讯,只需要后端暴露API接口,前端通过 Ajax,以 HTTP 协议与后端通信即可。

什么是MVVM模式

  • Model:提供/保存数据。
  • View:视图(页面DOM)
  • ViewModel:监控者(它就是负责监控两侧的数据,并相对应地通知另一侧进行修改)。

vue模板语法

vue模板

var vue = new Vue({
    el:'#root',  //el写html标签(css选择器)
    // data定义的是当前vue应用的dom元素中要使用的数据
    data:{
        title:'hello vue',
        total:100
    },
     methods:{
        add(){
            return this.x + this.y
        }
    }
})

插值

  • {{变量名}}

变量名中含有html标签的内容是原样输出 不能解析html标签 <!-- v-html=“变量名”----将变量值作为当前标签的内容,是可以解析html标签,{{变量名}}}是不能解析html标签的 -->

  • v-html=“变量名”

变量名中带有html标签的内容 可以解析html标签

  • {{js表达式}}

{{price*number}}
{{‘btn-’+type}}
{{funcName()}}
{{sex==1?‘男’:‘女’}}

实例

		<p>{{1+2}}</p>
        <p>{{3>1?'red':'blue'}}</p>
        <p>{{title.slice(1,3)}}</p>
        <!-- 访问的是vue实例上定义的methods中定义的方法 -->
        <p>{{add()}}</p>  //add()是一个函数 是放在methods里面的
        <p>{{'x+y='+add()}}</p>
        <p>x+y={{+add()}}</p>

部分常用指令 v-

(是带有“v-”前缀的特殊属性)

  • v-bind:属性名=“变量名” 绑定动态属性
<img v-bind:src="imgSrc" v-bind:alt="imgName"/> <-- 主要用于设置dom元素的自带的属性,如src,href,checked, 当设置所有属性名和属性值相等的属性的时候,设置false则舍去此属性,true则保留此属性-->
  • v-bind缩写形式==>:属性名=“变量名”
 <img :src="imgSrc" :alt="imgName"/>
  • v-if,v-else,v-else-if
v-for与v-if一起使用(先执行v-for,再执行v-if)
<--当条件成立时则创建当前元素,不成立则删除-->
<div v-if="dataList.length">数据列表</div>
<p>
    <span v-if="sex==1"></span>
    <span v-else-if="sex==2"></span>
    <span v-else>保密</span>
</p>
  • v-show
 v-show="条件"  当条件成立则显示元素,不成立则隐藏元素
当元素会频繁地进行显示与隐藏时则用v-show,反之v-if
<div v-show="isShow">
</div>
  • v-for
// 遍历数组 v-for与v-if一起使用(先执行v-for,再执行v-if)
<ul>
    <li v-for="(item,index) in dataList" :key="index">
        {{item.name}}
    </li>
</ul>
//  遍历普通对象{key:value}
<div v-for="(val,key) in config" :key="key">
    <p><span>{{key}}:</span><span>{{val}}</span></p>
</div>
// 特殊用法
<p>
    <span v-for="n in 10">*</span>
</p>

key属性的作用:跟踪每个节点的身份,从而重用和重新排序现有元素,理想的key值是每项都有的且它的值是唯一的。

  • v-on:事件名=“函数名()”
<input type="button" v-on:click="add()" value="加1">
// add方法定义是写在Vue实例中的methods属性中
  <!-- v-on:事件名="方法名" 这种方式不能传递额外的参数-->
  • v-on缩写形式==>@事件名=“函数名()”
<input type="button" @click="add()" value="加1">
  • v-model(双向绑定) //常用于表单元素
 <!-- 双向绑定----数据变化视图自动更新,视图输入的内容也自动更新相应的数据 -->
<div>
    <input type="text" v-model="money" placeholder="请输入捐献金额">
    <p>你将捐献{{money}}金额</p>
</div>

数组更新检测

  • 对数组操作会导致更新检测的方法

数组对象的方法:shift(),pop(),unshift(),push(),splice(),sort(),reverse()
数组变量名 = 新的数组

  • 对数组操作不会导致更新检测

注意:数组名[下标] = newValue 并不会导致更新检测
以上解决方案:1、Vue.set(数组名,下标,newValue) 2、用数组对象的splice方法

 this.colors[0] = 100  // 这样的方式是不能触发响应模式,因为没有使用Object.defineProperty来动态设置数组的元素
// Vue.set(this.onechecked,index,e.target.checked)
// this.onechecked.splice(index,1,e.target.checked)

对象更新检测 Vue.set

注意:要检测对象的属性是否变化了,一定要在声明此对象时将它的属性进行初始化,否则后期动态添加上的属性Vue是不能对它更新检测的,除非通过**Vue.set(对象名,属性名,值)**方法手动设置

Vue.set(对象名,属性名,值)

 // avator对象起初没有src属性,以下设置并不会触发更新检测
            this.avator.src = '1.jpg'
// 可以通过Vue实例的$set方法设置,触发视图更新
            this.$set('avator','src','1.jpg')
 			Vue.set('avator','src','1.jpg')

object.definePorperty

声明响应式属性

let Person = {age:20}

Object.defineProperty(Person, 'name', {
    get: function () {
        // 当在获取当前对象的当前属性时自动调用该方法
        console.log('get....')
    },
    set: function (val) {
        // 当在设置当前对象的当前属性时自动调用该方法
        console.log(Math.random())
        document.getElementById('nickname').innerHTML = val
    }
})

事件处理

事件处理几种写法

  • 监听事件—直接触发代码
<input type="button" @click="count = count + 1">
  • 方法事件处理器----写函数
<input type="button" @click="add">
// 这样方式不能传递参数,在定义add方法时可以写一个形参变量,用于接收当前事件对象
  • 内联处理器方法----执行函数表达式
<input type="button" @click="increment(2)">
// 这样方式能传递参数
<input type="button" @click="increment2($event,2)">
// $event是当前事件对象,是Vue中的内置变量

修饰符

事件修饰符

  • .stop 阻止事件冒泡(掌握)
  • .prevent 阻止默认事件(掌握)
  • .once 事件执行一次
  • .self 事件源是本身才会触发
  • 事件修饰符可以串写,如@click.stop.prevent
<div class="outer" @click="say()">
        <!-- 阻止事件冒泡 -->
        <div class="inner" @click.stop="out()"></div>
    </div>
     <!-- 阻止默认事件 -->
    <form @submit.prevent>
        <input type="submit" value="提交表单"/>
    </form>
    <!-- self点击的对象是本身,once事件绑定一次,修饰符可以连写 -->
    <div class="outer" @click.self.once="say()">
        <div class="inner" @click="out()"></div>

按键修饰符

  • .enter 按下并释放回车键时

@keyup.enter<==>@keyup.13

  • .left,.right,.top,.down 按下并释放左、右、上、下键时
  • .esc 按下并释放esc键时
  • .space 按下并释放空格键时
  • .tab 按下并释放tab键时
  • .delete 按下并释放删除键时

系统修饰键

  • .alt

@keyup.alt.67 ===> 按alt+c键时

  • .ctrl

@click.ctrl ===> 按住ctrl键同时再单击时

  • .shift

     <form @submit.prevent>
            <!-- <input type="text" placeholder="输入品牌名称" @keyup.enter="send($event)"/> -->
            <input type="text" placeholder="输入品牌名称" @keyup.ctrl.enter="send($event)"/>
     </form>
    

表单绑定 v-model

单行文本框

v-model绑定的变量的值作为单行文本框的内容

<input type="text" v-model="message">

多行文本框

v-model绑定的变量的值作为多行文本框的内容

<textarea v-model="desc">
</textarea>

单选按钮

v-model绑定的变量的值是同一组单选按钮的value值之一

<input type="radio"  v-model="sex" :value="1"><input type="radio"  v-model="sex" :value="2">

多选框

v-model绑定的变量的值是同一组复选框的value值中的一个或者多个,变量值是数组

<input type="checkbox"  v-model="subject" value="java">java
<input type="checkbox"  v-model="subject" value="C++">C++
<input type="checkbox"  v-model="subject" value="H5">H5
<input type="checkbox"  v-model="subject" value="phyon">phyon

下拉选择框(单选与多选)

单选,v-model绑定的变量的值是下拉列表所有选项的value值之一

<select v-model="brandId">
    <option :value="1">华为</option>
    <option :value="2">小米</option>
    <option :value="3">苹果</option>
</select>

多选,v-model绑定的变量的值是下拉列表所有选项的value值中的一个或者多个,变量值是数组

<select v-model="cityIds" multiple>
    <option :value="10">上海</option>
    <option :value="11">广州</option>
    <option :value="12">北京</option>
</select>

v-model的修饰符

.lazy–延迟更新
.number—强制将变量的值转换为数字整型
.trim—删除变量值两边空格

class与style属性绑定

绑定class

  • 对象语法(:class="{类名1:boolean,类名n:boolean}")
<div :class="{ active: isActive}" class="box">可以与普通的class共存</div>
  • 数组语法(:class=[‘类名1’,‘类名2’,{类名:boolean}])
<div :class="['box',{active:isActive}]" class="border">可以与普通的class共存</div>

绑定style属性

  • 对象语法(:style="{样式名1:值,样式名n:值}")
<p :style="{color:'#ccc',fontSize:'18px'}">绑定内联样式</p>
  • 数组语法(:style="[{样式名1:值,样式名n:值},{样式名1:值}]")
<p :style="[{color:'#ccc',fontSize:'20px'},{backgroundColor:'orange'}]">使用数组形式添加内联样式</p>

计算属性computed

模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护;所以,对于任何复杂逻辑,你都应当使用计算属性

函数可以返回任意类型的数据

// 声明n个计算属性(某个属性的值是依赖其它变量计算得来的数据)
computed: {
    total() { //total作为变量放入html标签中 
        // 函数的返回值作为计算属性的值,当参与计算的任意变量发生变化时则自动调用该方法
        return this.lifeAccount + this.telAccount + this.transportAccount
    },
    sum: {
        get() {
            // 返回计算属性的值,当计算total的值运行的函数
            return this.lifeAccount + this.telAccount + this.transportAccount
        },
            //当设置total的值的时候运行的函数  newValue是新的total的值
        set(newValue) {
        this.lifeAccount = this.telAccount = this.transportAccount = newValue / 3
        }
    },
},
<ul>
    <li v-for="(item,index) in oddNums">{{item}}</li>
</ul>
new Vue({
    computed:{
        oddNums(){
           // <!-- 当numbers变量的值发生变化此函数将会被执行 -->
            return this.numbers.filter((item)=>item % 2 == 0)
        }
    }
})

监听属性watch

当需要在数据变化时执行异步或开销较大的操作时,watch这个方式是最有用的

watch:{
        // 监听的是基本数据类型变化
        total(newVal,oldVal){
            // 当total变量的值发生变化时则执行当前方法
            console.log(newVal,oldVal)

            // 重新计算总页码,获取数据
            this.pages = Math.ceil(newVal / 10)
            this.getData()
        },
        // 监听对象的属性是否变化时
        'pageInfo.total':function(newVal,oldVal){
            console.log('监听对象上某个属性变化:',newVal)
            this.pages = Math.ceil(newVal / 10)
            this.getData()
        },
        // 监听对象变化(只要修改对象的任意一个属性则执行某个功能)---常用用于监听$route(路由变化)
        filter:{
            handler(newVal,oldVal){
                console.log('filter',newVal)
            },
            deep:true, //递归的监听
            immediate:true,  //(页面初始化完毕)立即监听   加载页面的时候就执行一次
        }
    },
watch:{
        // 监听基本类型变量
        typeId1(newVal,oldVal){
            // 当typeId1变化时将执行此方法数
            // newVal是最新的值,oldVal是前一次的值
            if(newVal){
                this.getData()
            }
        },
        typeId2:{
            //如果我们需要在最初绑定值的时候也执行方法,则就需要用到immediate属性。
            handler(newVal,oldVal){
                if(newVal){
                    this.getData()
                }
            },
            immediate:true
        },
        // 监听对象上某个属性
        'filter.name'(newVal,oldVal){
            this.search()
        },
        // 监听一个对象的改变时,需要将deep属性设置为true
        filter:{
            handler(newVal,oldVal){
                // filter对象上的任何属性变化了将执行此方法
            },
            deep:true
        }
    },

computed和watch的区别

计算属性与监听属性的使用场景

当你在模板内使用了复杂逻辑的表达式时,你应当使用计算属性。
当需要在数据变化时执行异步或开销较大的操作时,使用watch。

调用计算computed属性与通过调用方法methods来获取到某数据的区别

  • computed是属性调用,而methods是函数调用;
  • computed带有缓存功能,而methods不具有缓存功能;
  • 我们可以使用 methods 来替代 computed,效果上两个都是一样的,但是 computed是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。而使用 methods ,在重新渲染的时候,函数总会重新调用执行。可以说使用computed性能会更好

组件 component

每个组件的数据中心是的独立的

组件 :就是页面上的一部分。

组件的创建

// 组件名—首字母大写,例如HhPage

// 创建组件 Vue.component(‘组件名’,{组件的配置项})

// 创建一个按钮组件
Vue.component('HhButton',{
    name : "hhbutton", //给组件创建一个名称
    template:`<button>普通按钮组件</button>`,
    data(){
        // 定义组件自己的数据中心是用的data方法,该方法一定要返回一个对象
        // 为什么要返回一个对象,目的是让当前组件的每一个实例的数据是独立的
        return  {
            width:200
        }
    },
    props:{  //也可以写成 props:["title","type"]
    title:String,
    type:{
        type:String, //type属性的类型 
        default:'success', //设置当没有属性值的时候 默认值
        validator(val){
            // val接收的是当前属性值
            let flag = ['info','warning','danger','success'].indexOf(val) !== -1 
            if(!flag){
                console.log('********传递type属性值有误,当前传递的值是:'+val)
            }
            return flag
        }
    }
},
})

父组件向子组件传递数据

通过props进行数据的传递

在组件中是不能修改props属性值,(单向向下行绑定数据----单向数据流)----组件data上的数据由自己的行为处理

实例:

const ElChild = {
    template : `<div><button>显示数据</button>
            <p>{{numchild}}</p>
        </div>`,
    props:["numchild"], //子组件通过props对数据进行接收
}

Vue.component("ElParent",{
    template :`
        <div>
            <el-child :numchild="num"></el-child>
        </div>`, //父组件的模板通过绑定自定义属性:numchild把数据传入子组件
    data() {
        return {
            num : 1,
        }
    },
    components : {
        ElChild,
    }
})

子组件向父组件传递数据

通过自定义事件进行数据的传递

// 子组件向父组年传递数据(通过事件)

// 1.在父组件中使用子组件时绑定自定义事件

// 2.在子组件中触发在子组件上绑定的自定义事件emit()–>this.$emit(‘自定义事件名’,传递的数据)

// 3.在父组件中通过$event来获取子向父传递的数据

实例:

const ElChild = {
    template : `<div><button @click="emit(money)">显示数据</button></div>`,
    data() {
        return {
            money : 3,
        }
    },
    methods: {
        emit(e){ 
            this.$emit("getdata",e) //向父组件自定义事件为getdata的事件传递数据。e可以是任意类型的数据
        }
    },
}
Vue.component("ElParent",{
    template :`
    <div>
        <el-child @getdata="gete($event)"></el-child>
    </div>`, //$event是获得的数据
    methods: {
        gete(e){
            console.log(e); //e是子元素传递的数据
        }
    },
    components : {
        ElChild,
    }
})
new Vue({
    el:"#box",
})

兄弟组件传递数据

可以实现跨级传递数据

通过中央控制事件总线进行数据的传递

中央控制事件总线 就是一个空的Vue

var bus = new Vue()
bus. o n ( ′ 事 件 名 ′ , ( ) = > ) − − − − 写 在 组 件 的 c r e a t e d 勾 子 函 数 中 b u s . on('事件名',()=>{}) ----写在组件的created勾子函数中 bus. on(,()=>)createdbus.emit(‘事件名’,传递的数据)

//通过 中央控制事件总线
//bus.$on("事件名",()=>{})   接收数据并进行相应的处理
//bus.$emit('事件名',传递的数据)   发送数据

实例

Vue.component('HhB', {
    data() {
        return {
            bank: 2000,  
        }
    },
    template: `
    <div>兄弟组件B{{bank}}
    </div>`,
    created(){
        let _this = this
        bus.$on('jq',function(val){
            if(_this.bank > val){
                _this.bank -= val
                bus.$emit('answer',{code:1,msg:'同意',money:val})
            }else{
                bus.$emit('answer',{code:0,msg:'对不起,金额不足',money:0})
            }
        })
    }
})

Vue.component('HhA', {
    data() {
        return {
            money: 600,
            num:0
        }
    },
    template: `
    <div>兄弟组件A{{money}}
    <hr />
    <input type="text" v-model.number="num" @keyup.enter="brrow()"/>
    </div>`,
    methods:{
        brrow(){
            bus.$emit('jq',this.num)
        }
    },
    created(){
        bus.$on('answer',(val)=>{
            if(val.code == 1){
                this.money += val.money
            }else{
                console.log(val.msg)
            }
        })
    }
})
new Vue({
    el: '#app'  
})

组件绑定class和style

<App :style="{backgroundColor:'#ccc'}"></App>
<App :class="['bg','active']"></App>
<App :class="{active:index==2}"></App>
<!--有个App组件-->

slot 插槽

slot标签用于占位,接受当前组件中的子内容

//页面的<div slot="s"> <span></span> </div>
//template中 <slot name="s"></slot>
//页面中的内容等于<slot> </slot>   
//<slot name="s"></slot> = <div> <span></span> </div>

当定义组件时,组件的内部结构是无法确定时则可以用slot占位

<hh-swiper> 
<!-- 这一部分放在默认插槽处 -->
        <div>
            <img src="1.jpg" />
            <img src="2.jpg" />
        </div>
        <!-- 这一部分放在slot的name属性为pagination处 -->
        <div slot="pagination">
            <span>1</span> <span>2</span>
        </div>
</hh-swiper> //组件标签
// slot标签用于占位,接收的是当前组件中的子内容
// 定义组件中加了<slot name="插槽名称"></slot>,在使用组件时<组件名>插槽的内容</组件名>
 template:`
       <div class="swiper-container">
            <div class='swiper-items'>
                <slot>swiper要播放的项</slot>
            </div>
            <div class="swiper-pagination">
                 <slot name="pagination">swiper的分页器</slot>
            </div>
            
       </div>
    `

this.$refs.refName

在vue.js中获取dom元素或者组件的实例

例如

<div ref="header" class="box"></div>
<!-- 想获取这个div 
Vue的写法为 var box=this.$refs.header 
这个box就是这个div DOM元素-->

动态组件

// is来对变量进行判断

template:`
    <div>
        <div>
            <component :is="componentName"></component>
        </div>
        <hh-nav></hh-nav>
    </div>
    `,
    data(){
        return {
            componentName:'HhCenter' //用来改变组件的变量
        }
    },

声明周期

生命周期钩子

创建和挂载内的函数在页面加载的时候会自动运行一次 创建created 挂载mounted

// created----初始化页面数据以及ajax请求

// mounted----用于获取dom元素的

vue一整个的生命周期中会有很多钩子函数提供给我们在vue生命周期不同的时刻进行操作,项目开发中常用的两个生命周期钩子函数是(created,mounted)

  • beforeCreate

实例状态:实例初始化之后,this指向创建的实例,不能访问到data、computed、watch、methods上的方法和数据
使用场景:常用于初始化非响应式变量

  • created

组件状态:实例创建完成,可访问data、computed、watch、methods上的方法和数据,未挂载到DOM,不能访问到 e l 属 性 , el属性, elrefs属性内容为空数组
使用场景:常用于简单的ajax请求,页面的初始化

  • beforeMount

实例状态:在挂载开始之前被调用,beforeMount之前,会找到对应的template,并编译成render函数

  • mounted

实例状态:实例挂载到DOM上,此时可以通过DOM API获取到DOM节点,$refs属性可以访问
使用场景:常用于获取dom元素以及对它的操作

  • beforeUpdate

实例状态:响应式数据更新时调用,发生在虚拟DOM打补丁之前 js的一个对象来描述的html结构
使用场景:适合在更新之前访问现有的DOM,比如手动移除已添加的事件监听器

  • updated

实例状态:虚拟DOM重新渲染和打补丁之后调用,组件DOM已经更新,可执行依赖于DOM的操作
注意:避免在这个钩子函数中操作数据,可能陷入死循环

  • beforeDestroy

实例状态:实例销毁之前调用。这一步,实例仍然完全可用,this仍能获取到实例
使用场景:常用于销毁定时器、解绑全局事件、销毁插件对象等操作

  • destroyed

实例状态:实例销毁后调用,调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁

axios获取数据

axios的使用方式和jquery的AJAX请求没有什么区别

axios还相当于Promise所以回调函数是使用then

格式

axios({
    url : "",
    method :"",
    .....
}).then((res)=>{})//res是请求端口响应的数据
// 设置ajax请求的基本路径
axios.defaults.baseURL = 'http://localhost:9000/';
// 设置ajax请求超时时间
axios.defaults.timeout = 2000 
// 设置响应拦截器
axios.interceptors.response.use(result => {
    return result.data
},error=>{
    if(error.message.includes('timeout')){
        alert('请求超时')
        return 'timeout'
    }
    return Promise.reject(error);
});
// 设置请求拦截器
axios.interceptors.request.use((config)=>{
    // 在此可以设置所有接口都需要用到的参数
    config.headers['usertoken'] = '299429942428423191031031';
    return config
})

// get请求
axios.get(url).then(data=>{
}).catch(err=>{
})
// post请求
axios.post(url).then(data=>{
}).catch(err=>{
})
 axios({
   url : "https://m.maizuo.com/gateway?cityId=510100&pageNum=1&pageSize=10&type=1&k=4834734",
   method : "get",
   headers:{
  "X-Client-Info": '{"a":"3000","ch":"1002","v":"5.0.4","e":"156767148210033043604248"}',
  "X-Host": "mall.film-ticket.film.list"
            }
}).then(res=>{
      if(res.data.status==0){
      this.bannerlist=res.data.data.films
               } 
})

swipei组件的使用

//在不使用组件的时候 由于创建的时候拿到数据属于异步操作,所以当使用数据放入DOM元素中的时候会出现BUG,就是数据还没有拿到就进行了DOM操作。
//解决办法 
//一. 在updated中调用对DOM进行操作的函数。但是由于操作只需要进行一次,所以设定判定条件
updated() {
if(this.bannerbool){this.setswiper()}//数据更新的时候只调用一次
},
//二.使用组件,在调用组件的时候设定if条件,判断数据拿到了,就在页面创建元素
<el-banner v-if="bannerlist.length" :bannerlist="bannerlist"></el-banner>

过滤器 Vue-filter

过滤器的作用就是在使一个函数变得可以多次重复调用,在页面的DOM元素上。

主要用于数据不是自己想要的数据的格式的时候对数据的处理

全局过滤器

全局过滤器,在创建Vue实例前定义,在实例所挂载的el元素范围内都能使用

在v-html中不能使用过滤器

Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号指示

过滤器只能用于插值表达式中

模板

Vue.filter('过滤器名称',function(val){
    return  //返回值   val为接收的参数
})
<!-- 在双花括号中 -->
{{ val | 过滤器名称 }}
<!-- 在 `v-bind` 中 -->
<div v-bind:id="val | 过滤器名称"></div>

实例:

Vue.filter('formatDate',function(val){
    // val接收的是过滤器处理的变量值
    return new Date(val).toLocaleDateString()
})


// 过滤器只能用于插值表达式的语法中

const filters = {
    filterA(){
        return '123'
    },
    filterB(){
        return '456'
    },
}
// 批量创建过滤器
for(var i in filters){
    Vue.filter(i,filters[i])
}

局部过滤器

局部过滤器,只供当前组件使用

// 局部过滤器 在组件中配置项filters

模板

// 在组件的选项中定义
filters: {
  capitalize: function (value) {
    if (!value) return ''
    value = value.toString()
    return value.charAt(0).toUpperCase() + value.slice(1)
  }
}

实例

template:`<div>局部过滤器:<p>主要演员:<span>{{actors|formatActors}}</span></p></div>`,
    filters:{
        formatActors(actors){
            // 在过滤器不要返回html标签,应用在插值表达式不能解析的
            let str = ''
            actors.forEach(item=>{
                str += item.name + ' '
            })
            return str
        }
    },

自定义指令Vue-directive

除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令,有时候需要对普通DOM元素进行底层操作,这时候就会用到自定义指令

全局指令

// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
  inserted: function (el) {
    // 聚焦元素
    el.focus()
  }
})

内部钩子函数

Vue.directive('指令名称',{
    bind(){//只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
        console.log('bind')
    },
    inserted(){//被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)
        console.log('inserted')
    },
    update(){//更新的时候就进行调用
        console.log('updated')
    }
})

钩子函数简写方式:

// 当初始化的行为(bind或者inserted)与更新(update)时的行为相同时用以下简写的方式来实现
Vue.directive('hide1',function(el,binding,vode){
    if(binding.value){  //binding.value为指令的绑定值
            el.style.display = 'none'
       }else{
            el.style.display = ''
       }
})

局部指令

可以在组件中使用 directives建立

// 在组件的选项中定义
directives: {
  focus: {
    inserted: function (el,binding,vnode) {
      //el 指令所绑定的元素,可以用来直接操作 DOM 。
      // binding 一个对象,所包含属性参考官网,其中有一个value属性获取到使用指令时传递的参数
      el.focus()
    }
  }
}
// 在模板中使用方式:<input v-focus />

vue-cli

使用脚手架搭建项目

  1. 安装

npm install -g @vue/cli (全局安装)

  1. 创建项目

vue create 项目名称

  1. 命令的使用

npm run serve 开发环境构建 建立本地服务器
npm run build 将应用程序打包
npm run lint 代码检测工具

4.项目目录的介绍

public下的资源不会打包

assets下的资源会打包

@符号表示src文件夹

main.js

import Vue from 'vue'
// .vue----单文件组件(template(模板),script(数据+行为部分),style(样式部分))
// import App from './App.vue' // .vue文件是通过vue-loader工具转换为可识别的js文件

// import Hello from './Hello.vue'
import router from './router' //引入路由文件
import Todo from './Todo.vue'
Vue.config.productionTip = false
// main.js是入口文件----入口起点(entry point)指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。
new Vue({
    router : router, //使用路由文件
  render: h => h(Todo)
}).$mount('#app')

router.js

import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'

Vue.use(Router) //在vue上使用router

export default new Router({
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home
    },
    {
      path: '/about',
      name: 'about',
      // route level code-splitting
      // this generates a separate chunk (about.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import(/* webpackChunkName: "about" */ './views/About.vue')
    }
  ]
})

单文件组件实例

<template>
    <div>
        <h1 @click="say('hello .vue')">{{title}}</h1>
    </div>
</template>
<script>
export default {
    data(){
       return {
            title:'第一个单文件组件'
       }
    },
    methods:{
        say(msg){
            console.log(msg)
        }
    }
}
</script>
<style scoped lang="scss">
$color:blue;
h1{
    color:$color
}
</style>

vue.config.js的配置

在项目根目录下创建vue.config.js,注意修改了此文件内容需要重新运行npm run serve命令

Vue.config 是一个对象,包含 Vue 的全局配置。

proxy代理配置

// 在vue.config.js中添加以下代码
devServer:{
    port:3000,
    '/api':{
        target:'http://m.maoyan.com/',
        changeOrigin: true,
        pathRewrite: {
            '/api': ''
        }
    }
}

alias别名配置

@ is an alias to /src

// 在vue.config.js中添加以下代码
chainWebpack:(config)=>{
    console.log(config.resolve.alias.get('@')) // 获取别名
    // 为src/components目录设置别名为components
    config.resolve.alias.set('components',resolve('./src/components'))
}

publicPath配置

部署应用包时的基本URL,默认值是’/’,当程序不是部署在网站根目录是则需要配置此项

关闭eslint

去掉eslintrc.js文件中的@vue/standard

json-server实现mock数据

安装

npm install -g json-server

json-server命令的使用

json-server --watch db.json

利用vue-cli进行组件化开发

迁移todolist、swiper案例到vue-cli中

利用swiper模块封装一个Swiper组件

安装

npm install swiper --save

实现

<template>
  <div class="swiper-container">
    <div class="swiper-wrapper">
      <div class="swiper-slide" v-for="(item) in data" :key="item.bannerId">
        <img :src="item.imgUrl" />
      </div>
    </div>
    <div class="swiper-pagination"></div>
  </div>
</template>
<script>
import Swiper from "swiper";
import "swiper/dist/css/swiper.css";
export default {
  props: ["data"],
  data() {
    return {
      title: "swiper模块的使用"
    };
  },
  mounted() {
    new Swiper(".swiper-container", {
      pagination: {
        el: ".swiper-pagination"
      },
      autoplay: {
        delay: 3000,
        stopOnLastSlide: false,
        disableOnInteraction: true
      }
    });
  }
};
</script>
<style scoped lang="scss">
</style>

vue-router

起步

  • 安装
  • 通过vue-router创建路由规则

动态路由

在定义路由时路径中带有冒号的即是动态路由,例如路径是 /film/:id 为动态路由,通过this.$route.params.id 获取到相应的值

动态路由(路径中包含了以:开头的部分,这一部分值是不确定的)

写法

path:'/article/:id',

嵌套路由

注意使用嵌套路由的时候 children里面的路由不要加/

const router = new VueRouter({
routes:[{
	path:'/films',
	component:FilmIndex,
	children:[{
		path:'',
		// 当访问/films路由时直接跳转到/films/playing路径
		redirect:'/films/playing'
	},{
		path:'playing',
		//PlayingFilm 会被渲染在FilmIndex的<router-view>中
		component:PlayingFilm
	},{
		path:'coming',
		//ComingFilm 会被渲染在FilmIndex的<router-view>中
		component:ComingFilm
	}]
}]
})

实例:

{
    path:'/films',
    component:FilmsIndex,
    children:[{
      path:'',
      // redirect重定向
      redirect:'/films/nowPlaying'
    },{
      path:'nowPlaying',
      component:NowPlaying
    },{
      path:'comingSoon',
      component:ComingSoon
    }]
  }

编程式的导航

path 和params不能一起使用

this.$router.push('路径')
this.$router.push({path:'路径',query:{参数名:}})
this.$router.push({name:'路由名称',params:{参数名:}}) //通过name查找路由
// 注意:this.$router.push方法的参数是对象时,path不能与params搭配使用
// 获取动态路由中的参数使用this.$route.params
// 获取路径中?部分的参数使用this.$route.query
this.$router.go(-1)//-1表示返回上一页

实例:

goBack(){
            // 转向某地址
            // this.$router.push('/article')
            // this.$router.push({path:'/article'})
            this.$router.go(-1)  // 上一页(history.back())
        }
<li><router-link to="/article/199">react基础部分</router-link></li>
<li><router-link to="/article/100">react路由</router-link></li>
<li><input type="button" @click="$router.push({name:'detail',params:{id:800}})" value="查看文章id为109"/></li>
<li><input type="button" @click="$router.push({path:'/article/109'})" value="查看文章id为109"/></li>
<!-- <h1>当前文章id是:{{$route.query.id}}这是文章详情页面</h1> -->
    <h1>当前文章id是:{{$route.params.id}}这是文章详情页面</h1>

路由守卫

全局前置守卫(全局拦截)

写在路由外部

const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => { //进入路由前进行相应的运算
	//next传参就跳到指定页面 不传参就跳到to的路径
})
router.afterEach(()=>{}) //进入路由后进行相应的运算

实例:

// 路由前置守卫----用于检测用户认证
let whitePathes = ['/login','/home'] //路由白名单
router.beforeEach((to,from,next)=>{
    // to 进入的那个路由   from来自那个路由  next是个函数 决定是否展示to路由的组件
    console.log('********',to)
    if(whitePathes.indexOf(to.path) === -1 && !localStorage.getItem('username')){
       // router.push('/login')
        next('/login')
        return
    }
    console.log('这是路由的全局守卫',to.path,from.path)
    next()
})
路由的独享守卫(单个拦截)

写在路由内部

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
      }
    }
  ]
})

实例:

 beforeEnter(to,from,next){
            console.log('当前路由守卫....',to.params,from.path)
            if(isNaN(to.params.nid)){
                console.log('参数有误,新闻id必须有的')
                next('/error')
                return
            }
            next()
        }
组件内的守卫(单个拦截)

写在组件内部

// 在同一个组件中切换时,组件不会重新挂载,而又要重新渲染页面的数据时,在路由发生变化时去更新相应的数据
/* 这里注意的是:::如果切换当前新闻id时还要重新获取相应的详情数据,
需要在beforeRouteUpdate中处理 */

beforeRouteEnter (to, from, next) {
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`
    // 因为当守卫执行前,组件实例还没被创建
    next(vm => {
    	// 通过 `vm` 访问组件实例
  	})
},
beforeRouteUpdate (to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
},
beforeRouteLeave (to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例 `this`
}

监听路由变化

当路由发生改变的时候 运行handle的函数

watch:{
'$route':{
    handle(newValue,oldValue){
		// 当前路由发生变化时将调用该方法,如/user/1切换到/user/2时
    },
    deep:true,
    immediate:true // 页面初始化完成就立即监听
}
}

路由元信息

定义路由的时候可以配置 meta 字段:

const router = new VueRouter({
  routes: [
    {
      path: '/user',
      component: User,
      children: [
        {
          path: 'list',
          component: UserList,
          // 通过meta属性可以配置当前路由的说明信息
          meta: { title: '用户列表' }
        }
      ]
    }
  ]
})

实例:

{
        path:'/login',
        component:Login,
        // 是可以在当前路由上存储一些项目中需要的数据
        meta:{
            hideHeader:true
        }
    }

获取此路由上的meta

watch:{
        $route:{
            handler(val){
                this.isShow = !val.meta.hideHeader
            },
            deep:true,
            immediate:true
        }
    }

路由懒加载

按需要加载组件

const router = new VueRouter({
  routes: [
    { path: '/user', component: ()=> import('./views/User.vue') }
  ] //就是把component写为函数形式 而不是一开始进入主页面就把全部的组件加载完成。当需要那个组件的时候就加载那个组件,使得进入主页面更快
})

HTML5 History模式

  1. 设置mode为history,默认是hash(router.js中)
  2. 后端配置(这里以node.js+express作为后端为例)
app.use(express.static('./')) // 设置静态资源目录第一次
const history = require('connect-history-api-fallback'); // 支持history模式的中间件
app.use(history());
app.use(express.static('./')) // 设置静态资源目录第二次
// 注意必须设置两次静态资源目录两次,否则没有办法实现history模式

vuex Store

状态管理:可追踪,共享数据,数据变化所有使用这个数据的组件也进行改变

工作原理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u05BsdEE-1619682841247)(C:\Users\客户\Desktop\笔记\images\vuex.PNG)]

创建

store.js的内容

// vuex ---安装 npm install --save-dev vuex
// 导入
import Vue from 'vue'
import Vuex  from 'vuex'
Vue.use(Vuex) //全局使用vuex
// 状态管理中心----一个应用程序只能创建一个状态管理中心
let store = new Vuex.Store({
    //所有组件共享的数据中心
   state:{
       money:99, //班费
       username:'admin'
   },
   // 定义的规则来改变state中的数据,同步事务
   mutations:{
       // 现金交班费,state是接收的是当前store中的state
       addMoney(state,number){
            state.money += number
       },
   },

   // 处理异步事务的规则,是不能直接改变state中的数据,只能提交给mutaions中的规则来改变
   actions:{
       // context与store对象拥有相同的属性以及方法
       ybAddMoney(context){
           setTimeout(function(){
               // 异步执行完毕时则提交mutations中的方法
               context.commit('addMoney',450)
           },2000)
       },
   },
   getters:{
       // isOk是state的扩展数据
       isOk(state){
            return state.money < 100 ? '班费不足,请交班费' : '班费充足'
       }
   }
})
export default store

组件的内容:

访问store中的state数据,html=>{{KaTeX parse error: Expected 'EOF', got '}' at position 18: …ore.state.money}̲} js=>this.store.state.money

import { mapState,mapMutations,mapActions } from 'vuex'
export default {
    data(){
        return {}
    },
    computed:{
        free(){
          return  this.$store.state.money
        },
        ...mapState(['money','username'])
    },
    methods:{
        // 将this.addMoney(600)映射为this.$store.commit('addMoney',600)
        ...mapMutations(['addMoney','buyWater']),
        // 将this.ybAddMoney()映射为this.$store.dispatch('ybAddMoney')
        ...mapActions(['ybAddMoney','ybReduceMoney']),
        give(){
            // this.$store.commit('规则名称即是mutaions中定义的方法名',传递的参数)
           // this.$store.commit('addMoney',600)
           this.addMoney(600)
        } ,
        ybGive(){
            // 触发store中心定义的actions中的ybAddMoney方法
             // this.$store.dispatch('规则名称即是actions中定义的方法名',传递的参数)
           // this.$store.dispatch('ybAddMoney')
           this.ybAddMoney()
        },
    }
}

state

存放所有的公共数据的地方 相当于组件中的computed

//在组件中获取数据  //在计算属性中
 computed: {
    count () {
      return this.$store.state.count
    }
  }
//在html中可以使用 {{$store.state.count}}
// 在单独构建的版本中辅助函数为 Vuex.mapState
import { mapState } from 'vuex'

export default {
  computed: mapState({
    // 箭头函数可使代码更简练
    count: state => state.count,
  })
}
//也可以使用数组的方式
export default {
  computed: mapState(["count"])
}

mutations

实现同步操作的地方

每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数:

在组件中提交 Mutation

this.$store.commit( 规则名称即是actions中定义的方法名 , 参数)

import { mapMutations } from 'vuex'

export default {
  methods: {
      // 将this.addMoney(600)映射为this.$store.commit('addMoney',600)
        ...mapMutations(['addMoney','buyWater']),
      give(){
            // this.$store.commit('规则名称即是mutaions中定义的方法名',传递的参数)
           // this.$store.commit('addMoney',600)
           this.addMoney(600) //调用
        } ,
  }
}

store中的mutations

 mutations:{
       // 现金交班费,state是接收的是当前store中的state
       addMoney(state,number){
            state.money += number
       },
   },

actions

处理异步操作的地方

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。

store中的actions

 // 处理异步事务的规则,是不能直接改变state中的数据,只能提交给mutaions中的规则来改变
   actions:{
       // context与store对象拥有相同的属性以及方法
       ybAddMoney(context){
           setTimeout(function(){
               // 异步执行完毕时则提交mutations中的方法
               context.commit('addMoney',450)
           },2000)
       },
   },

组件中使用actions

this.$store.dispatch( 规则名称即是actions中定义的方法名 )

 // 将this.ybAddMoney()映射为this.$store.dispatch('ybAddMoney')
        ...mapActions(['ybAddMoney']),
 ybGive(){
            // 触发store中心定义的actions中的ybAddMoney方法
             // this.$store.dispatch('规则名称即是actions中定义的方法名',传递的参数)
           // this.$store.dispatch('ybAddMoney')
           this.ybAddMoney()
        },

getters

相当于是计算属性 只是是store的计算属性 和state中的数据相差不大

store中的getters

 getters:{
    havemoney(state){
      if(state.money<0){
        state.money = 0
      }
      return state.money>0? "还有钱":"没有钱啦"
    }
  }

组件中使用

//可以使用mapGetters
//也可以使用$store.getters.key

module

模块化

Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:

写法

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
export default {
    // 如果namespaced为true时,在调用相应的actions和mutaions需要在方法名前加模块名/
    // 例如在组件中写:this.$store.commit('mas/changeBg')
    // 例如在组件中写:this.$store.dispatch('mas/changeYbBg')
    namespaced:true,
    state:{
        bgColor:'red'
    },
    mutations:{
        changeBg(state){
            console.log('模块a中的changeBg方法')
        }
    },
    actions:{
        changeYbBg(state){
            console.log('模块a中的changeYbBg方法')
        }
    },
    getters:{

    }
}

项目

流程

产品对接客户 》需求文档》产品原型图(墨刀)

开发 UI 前端 后端 测试

熟悉产品业务–原型图规划结构(项目搭建)–静态页面–分模块开发

flexiable.js 动态设置根元素的font-size 设备宽度/设计稿的宽度

DPR 设备像素比

移动端页面自适应

方案一 : rem js实现 css用@media

方案二 :vw+rem

100vw 将视口平分为100单位的vw

大部分按iphone6分辨率设计

将html的font-size设为100px font-size:13.3333vw

1个逻辑像素 = 2个物理像素(设备像素) DPR : 2.0

在css中导入其他css的时候使用@符号要在前面加~符号,才会解析

下拉刷新使用Vant

代理 使用VUE-CLI

组件中不能修改porps属性值(单向向下行绑定数据—单向数据流)

Vue是双向绑定 — React是单向数据流

跨域 代理 proxy

在src同级别建立一个vue.config.js文件

vue.config.js 参考vue官网vue-cli的devServer 和devServer.proxy

module.exports = {
    devServer: {
        proxy: {
            '/api': { //匹配所有以/api开头的请求接口
                target: 'http://localhost:8089', 
                ws: true,
                changeOrigin: true,
                pathRewrite:{ //重定向
                    '/^api' :''  //把以/api开头的  去掉api
                }
            },
        }
    }
  }
devServer: {
    proxy: {
        '/rng': {     //这里最好有一个 /
            target: 'http://45.105.124.130:8081',  // 后台接口域名
            ws: true,        //如果要代理 websockets,配置这个参数
            secure: false,  // 如果是https接口,需要配置这个参数
            changeOrigin: true,  //是否跨域
            pathRewrite:{
                '^/rng':''
            }
        }
    }
  }

keep-alive

有缓存的作用第一次进入的时候进行缓存

<keep-alive>
  <component :is="view"></component>
</keep-alive>

相关设置

  • include - 字符串或正则表达式。只有名称匹配的组件会被缓存。
  • exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
  • max - 数字。最多可以缓存多少组件实例。
<keep-alive include="a,b"> 
  <component :is="view"></component>
</keep-alive>

includeexclude 属性允许组件有条件地缓存。二者都可以用逗号分隔字符串、正则表达式或一个数组来表示:

<!-- 逗号分隔字符串 -->
<keep-alive include="a,b">
  <component :is="view"></component>
</keep-alive>

<!-- 正则表达式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/">
  <component :is="view"></component>
</keep-alive>

<!-- 数组 (使用 `v-bind`) -->
<keep-alive :include="['a', 'b']">
  <component :is="view"></component>
</keep-alive>

匹配首先检查组件自身的 name 选项,如果 name 选项不可用,则匹配它的局部注册名称 (父组件 components 选项的键值)。匿名组件不能被匹配。

**keep-alive有两个钩子函数activateddeactivated**

在一个组件第一次被创建的时候钩子函数执行顺序为 create=>mounted=>activated

退出的时候执行deactivated 再次进入此组件的时候只会执行activated (这就大大的优化了性能)

$nextTick

将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。它跟全局方法 Vue.nextTick 一样,不同的是回调的 this 自动绑定到调用它的实例上。

在DOM加载完成后在进行操作

异步操作改变DOM如果需要在改变DOM后对其进行操作就可以使用nextTick的回调

使用的两种方式 : Vue.nextTick() this.$nextTick()

this.$nextTick().then(()=>)//应为nextTick返回的是一个promise所以可以在后面.then()
this.$nextTick(()=>{})

实例

getFilmsBannerList().then(resp=>{
        if(resp.status==0){
          this.bannerList = resp.data
          this.$nextTick(()=>{ //在获取数据后对DOM进行渲染之后才会执行
            this.runBanner()
          })
        }
      })

Vue API

全局API

Vue.compile(str)

var res = Vue.compile('<div><span>{{ msg }}</span></div>')
new Vue({
  data: {
    msg: 'hello'
  },
  render: res.render, //编译模板字符串
  staticRenderFns: res.staticRenderFns //静态渲染
})//和下面的相等  
new Vue({
            el:"#app",
            data: {
                msg: 'hello'
            },
            template : `<div>{{msg}}</div>`,
}

Vue.observable(obj)

让一个对象可响应。Vue 内部会用它来处理 data 函数返回的对象。

选项 / 数据

data

props

propsData

只能用于new Vue()创建的实例中

创建实例时传递 props。主要作用是方便测试。

computed

计算属性

methods

方法

watch

监听

component>


相关设置

- `include` - 字符串或正则表达式。只有名称匹配的组件会被缓存。
- `exclude` - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
- `max` - 数字。最多可以缓存多少组件实例。

```js
<keep-alive include="a,b"> 
  <component :is="view"></component>
</keep-alive>

includeexclude 属性允许组件有条件地缓存。二者都可以用逗号分隔字符串、正则表达式或一个数组来表示:

<!-- 逗号分隔字符串 -->
<keep-alive include="a,b">
  <component :is="view"></component>
</keep-alive>

<!-- 正则表达式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/">
  <component :is="view"></component>
</keep-alive>

<!-- 数组 (使用 `v-bind`) -->
<keep-alive :include="['a', 'b']">
  <component :is="view"></component>
</keep-alive>

匹配首先检查组件自身的 name 选项,如果 name 选项不可用,则匹配它的局部注册名称 (父组件 components 选项的键值)。匿名组件不能被匹配。

**keep-alive有两个钩子函数activateddeactivated**

在一个组件第一次被创建的时候钩子函数执行顺序为 create=>mounted=>activated

退出的时候执行deactivated 再次进入此组件的时候只会执行activated (这就大大的优化了性能)

$nextTick

将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。它跟全局方法 Vue.nextTick 一样,不同的是回调的 this 自动绑定到调用它的实例上。

在DOM加载完成后在进行操作

异步操作改变DOM如果需要在改变DOM后对其进行操作就可以使用nextTick的回调

使用的两种方式 : Vue.nextTick() this.$nextTick()

this.$nextTick().then(()=>)//应为nextTick返回的是一个promise所以可以在后面.then()
this.$nextTick(()=>{})

实例

getFilmsBannerList().then(resp=>{
        if(resp.status==0){
          this.bannerList = resp.data
          this.$nextTick(()=>{ //在获取数据后对DOM进行渲染之后才会执行
            this.runBanner()
          })
        }
      })

Vue API

全局API

Vue.compile(str)

var res = Vue.compile('<div><span>{{ msg }}</span></div>')
new Vue({
  data: {
    msg: 'hello'
  },
  render: res.render, //编译模板字符串
  staticRenderFns: res.staticRenderFns //静态渲染
})//和下面的相等  
new Vue({
            el:"#app",
            data: {
                msg: 'hello'
            },
            template : `<div>{{msg}}</div>`,
}

Vue.observable(obj)

让一个对象可响应。Vue 内部会用它来处理 data 函数返回的对象。

选项 / 数据

data

props

propsData

只能用于new Vue()创建的实例中

创建实例时传递 props。主要作用是方便测试。

computed

计算属性

methods

方法

watch

监听

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值