Vue快查

1.关于Vue

Vue是一个构建用户界面的渐进式JS框架

构建用户界面:在合适的时间 展示合适的数据给用户
渐进式:自底向上逐层的应用,可以从简单(小乔核心库)到复杂(各类Vue插件)

特点:

  • 组件化编程(复用、方便维护):将HTML+CSS+JS整体地封装成一块
  • 声明式编码:无需直接操作DOM

命令式编码:直接操作DOM的JS原生代码

  • 虚拟DOM+Diff算法:添加数据不必全部更新,比较后直接插入

Diff算法:一种比较算法,用于更新虚拟DOM

2.配置项

1.data

//普通型
data:{
  n:1
}
//函数型
data() {
  return {
    n:1
  }
}

2.methods

方法设置

3.computed

  • computed适合处理的场景是,获得一个值或者结果,该结果受其他的依赖的影响。(一个数据受多个数据影响),计算属性是基于响应式的依赖进行缓存,而只有定义在data中的参数才是响应式的,这个得特别注意
  • 以下列代码为例–调用get()时机初次读取isAll时;isAll所依赖的数据发生改变时【其余时候直接读取第一次调用get后存在缓存中的值】
// 只有定义在data中的数据才拥有响应式
// 计算属性只有在data中获取到初始数据才有意义
computed: {
  //自定义属性值(全)
  isAll: {
    set(val) {
      // isAll的值被事件触发发生改变时, 传入改变后的值val
    },
    get() {
      //get调用的两个时机:初次读取isAll时、isAll所依赖的数据发生改变时
      //其余时get()完会存入缓存,不再重复调用get()
      return (计算原始数据,发生改变之后就是isAll的初始值)
        },
  },
  //自定义属性值(简)---仅有get()时
  isnAll(){
    return xxx
  }
},

4.watch

watch适合处理的场景是,侦听一个数的变化,当该数据变化,来处理其他与之相关数据的变化

监听器配置项
// 深度监听和立刻执行(不用写this即可获取到值:data里面的变量)
// 监听器只能起到监听数据变化的效果,不能改写数据
watch: {
  //list是要监听的对象
  list: {
    	immediate: true, // 立即执行
      deep: true, // 深度监听复杂类型内变化
      handler(newVal, oldVal) {
      // newVal是改变后的状态
      // oldVal是改变后的状态
      console.log(newVal);
    },
    },
    //仅handler时可简写
    alist(newValue,oldValue){
      xxx
  },
}

//vm创建完成,后续发现需要监视
vm.$watch("list",{xxx})

3.指令

1.数据绑定

  • v-bind=xxx:单向数据绑定 简写为 : xxx
  • v-model:value=xxx:双向数据绑定 简写为 v-model=xxx

表单收集数据中,v-model修饰符:
.lazy:失去焦点在收集数据
.number:输入的字符串转化为有效数字
.trim:输入首尾空格过滤

2.事件绑定

  • v-on:click=fn:事件绑定 简写为 @click=fn @keyup=fn @keydown=fn

事件修饰符:
.prevent:阻止默认事件 .stop:阻止事件冒泡 .once:事件只执行一次 .capture:事件捕获形式 .self:(虽然vue管理的this指向vm,但按照原生js理解为:)e.target为this时才触发
键盘事件修饰符:
.enter:回车 .delete:删除、退格 .esc:退出 .space:空格 .tab,.ctrl,.alt,.shift,.meta/win:必须配合keydown使用,以tab为例,其本身便有切换焦点的的功能 .up .down .left .right:上下左右
多个时间修饰符:
连写,例如@keydown.ctrl.y:同时按下ctrl和y触发事件

3.条件渲染

  • v-show=“true/false”:调整display确定标签是否展示 —操作Style
  • v-if=“true/false”😗*确定标签是否存在 ** —操作Node

一般用v-show,不用重复渲染页面
v-if v-else-if v-else-if … v-else 一整套在HTML结构中不允许被打断

4.列表渲染

  • v-for:列表渲染

