Vue 全部知识点复习

Vue2.0

MVC、MVVM

MVC

MVC 模式同时提供了对 HTML、CSS 和 JavaScript 的完全控制。
Model(模型)是应用程序中用于处理应用程序数据逻辑的部分。
通常模型对象负责在数据库中存取数据。
View(视图)是应用程序中处理数据显示的部分。
通常视图是依据模型数据创建的。
Controller(控制器)是应用程序中处理用户交互的部分。
通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。

  • 图示

    • M

      • 模型(数据层如数据库)
    • V

      • 视图(视图层、HTML页面)
    • C

      • 控制器(业务逻辑层)
  • 优点

    • 耦合性低

      视图层和业务层分离,这样就允许更改视图层代码而不用重新编译模型和控制器代码,同样,一个应用的业务流程或者业务规则的改变只需要改动MVC的模型层即可。因为模型与控制器和视图相分离,所以很容易改变应用程序的数据层和业务规则。
      模型是自包含的,并且与控制器和视图相分离,所以很容易改变应用程序的数据层和业务规则。如果把数据库从MySQL移植到Oracle,或者改变基于RDBMS数据源到LDAP,只需改变模型即可。一旦正确的实现了模型,不管数据来自数据库或是LDAP服务器,视图将会正确的显示它们。由于运用MVC的应用程序的三个部件是相互独立,改变其中一个不会影响其它两个,所以依据这种设计思想能构造良好的松耦合

    • 重用性高

      随着技术的不断进步,需要用越来越多的方式来访问应用程序。MVC模式允许使用各种不同样式的视图来访问同一个服务器端的代码,因为多个视图能共享一个模型,它包括任何WEB(HTTP)浏览器或者无线浏览器(wap),比如,用户可以通过电脑也可通过手机来订购某样产品,虽然订购的方式不一样,但处理订购产品的方式是一样的。由于模型返回的数据没有进行格式化,所以同样的构件能被不同的界面使用。例如,很多数据可能用HTML来表示,但是也有可能用WAP来表示,而这些表示所需要的命令是改变视图层的实现方式,而控制层和模型层无需做任何改变。由于已经将数据和业务规则从表示层分开,所以可以最大化的重用代码了。模型也有状态管理和数据持久性处理的功能,例如,基于会话的购物车和电子商务过程也能被Flash网站或者无线联网的应用程序所重用。

    • 生命周期成本低

      MVC使开发和维护用户接口的技术含量降低。

    • 部署快

      使用MVC模式使开发时间得到相当大的缩减,它使程序员(Java开发人员)集中精力于业务逻辑,界面程序员(HTML和JSP开发人员)集中精力于表现形式上。

    • 可维护性高

      分离视图层和业务逻辑层也使得WEB应用更易于维护和修改。

    • 有利软件工程化管理

      由于不同的层各司其职,每一层不同的应用具有某些相同的特征,有利于通过工程化、工具化管理程序代码。控制器也提供了一个好处,就是可以使用控制器来联接不同的模型和视图去完成用户的需求,这样控制器可以为构造应用程序提供强有力的手段。给定一些可重用的模型和视图,控制器可以根据用户的需求选择模型进行处理,然后选择视图将处理结果显示给用户。

  • 缺点

    • 没有明确的定义
    • 不适合小型,中等规模的应用程序
    • 增加系统结构和实现的复杂性
    • 视图与控制器间的过于紧密的连接
    • 视图对模型数据的低效率访问
    • 一般高级的界面工具或构造器不支持模式

MVVM

MVVM是Model-View-ViewModel的简写。它本质上就是MVC 的改进版。MVVM 就是将其中的View 的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开。当然这些事 ViewModel 已经帮我们做了,它可以取出 Model 的数据同时帮忙处理 View 中由于需要展示内容而涉及的业务逻辑。

  • MVVM(Model–View–Viewmodel)是一种软件架构模式

    • M

      • 模型

        • 数据模型与持久化抽象模型。数据模型很好理解,就是从服务器拉回来的JSON数据。而持久化抽象模型暂时放在Model层,是因为MVVM诞生之初就没有对这块进行很细致的描述。按照经验,我们通常把数据库、文件操作封装成Model,并对外提供操作接口。(有些公司把数据存取操作单拎出来一层,称之为DataAdapter层,所以在业内会有很多MVVM的变种,但其本质上都是MVVM)
    • V

      • 视图

        • 视图展示。包含UIView以及UIViewController,View层是可以持有ViewModel的。
    • VM

      • 视图模型

        • 视图适配器。暴露属性与View元素显示内容或者元素状态一一对应。一般情况下ViewModel暴露的属性建议是readOnly的,至于为什么,我们在实战中会去解释。还有一点,ViewModel层是可以持有Model的。
    • Binder

      • MVVM的灵魂。可惜在MVVM这几个英文单词中并没有它的一席之地,它的最主要作用是在View和ViewModel之间做了双向数据绑定。如果MVVM没有Binder,那么它与MVC的差异不是很大。
  • 优点

    • 低耦合
    • 可重用性
    • 独立开发
    • 可测试
  • 缺点

    • 调用复杂度增加
    • DEBUG困难
    • 数据双向绑定不利于View部分的代码复用
    • 类会增多

