属性透传attribute、vue实例对象方法$nextTick()、虚拟dom与浏览器渲染机制

一、属性透传attribute

  • 指的是传递给一个组件,但没有通过props或emits接收,常见的如class、style、id
  • 透传的样式会自动被添加到子组件根元素上,如果子组件已经有一个样式,透传的样式会和已有样式合并。
  • 如果透传的是一个点击事件,也会自动被添加到子组件根元素上,如果子组件自身也有点击事件,点击时透传过来的事件和其本身的事件都会触发。
  • 透传的属性可以通过{{$attrs}}拿到
  • 属性透传只会透传到根元素上,如果有多个根节点,vue不知道要透传到哪个节点,需要通过v-bind="$attrs"绑定到要透传到的那个节点上,否则会抛出警告。
  • 属性透传是可以禁用的,通过inheritAttrs: false可以阻止透传

例:

目录

1.新建assets样式文件夹,样式文件style.css

css 复制代码
.large{
    color: red;
}
.small{
    background-color: pink;
}

2.在index.html中引入样式文件

xml 复制代码
<!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">
    <title>首页</title>
    <link rel="stylesheet" href="./assets/css/style.css">
</head>

<body>
    <div id="app"></div>
    <script type="module" src="./src/main.js"></script>
</body>
</html>

父组件App.js

arduino 复制代码
import Child from "./Child.js";
export default {
  components: {
    Child,
  },

  data() {
    return {
      title: "attribute属性透传",
      count:0
    };
  },

  /*html*/
  template: `<div style="width:400px;height:400px;background-color:skyblue;">
                <h2>{{title}}</h2>
                <p>{{count}}</p>
                 <Child class="large" @click="count++" ></Child>
            </div>`,
};

子组件Child.js

dart 复制代码
export default {
  data() {
    return {
      num: 10,
    };
  },

  inheritAttrs: true, // 阻止透传

  /*html*/
  template: `
              <button @click="num++" class="small">子按钮{{num}}</button>
              <main v-bind="$attrs">多个根节点</main>
          `,
};

二、vue实例对象方法$nextTick()

可以通过this.$nextTick(()=>{})访问,回调函数会在dom节点渲染完成后执行

如:正常操作dom节点是在mounted生命周期中操作,nextTick()方法可以实现在created生命周期中操作dom节点

javascript 复制代码
export default {
  data() {
    return {
      title: "vue实例对象的 $nextTick()",
      count:10
    };
  },

  created() {
      this.$nextTick(()=>{
        //回调函数,模板界面异步更新完成后执行
        const pEle = document.querySelector('#countP')
        console.log('bindPlus >> ',pEle.innerHTML);
      })
  },

  methods: {
    bindPlus(){
      this.count++
      // 验证, count数据变化,通知依赖更新界面是一个异步过程
      const pEle = document.querySelector('#countP')
      console.log('bindPlus >> ',pEle.innerHTML);//是更新之前的值,说明是异步更新的

      //模板界面异步更新完成后执行nextTick回调函数中代码
      this.$nextTick(()=>{
        const pEle = document.querySelector('#countP')
        console.log('bindPlus >> ',pEle.innerHTML); //是更新之后的值
      })
    }
  },

  /*html*/
  template: `<div>
                <h2>{{title}}</h2>
                <p id="countP">{{count}}</p>
                <button @click="bindPlus">加一 </button>
            </div>`,
};

三、虚拟dom、浏览器渲染机制

整个html文档是一个dom对象,整个html由dom节点对象构成。

浏览器渲染机制:

  1. 解析HTML生成dom树,同时解析CSS文档构建CSSOM树
  2. DOM树和CSSOM树关联起来生成渲染树(RenderTree)
  3. 浏览器按照渲染树进行重排重绘

重绘:CSS 样式改变(如:visibility,背景色的改变),使浏览器需要根据新的属性进行绘制

重排:对DOM的修改引发了DOM几何元素的变化(如:改变元素高度),渲染树需要重新计算,重新生成布局,重新排列元素。

重绘不一定导致重排,但重排一定会导致重绘

操作真实dom会引起重排重绘,vue框架操作的是虚拟dom(本质上就是一个普通的JS对象。是模拟真实dom得到的一个JS对象)

将真实dom多次操作在虚拟dom上完成,再将虚拟dom映射到真实dom,完成一次重排重绘,提高渲染效率。

我们在vue中写的template模板,vue编译过程中,会调用render()函数将其编译成虚拟dom树,后映射挂载成真实dom,然后重排重绘显示给用户

vue提供了一个h()方法,用于创建虚拟dom(vnode)

php 复制代码
import { h } from 'vue'
render(){
  return[

        h('div')

        h('div', { id: "foo" })

        h('div', { id: "foo", class: "bar", style: { color: 'red' }, onClick: () => { } },'标  题', [/*child*/])

  ]
}
相关推荐
RONIN2 小时前
vue自定义指令与自定义插件
vue.js
RONIN2 小时前
属性透传attribute与性能优化组件(component、异步组件、keep-alive/Suspense/Teleport/Transition)
vue.js
RONIN3 小时前
组件通讯(父传子、子传父、ref属性、表单双向绑定v-model、兄弟间传值Event Bus、插槽、依赖注入)
vue.js
RONIN3 小时前
vue组件、组件生命周期、组件分离模块化
前端·vue.js
RONIN3 小时前
vue开发环境与基础语法、计算属性、侦听属性
前端·vue.js
只会写Bug5 小时前
后台管理项目中关于新增、编辑弹框使用的另一种展示形式
前端·vue.js
M ? A6 小时前
Vue v-bind 转 React:VuReact 怎么处理?
前端·javascript·vue.js·经验分享·react.js·面试·vureact
军军君016 小时前
数字孪生监控大屏实战模板:政务服务大数据
前端·javascript·vue.js·typescript·前端框架·echarts·less
忆往wu前6 小时前
前端请求三部曲:Ajax / Fetch / Axios 演进与 Vue 工程化封装
前端·vue.js