表现形式
1.v-for=“p in persons” :key=“p.id” {{p}}
2.v-for=“(p,index) in persons” :key=“index” --遍历数组,先接收p
3.v-for=“(value,key) in Car” :key=“key” --遍历对象,先接收value
4.v-for=“(char,index) in str” :key=“index” --遍历字符,先接收char
所谓先接收,即如果遍历数组时写成 v-for=“k in persons”,则k为p

5.数据填充

  • v-text**:完全替换**标签内文本 —同innerText
  • v-html:可解析html标签 —同innerHTML—故也易受XSS攻击(假借用户之手,cookie)

6.无值指令

  • v-cloak
    • 一个属性,Vue接管容器时删除
    • 作用:结合css,解决网速慢时页面展示出未解析模板的问题
  • v-once
    • 一个属性
    • 作用:所在标签仅在初始化时动态渲染一次
  • v-model:
    • 一个属性
    • 作用:Vue将跳过所在标签的编译,效率up↑

4.底层

1.数据代理与数据劫持

1.数据代理【代理模式】模拟

通过一个对象代理另一个对象中属性的操作(读/写)
例如:下例通过obj2代理obj1,对obj2的操作最终都落到obj1上

let obj1={x:100}
let obj2={y:200}
Object.defineProperty(obj2,"x",{
  get(){
    return obj1.x;
  },
  set(val){
    obj1.x=val;
  }
})

2.Vue中的数据代理

在vue中的数据代理,实际上是**通过vm上的属性代理对_data中属性的操作 **
image.png

3.Vue中的数据劫持

在vue中的数据劫持,实际上是**劫持到vm上属性的变化,去重新解析模板,更新页面,实现响应式效果 **
image.png

4.vue中的数据代理与数据劫持(以vm.name为例)

data中的内容加工(Setter响应式,数据劫持)后,赋值给_data,然后代理(数据代理)给vm上的属性

2.Vue中的函数

  • 所有被vue管理的函数,最好写成普通函数(this指向vm或组件实例对象)
  • 所有不被vue管理的函数(定时器回调、Ajax回调、Promise回调…),最好写成箭头函数(this指向vm火组件实例对象)

3.Diff算法

在列表渲染时,通过将key与id绑定,在更新节点时使用Diff算法将真实DOM与新虚拟DOM进行比较,相同的直接复用,旧的新生成,以达到结点服用的功能

4.Vue监测数据更新的原理

1.对象中的数据

Setter监视:原理即Vue中的数据劫持
一个重要的API:
Vue.set(target,key,value) / vm.$set(target,key,value)

  • 作用:让后续追加在**_data中的数据也能实现响应式**
  • 参数:target:追加目标 key:追加名 value:追加值
  • 局限:只能给data中的响应式对象追加响应式属性,而不能操作vm与data自身
2.数组中的数据

包装数组身上常用的修改数组(直接修改自身)的方法:底层只做了两件事:1.通过原型链调用“七法” 2.重解析模板

七法:push,pop,shift,unshift,splice,sort,reserve
splice(start,deleteCount,items):
start:要开始改变数组的位置
deleteCount:要删除的元素个数  
items:要加入的元素

原理:
AE0E0261CFB0547C8B0DF14802B2A469.jpg
若不用“七法”:

  • 代码中–无法监视–无法修改
  • 控制台中(赋值修改)–可以修改但无法监视–无响应式

5.过滤器

  • 语法:
    • 注册:
      • 局部:filters:{xxx}
      • 全局:Vue.filter(name,callback)
    • 使用:{{xxx|过A|过B}} / v-bind:value=“xxx|A|B”
  • 注意项:
    • 默认只接收value,但也可以接受其他
    • 多过滤可串联
    • 过滤不改变源数据
  • 实例:
<body>
    <div id="root">
        <div>{{name}}</div>
        <div>付款:{{money | addIcon }}</div>
    </div>
</body>
<script>
    Vue.config.productionTip = false;
    // 全局注册
    Vue.filter("addIcon",(value)=>{
        return value + "元"
    })
                                    
    const vm = new Vue({
        el:'#root',
        data:{
            name:"张三",
            money:200
        },
        // 局部注册
        // filters:{
        //     addIcon(value){
        //         return value + "元"
        //     }
        // }
    })