环境搭建

单页面应用

  • 直接引用CDN链接

使用Cli搭建本地开发

  • 1、全局安装cli

    • npm install -g @vue/cli
      yarn global add @vue/cli
  • 2、初始化项目

    • vue create hello-world
  • 3、进入项目

    • cd hello-world
  • 4、安装依赖

    • npm/ cnpm install
      yarn install
  • 5、启动项目

    • npm run serve
      yarn run serve / yarn serve

生命周期

beforeCreate

  • 在实例初始化之后,数据观测(data observer)和event/watcher 事件配置之前调用

    • el (DOM) // undefined
      data // undefined
      message // undefined

created

  • 实例已经已经创建完成之后被调用。在这一步,实例一完成了以下配置:数据观测(data observer), 属性和方法的运算,watch/event 事件回调,但是挂载阶段还未开始,$el 属性目前还是undefined

    • el (DOM) // undefined
      data // 已被初始化
      message //已被初始化

beforeMount

  • 在挂载开始直接被被调用;相关的render韩式首次被调用。该钩子在服务器端渲染期间不被调用

    • el (DOM) // 已被初始化
      data // 已被初始化
      message //已被初始化

mounted

  • el 被薪创建的vm. e l 替 换 , 并 挂 载 到 实 例 上 去 之 后 调 用 该 钩 子 , 如 果 r o o t 实 例 挂 载 了 一 个 文 档 内 元 素 , 当 m o u n t e d 被 调 用 时 v m . el 替换,并挂载到实例上去之后调用该钩子,如果root 实例挂载了一个文档内元素,当mounted 被调用时 vm. elrootmountedvm.el 也在文档内。

    • el (DOM) // 已被初始化
      data // 已被初始化
      message //已被初始化

beforeUpdate

  • 数据更新时调用,发生在虚拟DOM重新渲染和打补丁之前。你可以在这个钩子中进一步改变状态,这不会触发附加的重渲染过程。
    该钩子在服务器渲染期间不被调用

updated

  • 由于数据更改导致的虚拟DOM 重新渲染和打补丁,在这之后会调用该钩子。
    当这个钩子被调用时,组件DOM 已经更新,所以你现在可以之心依赖于DOM的操作,然而在大多数情况下,你应该避免在此期间更改状态,因为这可能会导致更新无限循环。
    该钩子在服务器端渲染期间不被调用。

beforeDestroy

  • 实例销毁之前调用。在这一步,实例仍然完全可用。
    该钩子在服务器渲染期间不被调用。

destroyed

  • Vue实例销毁后调用, 调用后,Vue实例只是的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
    该钩子在服务器端渲染期间不被调用。

activated

  • keep-alive 组件激活是调用。
    该钩子在服务器渲染期间不被调用

deactivated

  • keep-alive 组件停用时调用。
    该钩子在服务器端渲染期间不被调用

常见指令

v-test

  • v-text主要用来更新textContent,可以等同于JS的text属性。

v-html

  • 双大括号的方式会将数据解释为纯文本,而非HTML。为了输出真正的HTML,可以用v-html指令。它等同于JS的innerHtml属性。

v-pre

  • v-pre主要用来跳过这个元素和它的子元素编译过程。可以用来显示原始的Mustache标签。跳过大量没有指令的节点加快编译。

    {{message}} //这条语句不进行编译 {{message}}
    最终仅显示第二个span的内容

v-cloak

  • 这个指令是用来保持在元素上直到关联实例结束时进行编译。

    {{message}}

    在页面加载时会闪烁,先显示:

    {{message}}

    然后才会编译为:

    hello world!

