Vue数据驱动原理

数据驱动流程

本文对应的 Vue 版本为 2.5.17

数据驱动是指视图由数据来调配生成,视图的更新不直接操作 DOM,而是直接修改数据。

Vue 是数据驱动的,其数据驱动流程大致如下:
Vue数据驱动原理$20230304194743

init

初始化数据与功能函数

阅读全文

CSS常见问题汇总
▶︎
all
running...

CSS 继承与非继承属性

CSS 属性在不设定取值时,其实际取值分为两种。
一种为继承属性,取父级元素该属性对应的值。
一种为非继承属性,去该属性的默认值。
由于 CSS 属性繁多,不容易死记来区分,一般可通过经验来判断一个属性是否可继承。

常见的不可继承属性如下:

  • display
  • 盒模型相关属性,如宽、高、内外边距、边框
  • 背景相关属性:如背景颜色、图片、位置、大小、重复
  • 定位相关属性:如 float、clear、position
  • 内容相关属性:如 content、counter-reset、counter-increment

其他属性多为可继承属性,例如:

  • 字体相关属性
  • 部分文本相关属性
  • 元素可见属性 visibility
  • 光标属性 cursor

display:none 与 visibility:hidden 区别

两者虽简单来说都是用于隐藏元素,表现形式大有不同。

display 会被文档流给移除,影响页面布局,导致重排重绘,原本位置会被其他元素占据。

visilibity:hidden 不会被文档流给移除,不会影响布局,页面重绘出一片空白,但不会重新排版。

display 不是继承属性,而 visibility 是继承属性。
若祖先设定为 visibility:hidden,后代元素会继承该属性不可见。
此时,若重置后代元素的 visibility 为 visible,其后代元素将可见。
若祖先设定的 display 属性设为 none 时,其不可继承,后代元素无力通过改变该属性重现。
总结如下表格所示:

样式 页面重绘 页面重排 显示效果 对应 css 属性是否继承
display:none 无显示 否(display)
visibility:hidden 所处区域空白 是(visibility)

媒体查询失效

媒体查询的常见用法为

设置屏幕在 300px 到 900px 时的背景

@media screen and (min-width: 300px) and (max-width: 900px) {
  body {
    background: #eee;
  }
}

当设置不生效时,检查在 <head> 中是否添加了如下 <meta> 标签

<meta name="viewport" content="width=device-width,initial-scale=1.0" />

img 标签是行内还是块级元素

img 标签是行内元素。
打开控制台查看:
CSS常见问题汇总20220421165556
但是,作为行内元素,img 标签为什么可以设定其宽高属性?
img 标签准确来说,是行内可替换元素。
所谓的可替换元素,简单来说,就是除了位置和大小,其自己内部的内容不受当前页面获取的样式与内部的填入的标签或文本等内容所影响。
img 标签可能不太好理解,另一个常见的行内可替换元素是 iframe 标签,其内部有自己一套样式来决定展现的内容。
常见的行内可替换元素有:

  • img
  • video
  • iframe
  • embed

总体来看,行内可替换元素趋向于 display:inline-block 的表现

BMW WARNING

  • Bulletin

本文首发于 skyline.show 欢迎访问,
文章实时更新,如果有什么错误或不严谨之处望请指出,十分感谢。
如果你觉得有用,欢迎到Github仓库点亮⭐️。

I am a bucolic migrant worker but I never walk backwards.

  • Material

参考资料如下列出,部分引用可能遗漏或不可考,侵删。

https://developer.mozilla.org/en-US/docs/Web/CSS/Replaced_element

  • Warrant

本文作者: Skyline(lty)
授权声明: 本博客所有文章除特别声明外, 均采用 CC BY - NC - SA 3.0 协议。 转载请注明出处!