</script>

6.生命周期

E7B183DD87FA511581465123E4A3A145.jpg

7.组件化编程

1.概念

47F88CD6CB48760308051D43D588E80E.jpg

2.概念小结

  • 组件:相当于把一整个页面拆分成一个个包含了完整html,js,css的小页面,代码复用性up↑
  • 由图可见,组件化编程分为三步:创建组件构造器(Vue.extend)并编写组件->组件注册->使用组件
  • 组件编写中的配置项:
    • name:在Vue开发者工具中可见的“组件名”,相当于一个注释,在代码中不会用到
    • template:代码块,用于放置HTML代码块,且代码块必须放置在一个根目录下
    • data():template中的数据
    • vc中methods,computed,watch等使用同vm
  • 组件注册:
    • 全局Vue.component(“xxx”,obj) /局部:components:{xxx:obj}
    • 这里的xxx才是html页面中要用到的组件名
  • Vue.component:image.pngimage.png
  • 所以,vc是可以访问到vm.__proto__上的属性和方法的

3.单文件组件

//xxx.vue
<template>
<!--HTML代码块  -->
</template>

<script>
    export default{
      data(){
        return{
          xxx
        }
      },
      methods:{
        xxx
      },
      ...
    }
</script>

<style>
/* 组件的样式  */
</style>

4.组件的引入和嵌套

1.组件的引入

ES6模块化的引入,import xxx from “xxx.vue”

2.组件的嵌套
  • 非单文件组件·本地注册:**直接在template中使用,但是
  • 单文件组件·外部引入:先import,再在此单文件组件中注册该组件,最后使用【引入,注册,使用
3.父子组件通信

父子组件通信

1.父向子传递
  • 父组件通过v-bind绑定value,子组件用props接收数据并直接使用传过来的数据绑定在了子组件vc实例上
2.子向父传递
  • 在子组件内通过 $emit触发父组件上的自定义事件并将参数传给监听器【即父组件】回调
关于vm.$emit( eventName, […args] )

ctrl+f:快速查找方法

  • 参数
    • {string} eventName 触发的事件名
    • […args] 传递给事件的参数
  • 作用: 触发当前实例上的事件。附加参数都会传给监听器回调。
  • 内部原理:

$emit也是采用了发布订阅者设计模式。

Vue.prototype.$emit = function (event: string): Component {
  const vm: Component = this
  let cbs = vm._events[event]
  if (cbs) {
    cbs = cbs.length > 1 ? toArray(cbs) : cbs
    const args = toArray(arguments, 1)
    for (let i = 0, l = cbs.length; i < l; i++) {
      try {
        // apply() 方法调用一个具有给定 this 值的函数,
        // 以及以一个数组(或一个类数组对象)的形式提供的参数。
        cbs[i].apply(vm, args)
      } catch (e) {
        handleError(e, vm, `event handler for "${event}"`)
      }
    }
  }
  return vm
}
}

根据传入的事件名从当前实例的_events属性(即事件中心)中获取到该事件名所对应的回调函数cbs,然后再获取传入的附加参数args,由于cbs是一个数组,所以遍历该数组,拿到每一个回调函数,执行回调函数并将附加参数args传给该回调。

3.实例
<body>
    <div id="root">
        <app></app>
    </div>