v-once

  • v-once关联的实例,只会渲染一次。之后的重新渲染,实例极其所有的子节点将被视为静态内容跳过,这可以用于优化更新性能。

v-if

  • v-if可以实现条件渲染,Vue会根据表达式的值的真假条件来渲染元素。

v-else

  • v-else是搭配v-if使用的,它必须紧跟在v-if或者v-else-if后面,否则不起作用

v-else-if

  • v-else-if充当v-if的else-if块,可以链式的使用多次。可以更加方便的实现switch语句。

v-show

  • 也是用根据条件展示元素,和v-if不同的是,如果v-if的值是false,则这个元素被销毁,不在dom中。但是v-show的元素会始终被渲染并保存在dom中,它只是简单的切换css的dispaly属性。

    • 注意:v-if有更高的切换开销
      v-show有更高的初始渲染开销。
      因此,如果要非常频繁的切换,则使用v-show较好;如果在运行时条件不太可能改变,则v-if较好

v-for

  • 用v-for指令根据遍历数组来进行渲染

    • 注意:当v-for和v-if同处于一个节点时,v-for的优先级比v-if更高。这意味着v-if将运行在每个v-for循环中

v-bind 简写【:】

  • v-bind用来动态的绑定一个或者多个特性。没有参数时,可以绑定到一个包含键值对的对象。常用于动态绑定class和style。以及href等

v-model

  • 这个指令用于在表单上创建双向数据绑定。

v-model会忽略所有表单元素的value、checked、selected特性的初始值。因为它选择Vue实例数据做为具体的值。

- v-model修饰符

	- <1> .lazy

	  默认情况下,v-model同步输入框的值和数据。可以通过这个修饰符,转变为在change事件再同步。
	  
	  

	- <2> .number

	  自动将用户的输入值转化为数值类型
	  
	  

	- <3> .trim

	  自动过滤用户输入的首尾空格
	  
	  

v-on 简写为【@】

  • v-on主要用来监听dom事件,以便执行一些代码块。表达式可以是一个方法名。

    • v-on事件修饰符

Vue Router

// 1. 定义 (路由) 组件。
// 可以从其他文件 import 进来
const Foo = { template: ‘

foo
’ }
const Bar = { template: ‘
bar
’ }

// 2. 定义路由
// 每个路由应该映射一个组件。 其中"component" 可以是
// 通过 Vue.extend() 创建的组件构造器,
// 或者,只是一个组件配置对象。
// 我们晚点再讨论嵌套路由。
const routes = [
{ path: ‘/foo’, component: Foo },
{ path: ‘/bar’, component: Bar }
]

// 3. 创建 router 实例,然后传 routes 配置
// 你还可以传别的配置参数, 不过先这么简单着吧。
const router = new VueRouter({
routes // (缩写) 相当于 routes: routes
})

