vue 组件以字符串插入_Vue开发实战笔记基础理论

属性

自定义属性:组件props中声明的属性原生属性:没有声明的属性,默认自动挂载到组件根元素上,设置inheritAttrs为false可关闭自动挂载特殊属性:挂载到组件根元素上,支持字符串、对象、数组等多种语法

事件

普通事件

@click @input @change @xxx等事件

this.$emit('eventName'...)出发

修饰符事件

@input.trim @click.stop @submit.prevent 等

一般用于原生HTML元素,自定义组件需要自行开发支持

插槽

普通插槽

slot="xxx">...

v-slot:xxx>...

作用域插槽

slot="xxx" slot-scope="props">...

v-slot:xxx="props">...

属性、事件、插槽完全都可以通过属性解决,大属性的概念

双向绑定与单项数据流

双向绑定:model与view互相更新 单项数据流:model更新view

  • Vue是单项数据流,非双向绑定

  • Vue的双向绑定不过是语法糖

  • Object.defineProperty是用来做响应式更新的,和双向绑定没关系

如何实现双向绑定(语法糖)

v-model="phoneInfo"

:zip-code.sync="zipCode"

/>

:phone-info="phoneInfo"

@change="val=>(phoneInfo = val)"

:zip-code.sync="zipCode"

@update:zipCode="val=>(zipCode = val)"

/>

虚拟Dom与Key属性

JQuery:Event ===> Element Vue:Event ====> State ====> Element

Virtual DOM

f0d329d6f592916dcdcecba8852ce7eb.png

Virtual DOM Diff(对比同层节点比较):

6bfe56e3feb0a428b0e65f1e20a8380d.png

如果节点类型不同,直接干掉前面的节点,再创建并插入新的节点,不会再比较这个节点以后的子节点了。

如果节点类型相同,则会重新设置该节点的属性,从而实现节点的更新。

  • 场景1:移动

     d5862ae968b92edb04fade9635d7c776.png

  • 场景2:删除后新建

     17b61f5198a74e1585bea6a52582a297.png

  • 场景3:删除后新建

     ce988d5d2da6ee56af75230396a60b98.png

  • 场景4:更新删除新建(无Key)

     af1bf459a212bfc7cfffaf93290c6016.png

  • 场景5:移动(有Key) 

    699e009f472e91c1b7c6d38c1d621b32.png

  • 场景6:插入(有Key)

     e2d775f92e690ad47cfffa6a6409055f.png

组件的数据来源分类

  • 来自父元素的属性

  • 来自组件自身的状态

  • 来自状态管理器,如vuex,Vue.observable

计算属性及侦听器

计算属性 computed
  • 减少模版中计算逻辑

  • 数据缓存

  • 依赖固定的数据类型(响应式)

侦听器 watch
  • 更加灵活,通用

  • watch中可以执行任何逻辑,如函数节流、Ajax异步获取数据,甚至操作DOM

computed VS watch
  • computed能做的,watch都能做,反之则不行

  • 能用computed的尽量用computed

函数式组件

  • functional:true

  • 无状态、无实例、没有this上下文、无生命周期

export default {

name: 'functional-button',

functional: true,

render(createElement, context) {

return createElement('button', 'click me')

}

}

<template>

<FunctionalButton>

click me

FunctionButton>

template>

Vue自定义指令

生命周期
  • bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。

  • inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。

  • update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新。

  • componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。

  • unbind:只调用一次,指令与元素解绑时调用。

案例

Vue.directive('focus', {

// 当被绑定的元素插入到 DOM 中时……

inserted: function (el) {

// 聚焦元素

el.focus()

}

})

<input v-focus>

template和JSX的对比以及它们的本质

template

  • 模版语法(HTML的扩展)

  • 数据绑定使用Mustache语法(双大括号)

  • 优点:学习成本低、大量内置指令简化开发、组件作用域CSS

  • 缺点:灵活性低

Message:{{ msg }}

JSX

  • Javascript 的语法扩展

  • 数据绑定使用单引号

  • 灵活灵活灵活

Message:{ this.msg }

template & JSX都是语法糖

Q&A

  1. 子组件为何不可以修改父组件传递的Prop,如果修改了,Vue是如何监控到属性的修改并给出警告的?

Vue是单项数据流的。Object.defineProperty()

  1. this.$emit的返回值是什么?

返回值是 this

如果需要需要返回值可以使用回调参数

  1. 相同名称的插槽是合并还是替换

替换。

  1. 为什么不能用index作为key?

更新DOM性能问题