</body>
<script>
    Vue.config.productionTip = false;

    // 父组件
    const app ={
        name:"app",
        template:`
        <div>
            <child1 :messageToChild="message"></child1>
            <child2 @childFn="parentFn"></child2>
        </div>
        `,
        data() {
            return {
                message:"Message from app",
            }
        },
        methods: {
            parentFn(message){
                this.getMessage=message;
            }
        },
    }

    // 子组件1--父向子传递信息
    const child1 = {
        name:"child1",
        template:`
        <div>
            <p>我是子组件1</p>
            <p>{{messageToChild}}</p>
        </div>
        `,
        props:['messageToChild']
    }

    // 子组件2--子向父传递信息
    const child2 = {
        name:"child2",
        template:`
        <div>
            <p>我是子组件2</p>
            <p>{{messageInChild}}</p>
            <!-- <button @click="submit"></button> -->
        </div>
        `,
        data() {
            return {
                messageInChild:"Message from child"
            }
        },
        // methods:{
        //     submit(){
        //         this.$emit("childFn",this.messageInChild)
        //     }
        // }
        mounted() {
            this.$emit("childFn",this.messageInChild)
        },
    }
    // 全局注册
    Vue.component("app",app);
    Vue.component("child1",child1);
    Vue.component("child2",child2);

    const vm = new Vue({
        el:'#root',
        // 组件递归中(即直接在template里面嵌套子组件),不能使用局部注册
        // components:{
        //     app,
        //     child1,
        //     child2
        // }
    })
    
    console.log(vm);
</script>

5.单文件组件的开发

  • 组件间的引入和嵌套见4
  • 随后所有的组件交由一个大的组件App.vue管理;然后新建一个main.js,用于创建vm实例并使用App大组件;最后在index.html实际执行页面中引入main.js即可

6.实例

1.非单文件组件–本地注册
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="../vue2/vue.js"></script>
    <title>Document</title>
</head>
<body>
    <div id="root">
        <!-- 编写组件标签 -->
        <student></student>
        <hr>
        <school></school>
    </div>
<script>
    Vue.config.productionTip = false;
            
    // 创建学生组件
    const student=Vue.extend({
        name:'studentTagInVueDevelopment',
        template:`
        <div>
            <h1>学生姓名:{{name}}</h1>
            <h1>学生年龄:{{age}}</h1>
        </div>
        `,
        data() {
            return {
                name:"张三",
                age:18
            }
        },
    })
    //创建学校组件,简写方式不用Vue.extend,直接大括号即可
    const school = {
        name:'schoolInVueDevelopment',
        template:`
        <div>
            <h1>{{name}}</h1>
            <h1>{{address}}</h1>
            <hr>
            <school-door></school-door>
        </div>
        `,
        data() {
            return {
                name:"atGuigu",
                address:"北京昌平"
            }
        },
    }
    // 创建学校大门组件,归属于学校组件
    const door =  {
        // name相当于Vue开发者工具中的“注释”
        name:'doorInVueDevelopment',
        template:`
        <div>
            <h1>南大门:{{south}}</h1>
            <h1>北大门:{{north}}</h1>
        </div>
        `,
        data() {
            return {
                south:'智行街185号',
                north:"天星路173号"
            }
        },
    }
    //组件全局注册,这里注册的名字才是要用的名字
    Vue.component('student',student);
    Vue.component('school',school);
    Vue.component('school-door',door);
  
    const vm = new Vue({
        el:'#root',
        // 组件局部注册
        // components:{
        //     student:student,
        //     school
        // }           
    })
    console.log(student);
</script>
</body>
</html>

2.单文件组件–组件的引入与管理

注意:单文件组件的开发只能在脚手架环境中才能正常执行

<!-- door,school的子组件 -->
<template>
    <div>
        {{ address }}
    </div>
</template>


<script>
    export default{
        data() {
            return {
                address:"北大门"
            }
        },
    }
</script>
<!-- school,受App组件管理 -->
<template>
    <div id="school">
        name:{{ name }}
        address: <door></door>
    </div>
</template>

<script>
    import door from './door.vue';
    
    export default{
        data() {
            return {
                name:"小天星幼儿园"
            }
        },
        components:{
            door
        }
    }
</script>
<!-- stu,受App组件管理 -->
<template>
    <div>
        {{ options }}
    </div>
</template>

<script>
    export default{
        data() {
            return {
                options:"stu"
            }
        },
    }
</script>
<!-- App,所有组件的总管,一个大组件 -->
<template>
    <div>
        <school></school>
        <stu></stu>
    </div>
</template>

<script>
    import school from "./school.vue"
    import stu from "./stu.vue"

    export default{
        components:{
            school,
            stu
        }
    }

</script>
<!-- mian.js,用于创建vm实例并使用App大组件 -->
import App from "./App.vue"

