vue2.0系统研究

131 阅读6分钟

vue数据响应原理

1:原理

原理图:

image.png

从MVVM模式

image.png

侵入式和非侵入式(react和小程序直接调用方法改变)

image.png

image.png

2:object.defineProperty()方法

      let obj={

      }
      Object.defineProperty(obj,'name',{
        value:'名字',
        writable:true,//是否可写
        enumerable:true, // 是否可枚举
        configurable:true // 是否可以删除
      })
      Object.defineProperty(obj,'age',{
        value:18,
        writable:true,//是否可写
        enumerable:true, // 是否可枚举【是否可以遍历这属性】
        configurable:true // 是否可以删除
      })

      console.log(obj)
    defineReactiveFun(){
       let obj={sex:'男'}
      function defineReactive (data,key,val){   
        Object.defineProperty(data,key,{
          enumerable:true, // 是否可枚举(遍历到这属性)
          configurable:true,
          get(){
            console.log('访问data属性',key)
            return val;
          },
          set(newVal){
            console.log('改变data属性',key,newVal)
            val=newVal
          }
        })
      }
      
      new Promise(function(resolve,reject){
         defineReactive(obj,'age',18)
         resolve()
      }).then(()=>{
        obj.age++
        console.log(obj)
        console.log(obj.age) //19
      })
     
    },

3:响应式处理(对象)

image.png

image.png

image.png

defineProperty.vue

    
    defineReactiveFun(){
      var obj={
        a:{
          m:{
            n:5
          }
        },
        b:{
          b1:'dsfdf'
        }
      }
    console.log(obj)
    observe(obj)
    obj.a.m.n=6
     
    },

Observe.js



//  创建observer 函数注意函数的没有r
export default function observe(value) {
    if (typeof value != 'object') return;
    var ob;
    if (typeof value.__ob__ !== 'undefined') {
        ob = value.__ob__
    } else {
        ob = new Observer(value)
    }
    return ob;

}

Observer.js

import defineReactive from '../vueReactive/defineReactive.js'

export default class Observer {
    constructor(value) {

        // 注意:下面的this 是构造函数的this。不是表示类的本身,而不是实例 
        def(value, '__obj__', this, false)
        console.log('我是Observer构造器', value);
        this.walk(value)
    }
    walk(value) {
        for (let k in value) {
            defineReactive(value, k)
        }
    }
}

function def(obj, key, value, enumerable) {
    Object.defineProperty(obj, key, {
        value,
        enumerable,
        writable: true,
        configurable: true
    })
}

defineReactive.js

import observe from '../vueReactive/Observe'
export default function defineReactive(data, key, val) {
    console.log('我是defineReactive', key)
    if (arguments.length == 2) {
        val = data[key];
    }
    // 子元素要进行observe 至此形成递归,这个递归不是函数自己调用自己,而是多个函数,类循环调用
    let childOb = observe(val)

    Object.defineProperty(data, key, {
        enumerable: true, // 是否可枚举(遍历到这属性)
        configurable: true,
        get() {
            console.log('访问data属性', key)
            return val;
        },
        set(newVal) {
            console.log('改变data属性', key, newVal)
            val = newVal

            childOb = observe(newVal) // 设置了新值,这个新值也要被observe
        }
    })
}

3:响应式处理(数组)

一:什么是vue

1:构建用户界面

用vue 往html页面中填充数据

2:框架

vue 指令、组件(对复杂的ui结构复用)、路由、vuex

二:vue特性:数据驱动视图和双向数据绑定

1 数据驱动视图

image.png

2: 双向数据绑定

在网页中:from标题复制采集数据 ajax负责提交数据

image.png

三MVVM框架

1:结构

image.png

2:原理

image.png

3:代码与结构的关系

image.png

四:指令与过滤器

1:指令

A: 内容指令:v-html {{}} v-text

image.png

B: 属性指令:v-bind

<div :data-titke="属性指令"></div>
<img :src="srcStr"/>

C: 事件指令 v-on:click 或者@click

<button @click="count++">count is: {{ count }}</button>

$event

    <button @click="clickFun(1,$event)">button</button>
    clickFun(n,e){
      console.log(e)
      e.target.innerHTML='点击'
    }

事件修饰符

image.png

prevent
<a href="www.baidu.com" @click.prevent="tiaoFun">跳转</a>
stop
  <div @click="divFun1">
        阻止冒泡1
     <div @click.stop="divFun2">阻止冒泡2</div>
  </div>
按键修饰符

image.png

按键修饰:<input @keyup="keyupFun">

