搜索
您的当前位置:首页VUE重点问题总结

VUE重点问题总结

时间:2023-11-30 来源:乐玩宠

本篇内容给大家总结了VUE的重要难点,并把代码做了详细分享,有兴趣的朋友参考学习下。

1、组件三种挂载方式

自动挂载

var app3 = new Vue({ el: '#app-3', data: { seen: true }})

手动挂载

// 可以实现延迟按需挂载<p id="app"> {{name}} </p> <button onclick="test()">挂载</button> <script> var obj= {name: '张三'} var vm = new Vue({ data: obj }) function test() { vm.$mount("#app"); }
// Vue.extend()创建没有挂载的的子类,可以使用该子累创建多个实例var app= Vue.extend({ template: '<p>{{message}}</p>', data: function () { return { message: 'message' } } }) new app().$mount('#app') // 创建 app实例,并挂载到一个元素上

2、路由传递参数的方式

<p> <!-- query要用path来引入,params要用name来引入,故不能写为 :to="{path:'/login',params: {isLogin: true}} --> <!-- 跳转路由时用this.$router: this.$router.push({name:"login",params:{isLogin:true}});this.$router.push({path: '/login', query: {isLogin : true}}); --> <!-- 接收参数时用this.$route: this.$route.query.isLogin 和 this.$route.params.isLogin; --> <router-link :to="{name:'login',params: {isLogin: true}}">亲,请登录</router-link> <router-link :to="{name:'login',params: {isLogin: false}}">免费注册</router-link> </p> <!-- 路由出口, 路由匹配到的组件将渲染在这里 --> <router-view></router-view>

3、对render:h => h(App)的理解

render:h=>h(App)是ES6中的箭头函数写法,等价于render:function(h){return h(App);}.

1.箭头函数中的this是 指向 包裹this所在函数外面的对象上。

2.h是creatElement的别名,vue生态系统的通用管理

3.template:‘<app/>',components:{App}配合使用与单独使用render:h=>h(App)会达到同样的效果

前者识别<template>标签,后者直接解析template下的id为app的p(忽略template的存在)