new Vue({
    el:"#root",
    template:`<App></App>`,
    components:{App}
})
// index.html,页面实际执行者
<body>
    <!-- 准备一个root容器 -->
    <div id="root"></div>
    <!-- 引入vue,防止main.js无vue可用 -->
    <script src="../../vue2/vue.js"></script>
    <!-- 引入main.js -->
    <script src="./main.js"></script>
</body>

8.Vue简单应用

1.Vue样式绑定

数据单向绑定的应用

1.绑定Class样式
//字符串写法
:class="mood" ==>data内:mood:"xxx"
//数组写法
:class="arr"  ==>data内:arr:["a","b","c"]
//对象写法
:class="obj"  ==>data内:obj:{a:false,b:false,c:true}

2.绑定style样式

原CSS短横杠形式key要改用驼峰命名法,如font-size==>fontSize

//对象写法
:class="styleObj"  ==>data内:obj:{fontSize:'40px',...}

9.Vue-Router

  • 用 Vue + Vue Router 创建单页应用非常简单:
    • 通过 Vue.js,我们已经用组件组成了我们的应用
    • 当加入 Vue Router 时,我们需要做的就是将我们的组件映射到路由上,让** Vue Router 知道在哪里渲染**它们。

10.Vue-cli

1.脚手架目录结构

//带*号的:需要才用,其余的目录文件是必须的
├── node_modules 
├── public
│   ├── favicon.ico: 页签图标
│   └── index.html: 主页面
├── src
│   ├── assets: 存放静态资源
│   │── component: 存放组件
│   │── router:存放路由
│   │── *mixin:存放混入js
│   │── views:存放子页面(组件)
│   │── App.vue: 汇总所有组件
│   │── main.js: 入口文件
├── .gitignore: git版本管制忽略的配置
├── babel.config.js: babel的配置文件//babel:用于es6转es5
├── package.json: 应用包配置文件 
├── README.md: 应用描述文件
├── package-lock.json:包版本控制文件
├── vue.congfig.js:可编写的更改的配置文件//文档参考:https://cli.vuejs.org/zh/config/

2.命令,Vue库组成,render函数,ref标识,props配置项

  • dev是vue cli2的默认执行命令,serve是vue cli4的默认执行命令
  • vue包括两部分:核心库+模板解析器
  • render函数:防止引入的是残缺版的vue,作用是生成template模板
    • render:h=>h(App),将APP组件放入容器中
  • ref属性:vue中对元素的标识,可以标识原生dom元素,也可以标识组件 this.$refs.xxx,前者替代id,后者可以得到组件的实例对象vc
    • 标识原生dom元素:  image.png,获取dom元素
    • 标识组件:image.png,获取vc实例
  • props配置项:优先级高于data,作用就是父向子通信

3.mixin混入

  • 作用:多个组件共享一套配置,以分发 Vue 组件中的可复用功能
  • 形式:局部注册:mixins:[mixin1,mixin2,…] /全局注册:Vue.mixin(mixin1)
  • 局部注册使用方法:
    • 将要复用的js部分单独挑出来
    • 单独写入一个js文件中并export暴露出来
    • 各个组件内import引入
    • mixins配置项中注册该混入
  • 全局注册使用方法:
    • 前二相同
    • 不必再在各个组件中引入,直接在main.js中import并全局注册
  • 注意:
    • 普通配置项/属性 混入与自身冲突时,选择合并,即不同名的合并,同名的则以自身为主
    • 钩子函数混入与自身冲突时,来者不拒且混入钩子先于自身钩子
    • 全局注册后,所有的vc以及vm都将包含有这个混入对象
  • 实例:
//mixin.js
export const showName = {
    methods: {
        showName(){
            alert(this.name)
        }
    }
}
export const data = {
    data() {
        return {
            name:"name from mixin",
            num:3
        }
    }
}
//局部注册--vc
import { showName } from '@/mixin/mixin';
export default{
	  name:"School",
    mixins:[showName]
}
//全局注册--vm,main.js
import { data } from './mixin/mixin'
Vue.mixin(data)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值