// 4. 创建和挂载根实例。
// 记得要通过 router 配置参数注入路由,
// 从而让整个应用都有路由功能
const app = new Vue({
router
}).$mount(’#app’)

npm install vue-router

动态路由匹配

  • 响应路由参数的变化

    • { path: ‘/user/:id’, component: User }

    • 响应路由参数的变化

      复用组件时,想对路由参数的变化作出响应的话,你可以简单地 watch (监测变化) $route 对象:
      const User = {
      template: ‘…’,
      watch: {
      $route(to, from) {
      // 对路由变化作出响应…
      }
      }
      }
      或者使用 2.2 中引入的 beforeRouteUpdate 导航守卫:
      const User = {
      template: ‘…’,
      beforeRouteUpdate(to, from, next) {
      // react to route changes…
      // don’t forget to call next()
      }
      }

编程式的导航

  • router.push(location, onComplete?, onAbort?)

    // 字符串
    router.push(‘home’)

    // 对象
    router.push({ path: ‘home’ })

    // 命名的路由
    router.push({ name: ‘user’, params: { userId: ‘123’ }})

    // 带查询参数,变成 /register?plan=private
    router.push({ path: ‘register’, query: { plan: ‘private’ }})

    • 注意:在 Vue 实例内部,你可以通过 r o u t e r 访 问 路 由 实 例 。 因 此 你 可 以 调 用 t h i s . router 访问路由实例。因此你可以调用 this. router访this.router.push。
  • router.replace(location, onComplete?,onAbort?)

  • router.go(n)

    // 在浏览器记录中前进一步,等同于 history.forward()
    router.go(1)

    // 后退一步记录,等同于 history.back()
    router.go(-1)

    // 前进 3 步记录
    router.go(3)

    // 如果 history 记录不够用,那就默默地失败呗
    router.go(-100)
    router.go(100)

命名路由

  • User

    这跟下面这个代码是一个意思
    router.push({ name: ‘user’, params: { userId: 123 } })

重定向和别名

  • 重定向

    • { path: ‘/a’, redirect: ‘/b’ }
    • { path: ‘/a’, redirect: { name: ‘foo’ }} 重定向的目标也可以是一个命名的路由
    • 也可以是个方法{ path: ‘/a’, redirect: to => {
      // 方法接收 目标路由 作为参数
      // return 重定向的 字符串路径/路径对象
      }}
  • 别名

    • { path: ‘/a’, component: A, alias: ‘/b’ }

导航守卫

  • 全局前置守卫

    • const router = new VueRouter({ … })
      router.beforeEach((to, from, next) => {
      // …
      })

      每个守卫方法接收三个参数:

      to: Route: 即将要进入的目标 路由对象
      from: Route: 当前导航正要离开的路由
      next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
      next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
      next(false): 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
      next(’/’) 或者 next({ path: ‘/’ }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向 next 传递任意位置对象,且允许设置诸如 replace: true、name: ‘home’ 之类的选项以及任何用在 router-link 的 to prop 或 router.push 中的选项。
      next(error): (2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。

      • 确保 next 函数在任何给定的导航守卫中都被严格调用一次。它可以出现多于一次,但是只能在所有的逻辑路径都不重叠的情况下,否则钩子永远都不会被解析或报错。
  • 全局解析守卫

    • 全局后置钩子

      • router.afterEach((to, from) => {
        // …
        })
  • 路由独享的守卫

    routes: [
    {
    path: ‘/foo’,
    component: Foo,
    beforeEnter: (to, from, next) => {
    // …
    }
    }
    ]

    • 你可以在路由配置上直接定义 beforeEnter 守卫
  • 组件内守卫

    • 最后,你可以在路由组件内直接定义以下路由导航守卫:
      beforeRouteEnter
      beforeRouteUpdate (2.2 新增)
      beforeRouteLeave

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

  • 完整的导航解析流程

    • 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 的回调函数,创建好的组件实例会作为回调函数的参数传入。

获取路由参数

  • this.$route.params/query

路由懒加载(即按需加载路由)

  • 1、vue异步组件加载

    • {
      path: ‘/promisedemo’,
      name: ‘PromiseDemo’,
      component: resolve => require([’…/components/PromiseDemo’], resolve)
      }
  • 2、es import()方法

    • const Foo = () => import(’./Foo.vue’)
      const router = new VueRouter({
      routes: [{ path: ‘/foo’, component: Foo }]
      })
  • 3、webpack提供的require.ensure(),

    • {
      path: ‘/promisedemo’,
      name: ‘PromiseDemo’,
      component: r => require.ensure([], () => r(require(’…/components/PromiseDemo’)), ‘demo’)
      },

开发中遇到需要注意的点

移动端

  • 移动端适配

Vuex

安装 npm install vuex --save

State

state: {
userInfo: [],
name:‘张飞’,
title: “标题”
},

  • 单一状态树

  • 写法

    • state: {}
  • 获取方式

    • this.$store.state

    • mapState

      • …mapState([‘title’])
      • …mapState({title: ‘title’})

Getters

写法:
getters: {
getUserInfo: state => state.userInfo
},

  • 写法

    • getUserInfo: state => state.userInfo
    • getUserInfoConst: (state, getters) => {
      return getters.getUserInfo.length
      }
  • 可以认为是 store 的计算属性

  • 获取方式

    • this.$store.getters.getUserInfo // -> [{ id: 1, text: ‘…’, done: true }]

    • mapGetters

      • …mapGetters([
        ‘getUserInfo’,‘getUserInfoConst’,
        // … ])

Mutations

mutations: {
setUserInfo(state, data) {
state.userInfo = data
}

},

  • 写法

    • mutations: {
      setUserInfo(state, data) {
      state.userInfo = data
      }
      },

    • 使用常量替代 Mutation 事件类型

      import Vuex from ‘vuex’
      import { SOME_MUTATION } from ‘./mutation-types’

      const store = new Vuex.Store({
      state: { … },
      mutations: {
      // 我们可以使用 ES2015 风格的计算属性命名功能来使用一个常量作为函数名
      [SOME_MUTATION] (state) {
      // mutate state
      }
      }
      })

  • Mutation 必须是同步函数

  • 触发方式

    • 触发 $store.commit(‘title’, ‘标题二’)

    • mapMutations

      • …mapMutations({
        add: ‘increment’ // 将 this.add() 映射为 this.$store.commit('increment')
        })

Actions

const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit(‘increment’)
}
}
})

  • 写法

    • increment (context) {
      context.commit(‘increment’)
      }
    • increment ({ commit, state }) {
      commit(‘increment’)
      }
  • 触发方式

    • // 以载荷形式分发
      store.dispatch(‘incrementAsync’, {
      amount: 10
      })

    • // 以对象形式分发
      store.dispatch({
      type: ‘incrementAsync’,
      amount: 10
      })

    • mapActions

      • …mapActions([
        ‘increment’, // 将 this.increment() 映射为 this.$store.dispatch('increment')
      • // mapActions 也支持载荷:
        ‘incrementBy’ // 将 this.incrementBy(amount) 映射为 this.$store.dispatch('incrementBy', amount)
        ]),
  • actions是异步操作

Modules

const moduleA = {
state: () => ({ … }),
mutations: { … },
actions: { … },
getters: { … }
}

const moduleB = {
state: () => ({ … }),
mutations: { … },
actions: { … }
}

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

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态

  • Vuex 允许我们将 store 分割成模块

组件

组件注册

  • 全局注册

    HTML

    JS Vue.component('component-a', { /* ... */ }) Vue.component('component-b', { /* ... */ }) Vue.component('component-c', { /* ... */ })

    new Vue({ el: ‘#app’ })

    • Vue.component(‘组件名称’, ‘组件模板名称’)
  • 局部注册

    • 在用到的页面注册即可

      new Vue({
      el: ‘#app’,
      components: {
      ‘component-a’: ComponentA,
      ‘component-b’: ComponentB
      }
      })

属性

  • 自定义属性 props

    父组件可以使用 props 把数据传给子组件。

    • 组件props中声明的属性

      // 父组件
      :type=‘type’
      :is-visible=“false”
      :on-change=“handlePropChange”
      :list=[22,33,44]
      title=“属性Demo”
      class=“test1”
      :class="[‘test2’]"
      :style="{ marginTop: ‘20px’ }" //注意:style 的优先级是要高于 style
      style=“margin-top: 10px”>

      // 子组件
      props: {
      name: String,
      type: {
        //从父级传入的 type,它的值必须是指定的 ‘success’, ‘warning’, 'danger’中的一个,如果传入这三个以外的值,都会抛出一条警告
      validator: (value) => {
      return [‘success’, ‘warning’, ‘danger’].includes(value)
      }
      },
      onChange: {
      //对于接收的数据,可以是各种数据类型,同样也可以传递一个函数
      type: Function,
      default: () => { }
      },
      isVisible: {
      type: Boolean,
      default: false
      },
      list: {
      type: Array,
      // 对象或数组默认值必须从一个工厂函数获取
      default: () => []
      }
      }

      • data与props的区别
      • 单项数据流
      • 加与不加v-bind
  • 原生属性attrs

    • 没有声明的属性,默认自动挂载到组件根元素上
    • 设置inheritAttrs为false可以关闭自动挂载
  • 特殊属性class、style

    • 挂载到组件根元素上
    • 支持字符串、对象、数组等多种语法

事件

  • $emit

    • 子组件可以使用 $emit 触发父组件的自定义事件

      • vm.$emit( event, arg )
  • 普通事件与修饰符事件

  • 事件驱动

    • 先通过特定的选择器查找到需要操作的节点 -> 给节点添加相应的事件监听

      • 然后用户执行某事件(点击,输入,后退等等) -> 调用 JavaScript 来修改节点
  • 数据驱动

    • 是指视图是由数据驱动生成的,我们对视图的修改,不会直接操作 DOM,而是通过修改数据

      • 用户执行某个操作 -> 反馈到 VM 处理(可以导致 Model 变动) -> VM 层改变,通过绑定关系直接更新页面对应位置的数据(即:数据驱动不是操作节点的,而是通过虚拟的抽象数据层来直接更新页面)
  • 普通事件

  • 修饰符事件

    • <1> .lazy

      默认情况下,v-model同步输入框的值和数据。可以通过这个修饰符,转变为在change事件再同步。

插槽

插槽就是子组件中的提供给父组件使用的一个占位符,用 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的标签。

  • 普通插槽

    • 默认插槽

      • 父组件

        默认插槽:default slot

        
        

        子组件

    • 具名插槽

      • 父组件


        具名插槽:title slot1


        具名插槽:title slot2



        子组件

      • 缩写:例如 v-slot:header 可以被重写为 #header

  • 作用域插槽

    父组件
    
      
        
    
    子组件
    
    
    

组件之间的通信

  • 父组件

    // 父组件
    :type=‘type’
    :is-visible=“false”
    :on-change=“handlePropChange”
    :list=[22,33,44]
    title=“属性Demo”
    class=“test1”
    :class="[‘test2’]"
    :style="{ marginTop: ‘20px’ }" //注意:style 的优先级是要高于 style
    style=“margin-top: 10px”>

    • 父传子

      • :type=‘type’

      • :style="{ marginTop: ‘20px’ }" //注意:style 的优先级是要高于 style

      • :on-change=“handlePropChange”

      • name=‘属性’

      • :show.sync=“show” 使用sync 进行父子组件数据双向绑定

        1)不能和表达式一起使用(如v-bind:title.sync="doc.title + ‘!’“是无效的);
        2)不能用在字面量对象上(如v-bind.sync=”{ title: doc.title }"是无法正常工作的)。

  • 子组件

    • 通过props接收父组件的传值

      • name: String,

      • type: {
        validator: (value) => {
        return [‘success’, ‘warning’, ‘danger’].includes(value)
        }
        },

        //从父级传入的 type,它的值必须是指定的 ‘success’, ‘warning’, 'danger’中的一个,如果传入这三个以外的值,都会抛出一条警告

      • onChange: {
        type: Function,
        default: () => { }
        },

        //对于接收的数据,可以是各种数据类型,同样也可以传递一个函数

      • isVisible: {
        type: Boolean,
        default: false
        },

      • list: {
        type: Array,
        default: () => []
        }

        // 对象或数组默认值必须从一个工厂函数获取

    • 通过$emit 触发父组件

  • 兄弟组件

    • bus.js

      import Vue from ‘vue’
      export default new Vue

    • bus.$emit(“event”, data) 发布消息

      import Bus from “./bus.js”
      Bus.$emit(‘getTarget’, event.target);

    • bus.$on(“event”,()=> {}) 接收消息

      import Bus from “./bus.js”
      created() {
      Bus.$on(‘getTarget’, target => {
      console.log(target);
      });
      },

动态组件&异步组件

  • keep-alive
  • 异步组件

处理边界情况

  • $root

    • 实例的子组件中,其根实例可以通过 r o o t p r o p e r t y 进 行 访 问 t h i s . root property 进行访问 this. rootproperty访this.root
  • $parent

    • $parent property 可以用来从一个子组件访问父组件的实例
  • ref

    • 你可以通过 ref 这个 attribute 为子组件赋予一个 ID 引用,直接访问子组件

      this.$refs.usernameInput

      这样就允许父级组件通过下面的代码聚焦 里的输入框:

      this.$refs.usernameInput.focus()

    • 当 ref 和 v-for 一起使用的时候,你得到的 ref 将会是一个包含了对应数据源的这些子组件的数组。

    • 注意:$refs 只会在组件渲染完成之后生效,并且它们不是响应式的。这仅作为一个用于直接操作子组件的“逃生舱”——你应该避免在模板或计算属性中访问 $refs。

  • 循环引用

    • 递归组件

      • 自己调用自己
    • 组件之间的循环引用

  • vm.$forceUpdate() 强制更新

    • 迫使 Vue 实例重新渲染。注意它仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件。

全局事件的绑定与解绑

activated() {
window.addEventListener(‘scroll’, this.handleScroll)
},
deactivated() {
window.removeEventListener(‘scroll’, this.handleScroll)
},
不解绑全局事件可能会出现跟中bug
activated: 表示在页面展示的时候触发
deaatived 表示在页面即将被隐藏或替换成新的页面的时候触发

绑定

  • window.addEventListener(‘scroll’, this.handleScroll)

解绑

  • window.removeEventListener(‘scroll’, this.handleScroll)

你可能感兴趣的:(vue,面试题,web,mvc,vue)