D: 双向绑定指令 v-model

image.png

双向数据绑定修饰符

image.png

image.png

E: 条件渲染指令 v-if 和v-show

v-if 和v-else-if /v-else

  <div v-if="n1">sdf</div>
  <div v-else-if="n2">sdf</div>
  <div v-else>sdf</div>

F: 列表渲染指令

image.png

2:过滤器【vue3.0已废除】

image.png

私有过滤器和全局过滤器

image.png

连续调用多个过滤器

image.png

五:侦听器

六:计算属性

**只要计算属性中;依赖的的数据源变化,则计算属性会自动重新求值:如:下面的 r g b ** image.png 计算属性改造:

image.png

七:axios

结合 ansync、await/和解构赋值 代码美滋滋

八:组件

image.png

组件中的data为啥是个函数不是对象?

image.png

我们可以发现当我们使用组件的时候,虽然data是在构造器的原型链上被创建的,但是实例化的component1和component2确是共享同样的data对象,当你修改一个属性的时候,data也会发生改变,这明显不是我们想要的效果。

当我们的data是一个函数的时候,每一个实例的data属性都是独立的,不会相互影响了。你现在知道为什么vue组件的data必须是函数了吧

九 vscode中常用插件

1: @路径提示插件

image.png

image.png

打开vscode settings.json添加一下代码

    "path-autocomplete.extensionOnImport":true,
    "path-autocomplete.pathMappings": {
      "@":"${folder}/src"
    }

2:标签回阔自动生成

image.png

十:简写计较方法案例

累加

image.png image.png

十一:注册组件

注册全局组件

image.png

注册私有子组件

image.png

十二:props 接受参数

1:props只读的,子组件不能改父组件传过来的的值

deep 父组件修改组件的样式

image.png

十三:vue 单应用页面渲染原理步骤

image.png

十三:vue 组件生命周期

阶段结构图

image.png

分析周期流程图

image.png

image.png

image.png

image.png

十四:兄弟组件数据共享eventBus.js

image.png

image.png

十五:ref使用

获取当前组件Dom

获取子组件,然后调用子组件的方法

image.png

this.$nextTick(cb)

image.png

十六:常见的数组方法(购物车)

some

image.png

every

image.png

reduce方法

image.png

image.png

十六:计算属性computed

image.png

十七: 动态组件component

image.png

十八:keep-alive

image.png

deactivated、activted

image.png image.png

include 属性指定缓存组件

image.png

exclude 排除项;主要 不能和include同时使用

image.png

十九:组件的name

image.png

image.png

二十:插槽

image.png

image.png

image.png

二十一:自定义指令

私有

image.png

image.png

upadate(更新绑定的指定一的值)

image.png

image.png

优化简写更新

image.png

image.png

全局

image.png

image.png

二十二:main.js的提示

image.png

二十三:esline作用和 vscode工具格式化

image.png

image.png

image.png

二十四:路由

hash: location.hash

image.png

前端路由工作方式

image.png

模拟前端路由 window.onhashchange

image.png

image.png

vue-router官方插件

安装与使用

image.png

小细节注意:

在进行模块化导入的时候,如果给定文件夹,则默认导入这个文件夹下,名字叫做index.js文件

image.png

router文件夹的拓展

为了部署大项目,不要把所有的路由都放到index.js ,可以拆分多个js

image.png

router的占位符 router-view

image.png image.png

路由重定向redirect

image.png

嵌套路由

image.png image.png

image.png

image.png

动态路由 :注意获取的是$route 是不带r的

image.png image.png

this.$route是路由的参数对象
this.$router是路由的导航对象

动态路由规则开启props传参

image.png

路径参数和查询参数 拓展:fullpath 和query

1:在hash地址中 /后面的参数项,叫做路径参数项,通过this.$route.params 获取参数
  /home/1
2::在hash地址中 ?后面的参数项  叫做查询参数,通过this.$route.query 来获取参数
 /home?id=1&sel=2

image.png

路由导航跳转方式

1:声明式导航

image.png

image.png

2:编程式导航 push replace go

image.png

image.png image.png

1):go 的简写 router.back()router.back() router.forward()

image.png

image.png

Vue路由传参详解(params 与 query)

params 传参类似于网络请求中的 post 请求,params 传过去的参数不会显示在地址栏中(但是不能刷新)。params 只能配合 name 使用,如果提供了 path,params 会失效。

query 传参类似于网络请求中的 get 请求,query 传过去的参数会拼接在地址栏中(?name=xx)。query 较为灵活既可以配合 path 使用,也能配合 name 使用(亲测可用)。