new Vue({ el: '#app', // 相当于 new Vue({}).$mount('#app'); template: '<App/>', // 1、可以通过在 #app 内加入<app></app>替代 2、或者 通过 render: h => h(App) 渲染一个视图,然后提供给el挂载 components: { // vue2中可以通过 render: h => h(App) 渲染一个视图,然后提供给el挂载 App }});

4、Vue.nextTick()的理解

与DOM相关操作写在该函数回调中,确保DOM已渲染

nextTick的由来:

由于VUE的数据驱动视图更新,是异步的,即修改数据的当下,视图不会立刻更新,而是等同一事件循环中的所有数据变化完成之后,再统一进行视图更新。

nextTick的触发时机:

在同一事件循环中的数据变化后,DOM完成更新,立即执行nextTick(callback)内的回调。

应用场景:

需要在视图更新之后,基于新的视图进行操作。

在Vue生命周期的created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中。原因是什么呢,原因是在created()钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的js代码放进Vue.nextTick()的回调函数中。与之对应的就是mounted钩子函数,因为该钩子函数执行时所有的DOM挂载和渲染都已完成,此时在该钩子函数中进行任何DOM操作都不会有问题 。

在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的DOM结构的时候,这个操作都应该放进Vue.nextTick()的回调函数中。

简单总结事件循环:

同步代码执行 -> 查找异步队列,推入执行栈,执行callback1[事件循环1] ->查找异步队列,推入执行栈,执行callback2[事件循环2]...即每个异步callback,最终都会形成自己独立的一个事件循环。结合nextTick的由来,可以推出每个事件循环中,nextTick触发的时机:

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

使用Angular CLI进行单元测试和E2E测试的方法

使用Angular CLI进行Build(构建)和Serve详解

使用Angular CLI生成路由的方法

小编还为您整理了以下内容,可能对您也有帮助:

Vue知识点整理

每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例开始的。

Vue 实例使用的根 DOM 元素。

当前组件树的根 Vue 实例。如果当前实例没有父实例,此实例将会是其自己。

获取定义在data外的数据和方法。

当前实例的直接子组件。

获取被插槽分发的内容。

获取具名插槽。

获取注册过refs的所有DOM元素和组件实例。

Vue是否运行于服务端。

主动销毁该实例。

挂载DOM。

观察 Vue 实例上的一个表达式或者一个函数计算结果的变化。回调函数得到的参数为新值和旧值。

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

使回调函数在 DOM 更新完成后被调用。

Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。
为了在数据变化之后等待 Vue 完成更新 DOM,可以在数据变化之后立即使用 Vue.nextTick(callback)。这样回调函数将在 DOM 更新完成后被调用。

实例被创建之前执行。在生命周期过程中只执行一次。

实例创建完成之后执行。在生命周期过程中只执行一次。

挂载组件之前(如果有挂载组件的操作)。在生命周期过程中只执行一次。

组件挂载之后。在生命周期过程中只执行一次。

组件更新前。

组件更新完成。

组件销毁前。

组件被销毁。

computed是计算属性(通过其他变量计算得来的另一个属性),在相关响应式依赖发生变化时它们才会重新求值。
watch是侦听器,来响应数据的变化,当需要在数据变化时执行异步或开销较大的操作时,这个方式最有用。

computed和watch都不要去改变自己监听的属性,而是要去生成一个新的值,否则会触发无限循环。

v-if=false生效时会使节点不存在在DOM流中,会动态增删节点,比较耗能;
v-show只是在节点上加上display:none。
v-if可配合v-else-if、v-else使用。

v-for的优先级高于v-if,所以在两者同时使用时,v-if会作用于每一个v-for循环上。

继承的组件的prop需要通过propsData传入,data可以直接改变。

需求:有一些内容,是在调用组件时根据场景去写的。

父组件使用子组件时:

<slot></slot>的内容将被123代替。

父组件使用子组件时:

注意:一个不带 name 的 <slot> 出口会带有隐含的名字“default”。

需求:插槽内容能够访问子组件中才有的数据。
子组件:

父组件中使用:

Vue知识点整理

每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例开始的。

Vue 实例使用的根 DOM 元素。

当前组件树的根 Vue 实例。如果当前实例没有父实例,此实例将会是其自己。

获取定义在data外的数据和方法。

当前实例的直接子组件。

获取被插槽分发的内容。

获取具名插槽。

获取注册过refs的所有DOM元素和组件实例。

Vue是否运行于服务端。

主动销毁该实例。

挂载DOM。

观察 Vue 实例上的一个表达式或者一个函数计算结果的变化。回调函数得到的参数为新值和旧值。

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

使回调函数在 DOM 更新完成后被调用。

Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。
为了在数据变化之后等待 Vue 完成更新 DOM,可以在数据变化之后立即使用 Vue.nextTick(callback)。这样回调函数将在 DOM 更新完成后被调用。

实例被创建之前执行。在生命周期过程中只执行一次。

实例创建完成之后执行。在生命周期过程中只执行一次。

挂载组件之前(如果有挂载组件的操作)。在生命周期过程中只执行一次。

组件挂载之后。在生命周期过程中只执行一次。

组件更新前。

组件更新完成。

组件销毁前。

组件被销毁。

computed是计算属性(通过其他变量计算得来的另一个属性),在相关响应式依赖发生变化时它们才会重新求值。
watch是侦听器,来响应数据的变化,当需要在数据变化时执行异步或开销较大的操作时,这个方式最有用。

computed和watch都不要去改变自己监听的属性,而是要去生成一个新的值,否则会触发无限循环。

v-if=false生效时会使节点不存在在DOM流中,会动态增删节点,比较耗能;
v-show只是在节点上加上display:none。
v-if可配合v-else-if、v-else使用。

v-for的优先级高于v-if,所以在两者同时使用时,v-if会作用于每一个v-for循环上。

继承的组件的prop需要通过propsData传入,data可以直接改变。

需求:有一些内容,是在调用组件时根据场景去写的。

父组件使用子组件时:

<slot></slot>的内容将被123代替。

父组件使用子组件时:

注意:一个不带 name 的 <slot> 出口会带有隐含的名字“default”。

需求:插槽内容能够访问子组件中才有的数据。
子组件:

父组件中使用:

Vue.js提升必知的几点总结

这次给大家带来Vue.js提升必知的几点总结,Vue.js提升的注意事项有哪些,下面就是实战案例,一起来看一下。

第一招:化繁为简的Watchers

场景还原:

created(){

this.fetchPostList()

},

watch: {

searchInputValue(){

this.fetchPostList()

}

}

组件创建的时候我们获取一次列表,同时监听input框,每当发生变化的时候重新获取一次筛选后的列表这个场景很常见,有没有办法优化一下呢?

招式解析:

首先,在watchers中,可以直接使用函数的字面量名称;其次,声明immediate:true表示创建组件时立马执行一次。

watch: {

searchInputValue:{

handler: 'fetchPostList',

immediate: true

}

}

第二招:一劳永逸的组件注册

场景还原:

import BaseButton from './baseButton'

import BaseIcon from './baseIcon'

import BaseInput from './baseInput'

export default {

components: {

BaseButton,

BaseIcon,

BaseInput

}

}<BaseInput

v-model="searchText"

@keydown.enter="search"

/>

<BaseButton @click="search">

<BaseIcon name="search"/>

</BaseButton>

我们写了一堆基础UI组件,然后每次我们需要使用这些组件的时候,都得先import,然后声明components,很繁琐!秉持能偷懒就偷懒的原则,我们要想办法优化!

招式解析:

我们需要借助一下神器webpack,使用 require.context() 方法来创建自己的(模块)上下文,从而实现自动动态require组件。这个方法需要3个参数:要搜索的文件夹目录,是否还应该搜索它的子目录,以及一个匹配文件的正则表达式。

我们在components文件夹添加一个叫global.js的文件,在这个文件里借助webpack动态将需要的基础组件统统打包进来。

import Vue from 'vue'

function capitalizeFirstLetter(string) {

return string.charAt(0).toUpperCase() + string.slice(1)

}

const requireComponent = require.context(

'.', false, /.vue$/

//找到components文件夹下以.vue命名的文件

)

requireComponent.keys().forEach(fileName => {

const componentConfig = requireComponent(fileName)

const componentName = capitalizeFirstLetter(

fileName.replace(/^.//, '').replace(/.w+$/, '')

//因为得到的filename格式是: './baseButton.vue', 所以这里我们去掉头和尾,只保留真正的文件名

)

Vue.component(componentName, componentConfig.default || componentConfig)

})

最后我们在main.js中import 'components/global.js',然后我们就可以随时随地使用这些基础组件,无需手动引入了。

第三招:釜底抽薪的router key

场景还原:

下面这个场景真的是伤透了很多程序员的心...先默认大家用的是Vue-router来实现路由的控制。

假设我们在写一个博客网站,需求是从/post-page/a,跳转到/post-page/b。然后我们惊人的发现,页面跳转后数据竟然没更新?!原因是vue-router"智能地"发现这是同一个组件,然后它就决定要复用这个组件,所以你在created函数里写的方法压根就没执行。通常的解决方案是监听$route的变化来初始化数据,如下:

data() {

return {

loading: false,

error: null,

post: null

}

},

watch: {

'$route': {

handler: 'resetData',

immediate: true

}

},

methods: {

resetData() {

this.loading = false

this.error = null

this.post = null

this.getPost(this.$route.params.id)

},

getPost(id){

}

}

bug是解决了,可每次这么写也太不优雅了吧?秉持着能偷懒则偷懒的原则,我们希望代码这样写:

data() {

return {

loading: false,

error: null,

post: null

}

},

created () {

this.getPost(this.$route.params.id)

},

methods () {

getPost(postId) {

// ...

}

}

招式解析:

那要怎么样才能实现这样的效果呢,答案是给router-view添加一个unique的key,这样即使是公用组件,只要url变化了,就一定会重新创建这个组件。(虽然损失了一丢丢性能,但避免了无限的bug)。同时,注意我将key直接设置为路由的完整路径,一举两得。

<router-view :key="$route.fullpath"></router-view>

第四招: 无所不能的render函数

场景还原:

vue要求每一个组件都只能有一个根元素,当你有多个根元素时,vue就会给你报错

<template>

<li

v-for="route in routes"

:key="route.name"

>

<router-link :to="route">

{{ route.title }}

</router-link>

</li>

</template>

ERROR - Component template should contain exactly one root element.

If you are using v-if on multiple elements, use v-else-if

to chain them instead.

招式解析:

那有没有办法化解呢,答案是有的,只不过这时候我们需要使用render()函数来创建HTML,而不是template。其实用js来生成html的好处就是极度的灵活功能强大,而且你不需要去学习使用vue的那些功能有限的指令API,比如v-for,

v-if。(reactjs就完全丢弃了template)

functional: true,

render(h, { props }) {

return props.routes.map(route =>

<li key={route.name}>

<router-link to={route}>

{route.title}

</router-link>

</li>

)

}

第五招:无招胜有招的高阶组件

划重点:这一招威力无穷,请务必掌握

当我们写组件的时候,通常我们都需要从父组件传递一系列的props到子组件,同时父组件监听子组件emit过来的一系列事件。举例子:

//父组件

<BaseInput

:value="value"

label="密码"

placeholder="请填写密码"

@input="handleInput"

@focus="handleFocus>

</BaseInput>

//子组件

<template>

<label>

{{ label }}

<input

:value="value"

:placeholder="placeholder"

@focus=$emit('focus', $event)"

@input="$emit('input', $event.target.value)"

>

</label>

</template>

有下面几个优化点:

1.每一个从父组件传到子组件的props,我们都得在子组件的Props中显式的声明才能使用。这样一来,我们的子组件每次都需要申明一大堆props,

而类似placeholer这种dom原生的property我们其实完全可以直接从父传到子,无需声明。方法如下:

<input

:value="value"

v-bind="$attrs"

@input="$emit('input', $event.target.value)"

>

$attrs包含了父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (class 和 style 除外)。当一个组件没有声明任何

prop 时,这里会包含所有父作用域的绑定,并且可以通过 v-bind="$attrs" 传入内部组件——在创建更高层次的组件时非常有用。

2.注意到子组件的@focus=$emit('focus', $event)"其实什么都没做,只是把event传回给父组件而已,那其实和上面类似,我完全没必要显式地申明:

<input

:value="value"

v-bind="$attrs"

v-on="listeners"

>

computed: {

listeners() {

return {

...this.$listeners,

input: event =>

this.$emit('input', event.target.value)

}

}

}

$listeners包含了父作用域中的 (不含 .native 修饰器的) v-on 事件。它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。

3.需要注意的是,由于我们input并不是BaseInput这个组件的根节点,而默认情况下父作用域的不被认作 props

的特性绑定将会“回退”且作为普通的 HTML

特性应用在子组件的根元素上。所以我们需要设置inheritAttrs:false,这些默认行为将会被去掉, 以上两点的优化才能成功。

相信看了本文案例你已经掌握了方法,更多精彩请关注Gxl网其它相关文章!

推荐阅读:

vue的新手入门教程

Vue项目怎样分环境打包

乐玩宠还为您提供以下相关内容希望对您有帮助:

Vue知识点整理

Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的...

vue面试题

原理:eventloop事件循环 在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。key 主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。不指定key时,Vue 会使用...

记一次 Vue2 迁移 Vue3 的实践总结

一、Vue3 Vue3中文文档[1]2.x 全局 API3.x 实例 API (app) Vue.configapp.config Vue.config.productionTip无 Vue.config.ignoredElementsapp.config.isCustomElement Vue.componentapp.component Vue.direct...

vue2.0怎样开发多页面

当一个vue项目完成好所有的配置后,接下来就是我们的重点了,首先我们新新建几个html文件,博主我新建了一个one.html和two.html,及其与之对应的vue文件和js文件,文件目录如下:弄好之后我们进入buildwebpack.base.conf.js...

05《Vue 入门教程》Vue 动态样式绑定

本小节我们将介绍 Vue 中如何动态绑定样式。包括 Class 的绑定、内联样式 Style 的绑定。掌握样式绑定的多种形式是其中的重点难点。同学们可以在学完本小节之后对样式的绑定方式加以总结,再通过反复的练习来加深印象。通过 ...

vue3实践---路由router

创建好vue3项目的第一步就是安装vue-router ,因为vite 默认并没有安装的。参考官网: 安装 | Vue Router (vuejs.org)然后在src 目录下创建router目录,并添加2个文件index.js,routes.js.这里就要画重点了。因为vue3的...

Vue 5 Esprit 基础教程之菜单详解:Help(帮助)

Help(帮助)菜单是Vue菜单栏中的最后一组,如图15所示。它主要是用于显示帮助信息的,使用Vue的Help(帮助)菜单我们可以快速使用它的帮助系统帮我们轻松掌握Vue的使用。Help(帮助)菜单其中,Kick Start Tutorial(开始学习)...

Vue生命周期中mounted和created的区别

1、在使用vue框架的过程中,我们经常需要给一些数据做一些初始化处理,这时候我们常用的就是在created与mounted选项中作出处理。首先来看下官方解释,官方解释说created是在实例创建完成后立即调用。在这一步,实例已完成以下配置...

21《Vue 入门教程》VueRouter 基础使用

其中,学习使用 VueRouter 配置一个单页应用是本节的重点。同学们在学完本节课程之后需要自己多尝试配置路由。我们可以在官网 (VueRouter) 上直接下载 VueRouter 。 在 Vue 之后引入 VueRouter 会进行自动...

vue3.2 setup 之局部自定义指令

在组件内部,使用 directives 引入的叫做局部自定义指令。其实,在vue3.2中,自定义指令变得更加的简单,直接上例子。看到了吗,重点是: 注册一个局部的自定义指令,需要以小写v开头 。这里做最简单示例,实战中举一反三...

Top
7.960006s