会引入状态bug问题(因为array改变后,index会动态的相应改变)

  1. 数组有哪些方式支持响应式更新,如不支持如何处理,底层原理如何实现的?

- 支持:push、pop、shift、unshift、splice、sort、reverse

- 不支持:filter、concat、slice

- 原理同样使用Object.defineProperty对数组方法进行改写

  1. 进行节流改造,即直到用户停止输入超过500毫秒后才更新 fullName

watch:{

firstName:function(val){

clearTimeout(this.firstTimeout);

this.firstTimeout = setTimeout(()=>{

this.fullName = val + '"" + this.lastName

},500)

}

}

只能用watch,无法使用computed

进阶生态

在Vue中使用vuex

//main.js

const store = new Vuex.Store({

state:{

count:0

},

mutations:{

INCREMENT(state){

state.count++

}

},

actions:{

increment(commit){

setTimeout(() => {

commit('INCREMENT')

}, 1000)

}

},

getters:{

doubleCount(state){

return state.count+2

}

}

})

//App.vue

<template>

<div id="app">

{{count}}

<br />

{{$store.getters.doubleCount}

<button @click="$store.commit('INCREMENT')">count++button>

<button @click="$store.dispatch('increment')">count++button>

div>

template>

...

computed:{

count(){

return this.$store.state.count

}

}

...

vuex核心概念及底层原理

  • State:state类似与组件中的data数据,而data只仅局部使用于该组件中,state数据是全局的可以再任何一个组件使用,并且我们可以在单个组件中修改state的数据。

  • Mutations:mutations 类似于组件里面的methods在mutations里面可以对state的数据进行修改。mutations必须是同步的。同步的意义在于这样每一个 mutation 执行完成后都可以对应到一个新的状态(和 reducer 一样),这样 devtools 就可以打个 snapshot 存下来。

  • Actions:actions 只是一个架构性的概念,并不是必须的,说到底只是一个函数。区分 actions 和 mutations 并不是为了解决竞态问题,而是为了能用 devtools 追踪状态变化。actions可以包含任意异步操作。

  • Getters: getters存放公共函数供组件调用,类似于组件中的过滤函数computed或者filters,缓存state的数据。

  • Module:Vue.set动态添加state到响应式数据中

实现原理(响应式数据)

import Vue from 'vue'

const Store = function Store (options={}){

const {state={},mutations={}} = options;

this._vm = new Vue({ // 将state放在Vue的data下,就变成了响应式的数据

data:{

$$state: state

}

})

this._mutations = mutations

}

Store.prototype.commit = function(type,payload){

if(this._mutations[type]){

this._mutations[type](this.state,payload)

}

}

Object.defineProperties(Store.prototype,{ // 将state的get重写,每次get值的时其实是访问_vm实例下state 的值

state:{

get:function(){

return this._vm._data.$$state

}

}

})

vuex辅助函数

  • State ---- this.$store.state.xxx ---- mapState 取值

  • Getter ---- this.$store.getters.xxx ---- mapGetters 取值

  • Mutation ---- this.$store.commit('xxx') ---- mapMutations 取值

  • Action ---- this.$store.dispatch('xxx') ---- mapActions 取值

computed: mapState({

products: state => state.products

})

// 等价于

computed: {

products(){

return this.$store.state.products

}

}

methods:mapAction('cart',{

'addProductToCart'

})

// 等价于

methods;{

addProductToCart(product){

this.$store.dispatch('cart/addProductToCart',product)

}

}

Vue-Router的使用场景

解决的问题
  • 监听URL的变化,并在变化前后执行相应的逻辑

  • 不同的URL对应不同的组件

  • 提供多种方式改变URL的API(URL的改变不能导致浏览器刷新)

路由类型以及底层原理

类型
  • hash模式:丑,无法使用锚点定位

  • history模式:需要后端配合,IE9不兼容(可使用强制刷新处理)

底层原理

5496d1072b2acd2a27409568224bd30a.png

Nuxt

SPA模式缺点
  • 不利于SEO 服务端渲染 SSR

  • 首屏渲染时间长 预渲染 Prerendering

Nuxt的作用
  • 静态站点

  • 动态渲染

  • 简化配置

SSR流程图

06bf12aba01afa2aacaa7b665395013a.png

单元测试的使用

使用方式
  • jest or mocha

  • @vue/test-utils

  • sinon

*该笔记基于 Vue开发实战课程 整理

来自Jerry的blog

欢迎扫码看看这个 Flutter 课程

87eedb264b33812a03a9b0ca76343aa5.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值