//query方式
<router-link :to="{path: '/linkTo', query: {name:'ming', age: 18 }}"> 
    <button>跳转</button> 
</router-link> 

//params方式 
<router-link :to="{name: 'linkTo', params: {name:'ming', age: 18 }}">
    <button>跳转</button> 
</router-link>
// 以query方式接收参数:【query传递数据是通过URL传递的,类似ajax中的get方式】
console.log(this.$route.query.name);    // ming
console.log(this.$route.query.age);     // 18
 
// 以params方式接收参数:【params方式,类似ajax中的post方式】
console.log(this.$route.params.name);    // ming
console.log(this.$route.params.age);     // 18

//query方式
<button @click="jump1">跳转</button>
jump1() {  
	this.$router.push({
		path: '/linkTo',
		query: {
			name: "ming",
			age: 18
		}
	});
}
//⚠️注:如果要传递的参数很长时,请用params方式,因为query方式是通过URL传递的,而URL传参数长度是有限制的哦!!

//params方式
<button @click="jump2">跳转</button>

open2() {
	this.$router.push({
		name: "abolinkTout", // ⚠️注:这里不能用path路径,只能用name【请对照router.js中的路由规则中的name项】,否则取不到传过去的数据
		params: {
			name: "ming",
			age: 18
		}
	});
}

//⚠️注:在传递参数时,用什么方式传参,就用什么方式接收!!
// 以query方式接收参数:【query传递数据是通过URL传递的,类似ajax中的get方式】
console.log(this.$route.query.name);    // ming
console.log(this.$route.query.age);     // 18

// 以params方式接收参数:【params方式,类似ajax中的post方式】
console.log(this.$route.params.name);   // ming
console.log(this.$route.params.age);    // 18
 
// this.$route 路由信息对象
console.log(this.$route);

监听路由参数的变化:商品详情页面点击切换商品

image.png

image.png

参考链接:

juejin.cn/post/698535…

二十五:导航守卫

1:全局前置守卫 router.beforeEach()

image.png

守卫形参 to from next

image.png

next 3钟调用方式

image.png

2: 全局解析守卫router.beforeResolve 注册一个全局守卫

3:全局后置钩子 afterEach

这些钩子不会接受 next 函数也不会改变导航本身:

router.afterEach((to, from) => {
  // ...
})

4:路由独享的守卫

image.png

5: 组件内的守卫-

  • beforeRouteEnter
  • beforeRouteUpdate (2.2 新增)
  • beforeRouteLeave

image.png

6:完整的导航解析流程

  1. 导航被触发。
  2. 在失活的组件里调用 beforeRouteLeave 守卫。
  3. 调用全局的 beforeEach 守卫。
  4. 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
  5. 在路由配置里调用 beforeEnter
  6. 解析异步路由组件。
  7. 在被激活的组件里调用 beforeRouteEnter
  8. 调用全局的 beforeResolve 守卫 (2.5+)。
  9. 导航被确认。
  10. 调用全局的 afterEach 钩子。
  11. 触发 DOM 更新。
  12. 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传

二十六: 路由元信息

22c119932bc0e8de12446c5d46289ec.png

22c119932bc0e8de12446c5d46289ec.png

二十七:Es6模块化

1:默认导入与导出

image.png

2 按需导入与导出

image.png image.png

3:直接导入并执行

9c1383e7e4e56e576e465f3a9ca11c6.jpg

二十八pormise

第三方包读取文件 then-fs

npm install then-sf 按照第三包

image.png

按顺序执行

image.png

catch捕获错误

image.png

promise all 等待所有promise执行成功后执行

image.png

promise race 只要一个promise返回成功就执行

image.png

二十九:async 和await

a:基本用法

image.png

b:注意事项

image.png

三十 eventLoop

image.png

A: 同步任务和异步任务

Event Loop即事件循环,是指浏览器或Node的一种解决javaScript单线程运行时不会阻塞的一种机制,也就是我们经常使用异步的原理。

image.png

1:案例

image.png

B:宏任务和薇任务

image.png

image.png

image.png

案例1:

image.png

案例2

image.png

三十一:sass 和scss区别

1:异同:简言之可以理解scss是sass的一个升级版本,完全兼容sass之前的功能,又有了些新增能力。语法形式上有些许不同,最主要的就是sass是靠缩进表示嵌套关系,scss是花括号

image.png

2 scss功能很强大的样子,能做运算、写函数啥的,但是我只是作为语法糖用而已,只看了些基础功能