[CC BY - NC - SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed.zh

Webpack代码拆分

基础代码

//pageA.js

var vue = require('vue');
var utility1 = require('./utility1');
var utility2 = require('./utility2');
new Vue()

import(/* webpackChunkName: "common-async.js" */"./common-async").then(common => {
console.log(common);
})

module.exports = "pageA";

//pageB.js
var react = require('react');
var reactDom = require('react-dom');
var utility2 = require('./utility2');
var utility3 = require('./utility3');
import(/* webpackChunkName: "common-async.js" */"./common-async").then(common => {
console.log(common);
})
module.exports = "pageB";

//pageC.js
var utility2 = require('./utility2');
var utility3 = require('./utility3');

module.exports = "pageC";

//pageD.js
import "./common-async"
module.exports = "pageD";

//common-async.js
import(/* webpackChunkName: "f.js" */"./f").then(f => {
console.log(f);
})

module.exports = "common-async";

//f.js utility1.js utility1.js utility1.js
module.exports = "utility1"
module.exports = "utility2"
module.exports = "utility3"
module.exports = "f"

默认开箱配置

Webpack默认会将入口文件和按需加载的文件来生成对应的代码块
webpack.config.js

var path = require("path");
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin // BundleAnalyzer插件,图形化分析打包文件结构

module.exports = {
// mode: "development" || "production",
entry: {
pageA: "./pageA", // 引用utility1.js utility2.js vue.js 动态引入common-async
pageB: "./pageB", // 引用utility2.js utility3.js react reactDom 动态引入common-async
pageC: "./pageC", // 引用utility2.js utility3.js,
},
optimization: {
},
output: {
path: path.join(__dirname, "dist"),
filename: "[name].js"
},
plugins: [new BundleAnalyzerPlugin()]
};

HTTP缓存

缓存的优势

  • 减少网络带宽消耗

通过减少网络请求数量来减少网络流量消耗

  • 降低服务器压力

并发的大量的请求会使得服务器负载过重,减少网络请求能是服务器与更多地客户端建立连接,
减少过载死机的次数。

  • 加快页面打开速度

直接使用本地的缓存,能明显地加快页面响应速度

缓存位置

memory cache

阅读全文

CSS基础布局

居中布局

居中布局概述

方案 宽高固定
flex
position+transition
position+margin
display:table-cell

几种实现方案使用共同的类样式:

.simulated_body {
resize: both;
overflow: scroll;
width: 50%;
}

.example {
background-color: #eee;
overflow: hidden;
height: 200px;
}

.cell {
width: 100px;
height: 100px;
background: lightblue;
text-align: center;
}

flex

阅读全文

Vue渲染机制

VDOM

在 JQuery 同时代,大多数的框架首先都是直接操作 DOM 元素。
但是不管多简单的 DOM 元素,都包含了较为复杂的属性。
打开任意网页,右键审查元素,在控制台输入

Object.keys(console.dir($0))

Vue渲染机制$20230222094020

截图仅为很小的部分,可以看到即便是最简单的叶子节点,其都有较为庞大的身躯。
直接操作 DOM,当交互复杂时,不可避免会频繁操作 DOM, 这将造成浏览器回流重绘等性能问题。
最为直接的表现就是页面卡顿。

真实 DOM 上的额外的属性与方法往往与我们的操作无关,最终实现的效果也毫无关系。
于是为 DOM 瘦身,同时将频繁操作统一一步进行等理念应运而生。

虚拟 Dom,由 React 最先提出,她不是一种标准,更像是思想理念,或者说是一种设计,一个模式。
VDom 可以被看做是 UI 在内存中的虚拟。

假定 HTML 为:

<div id="skyline">
<h3 class="title"></h3>
<p>{{ name }}</p>
</div>

则用 JS 对象简单实现的 VDOM 类似如下:

{
type: 'div',
props: {
id: 'skyline'
},
children: [
{
type: 'h3',
props: {
class: 'title'
},
},
{
type: 'p',
props: {},
},
]
}

每一个节点可以称为虚拟节点 vnode 。
不同框架定义的节点属性可能不同,但大体都有上述属性。
若以上节点为根节点,子节点不断扩展,便可联结壮大这颗 VDOM 树。

Vue render 函数返回 VDOM(准确来说是 AST,即虚拟语法树)。
通过官方的工具进行如下 Demo:

仍以前述 HTML 模板为例,上述模板会被解析成 Render 语法

import {
createElementVNode as _createElementVNode,
toDisplayString as _toDisplayString,
openBlock as _openBlock,
createElementBlock as _createElementBlock,
} from 'vue'

export function render(_ctx, _cache, $props, $setup, $data, $options) {
return (
_openBlock(),
_createElementBlock('div', { id: 'skyline' }, [
_createElementVNode('h3', { class: 'title' }),
_createElementVNode('p', null, _toDisplayString(_ctx.name), 1 /* TEXT */),
])
)
}

// Check the console for the AST

通过打开控制台找到 AST,可以看到:

Vue渲染机制$20230210110315

VDOM实质是在真实DOM和JS之间做“缓存”的作用,
减轻了真实DOM更新与构建缓慢带来的影响。

渲染流程

Vue底层将模板语法编译成 Render(或直接写Render函数),
通过Render创建VDOM,
通过mount将VDOM挂载或更新成真实DOM。

具体用一个官方图来说明

Vue渲染机制$20230222093857

Template优化

阅读全文

ES事件轮询

执行机制

单线程

JS 设计为单线程脚本语言,主线程只能同时处理一个任务。
为了防止主线程阻塞,事件轮询机制应运而生(event loop)
先看如下一个常见示例

console.log(1)

setTimeout(() => {
console.log(5)
}, 0)

setTimeout(() => {
console.log(6)
}, 10)

Promise.resolve()
.then(() => {
console.log(3)
})
.then(() => {
console.log(4)
})

console.log(2)

// 1 2 3 4 5 6

同异步

阅读全文

ES防抖和节流

防抖

防抖的理解

防抖debounce ,即防止抖动。
当事件不停地触发时,浏览器为了应对同一时间段的大量任务,交互区域表现出来就像是在抖动。
防抖将事件触发规定在单位时间内,单位时间内新事件触发会丢弃上次事件并重新计算下个时间段,
以此往复,直到最新的单位时间段内无新事件触发,对应函数执行完成。

防抖一般只执行最后一次函数,
或根据需求,立即执行首次函数,然后只执行后续连续触发的最后一次。

其主要实现原理:

  • setTimeout
  • 闭包

防抖基础版本

阅读全文

String相关基础操作

字符串存为数组

var a = 'skyline'

var b = Array.prototype.slice.call(a, 0)
// ['s', 'k', 'y', 'l', 'i', 'n', 'e']
var c = a.split('')
// ['s', 'k', 'y', 'l', 'i', 'n', 'e']

重复字符串

主要为使用字符串的 repeat 方法或数组来实现

Array(7).fill('1').join('')
// '1111111'
new Array(8).join(1)
// '1111111'
'1'.repeat(7)
// '1111111'
String.prototype.repeat.call(1, 7)
// '1111111'

变量命名

阅读全文


Copyright © 2017 - 2024 鹧鸪天 All Rights Reserved.

skyline 保留所有权利