vue(html,css,vue2,vue3) 学习总结

文章目录

  • [小白 Vue 3 学习](#小白 Vue 3 学习)
  • [VSCode 中的一些设置](#VSCode 中的一些设置)
    • [1. 关闭eslint检查](#1. 关闭eslint检查)
    • [tsconfig.json 配置文件](#tsconfig.json 配置文件)
    • [2. ts 文件引用报红](#2. ts 文件引用报红)
  • 相对路径写法
  • 常见图片格式和区别
  • 目录结构
  • JS/TS
    • [1. prototype(原型对象)](#1. prototype(原型对象))
    • [2. 导入/导出](#2. 导入/导出)
    • [3. 去除字符串两端空格](#3. 去除字符串两端空格)
    • [4. 一些特殊语法糖](#4. 一些特殊语法糖)
    • [5. 深拷贝](#5. 深拷贝)
    • [6. 拼接两个数组](#6. 拼接两个数组)
    • [7. JSON](#7. JSON)
  • DOM
  • HTML
  • CSS
  • CSS3
  • cas_websited
    • [0. 项目中学到的一些技巧](#0. 项目中学到的一些技巧)
    • [1. 指令](#1. 指令)
    • [2. 协议对接](#2. 协议对接)
    • [3. 请求服务器](#3. 请求服务器)
    • [4. 上拉加载历史消息(滑动条保持原高度)](#4. 上拉加载历史消息(滑动条保持原高度))
    • [5. 滑动条定位](#5. 滑动条定位)
  • [Vue 2](#Vue 2)
    • [0. 总结](#0. 总结)
    • [1. 初识 vue](#1. 初识 vue)
    • [2. 模板语法(V-bind,v-model)](#2. 模板语法(V-bind,v-model))
    • [3. vue 实例两种写法](#3. vue 实例两种写法)
    • [4. Object.defineProperty() 给对象添加属性](#4. Object.defineProperty() 给对象添加属性)
    • [5. Object.keys(对象)](#5. Object.keys(对象))
    • [6. v-on(事件处理)](#6. v-on(事件处理))
    • [7. 事件修饰符](#7. 事件修饰符)
    • [8. 键盘事件](#8. 键盘事件)
    • [9. methods(方法)](#9. methods(方法))
    • [10. computed(计算属性)](#10. computed(计算属性))
    • [11. watch(监视属性)](#11. watch(监视属性))
    • [12. 绑定样式](#12. 绑定样式)
    • [13. 条件渲染(v-show/v-if/v-else-if/v-else)](#13. 条件渲染(v-show/v-if/v-else-if/v-else))
    • [14. v-for (列表渲染)](#14. v-for (列表渲染))
    • [15. 列表过滤和排序](#15. 列表过滤和排序)
    • [16. set(object, key, value) 添加响应式属性](#16. set(object, key, value) 添加响应式属性)
    • [17. vue 监测数据总结](#17. vue 监测数据总结)
    • [18. 收集表单数据示例](#18. 收集表单数据示例)
    • [19. vue 内部指令](#19. vue 内部指令)
    • [20. 生命周期](#20. 生命周期)
    • [21. 非单文件组件](#21. 非单文件组件)
    • [22. vm 与 vc](#22. vm 与 vc)
    • [23. 单文件组件(.vue)](#23. 单文件组件(.vue))
    • [24. ref 属性](#24. ref 属性)
    • [25. props 属性(父传子)](#25. props 属性(父传子))
    • [26. mixin(混合)](#26. mixin(混合))
    • [27. scoped(局部样式)](#27. scoped(局部样式))
    • [28. less](#28. less)
    • [29. 路由](#29. 路由)
    • [30. 浏览器本地存储](#30. 浏览器本地存储)
    • [31. $emit $on 组件自定义事件(子传父)](#31. $emit $on 组件自定义事件(子传父))
    • [32. nextTick()](#32. nextTick())
    • [33. 插槽](#33. 插槽)
  • [Vue 3](#Vue 3)
    • 注意事项
    • [0. 创建 vue3 工程](#0. 创建 vue3 工程)
    • [1. setup 函数](#1. setup 函数)
    • [2. ref 函数(为数据做响应式)](#2. ref 函数(为数据做响应式))
    • [3. reactive 函数(处理对象响应式)](#3. reactive 函数(处理对象响应式))
    • [4. 新增/删除属性](#4. 新增/删除属性)
    • [5. computed 计算属性](#5. computed 计算属性)
    • [6. watch 数据监视](#6. watch 数据监视)
    • [7. watchEffect](#7. watchEffect)
    • [8. 生命周期](#8. 生命周期)
    • [9. hook (复用代码)](#9. hook (复用代码))
    • [10. toRef 和 toRefs](#10. toRef 和 toRefs)
    • [11. shallowReactive](#11. shallowReactive)
    • [12. readonly 和 shallowReadOnly](#12. readonly 和 shallowReadOnly)
    • [13. toRaw 和 markRaw](#13. toRaw 和 markRaw)
    • [14. provide 和 inject](#14. provide 和 inject)
    • 15.响应式数据判断
    • [16. Router (路由)](#16. Router (路由))
    • [17. pinia 状态管理器使用](#17. pinia 状态管理器使用)
    • [18. ref 获取 DOM 元素](#18. ref 获取 DOM 元素)

小白 Vue 3 学习

一些名词

  • Node.js

    Node.js 是一个基于 Chrome V8 引擎的 Javascript 运行环境

  • NPM (Node Package Manager)

    软件包仓库

软件安装

VSCode 中的一些设置

1. 关闭eslint检查

在 src/vue.config.js 文件中加入

javascript 复制代码
module.exports = {
// 避免Eslint报错
lintOnSave: false
}

tsconfig.json 配置文件

typescript 复制代码
{
"compilerOptions": {
 /* 访问 https://aka.ms/tsconfig.json 以阅读有关此文件的更多信息 */


 /* 基本选项 */
 "incremental": true,                   /* 启用增量编译 */
 "target": "ESNEXT",                    /* 指定 ECMAScript 目标版本:'ES3'、'ES5'(默认)、'ES2015'、'ES2016'、'ES2017'、'ES2018'、'ES2019'、'ES2020' 或 'ESNEXT'。 */
 "module": "commonjs",                  /* 指定模块代码生成:"none"、"commonjs"、"amd"、"system"、"umd"、"es2015"、"es2020"或"ESNext"。 */
 "lib": [],                             /* 指定要包含在编译中的库文件。 */
 "allowJs": true,                       /* 允许编译 javascript 文件。 */
 "checkJs": true,                       /* 报告 .js 文件中的错误。 */
 "jsx": "preserve",                     /* 指定 JSX 代码生成:'preserve'、'react-native' 或 'react'。 */
 "declaration": true,                   /* 生成相应的".d.ts"文件。 */
 "declarationMap": true,                /* 为每个对应的".d.ts"文件生成一个源映射。 */
 "sourceMap": true,                     /* 生成相应的".map"文件。 */
 "outFile": "./",                       /* 连接输出到单个文件。 */
 "outDir": "./",                        /* 将输出结构重定向到目录。 */
 "rootDir": "./",                       /* 指定输入文件的根目录。用于通过 --outDir 控制输出目录结构。 */
 "composite": true,                     /* 启用项目编译 */
 "tsBuildInfoFile": "./",               /* 指定文件存放增量编译信息 */
 "removeComments": true,                /* 不要向输出发出注释(删除除代码注释)。 */
 "noEmit": true,                        /* 不发出输出(不生成编译后的文件)。 */
 "noEmitOnError": true,                 /* 在输出js代码时,如果有错将不编译文件。 */
 "importHelpers": true,                 /* 从 'tslib' 导入发射助手。 */
 "downlevelIteration": true,            /* 以"ES5"或"ES3"为目标时,为"for-of"、展开和解构中的迭代提供全面支持。 */
 "isolatedModules": true,               /* 将每个文件转换为一个单独的模块(类似于 'ts.transpileModule')。 */


 /* 严格的类型检查选项 */
 "strict": true,                        /* 启用所有严格的类型检查选项。 在开发中,建议将stricet这类选项都开启。 */
 "strictNullChecks": true,              /* 启用严格的空(undefined、null)检查,可以防止"未定义不是对象"。 建议开启*/
 "strictFunctionTypes": true,           /* 启用函数类型的严格检查。 */
 "strictBindCallApply": true,           /* 在函数上启用严格的"绑定"、"调用"、应用"方法。 */
 "strictPropertyInitialization": true,  /* 启用对类中属性初始化的严格检查。 */
 "noImplicitThis": true,                /* 使用隐含的"any"类型在"this"表达式上引发错误。 */
 "noImplicitAny": true,                 /* 使用隐含的"any"类型在表达式和声明上引发错误(主要用于控制变量、参数是否必须知道它们的类型【类型检查】),如果是将JavaScript迁移到TypeScript时,可以关闭此项,但不建议这样做。 */
 "alwaysStrict": true,                  /* 以严格模式解析并为每个源文件发出"使用严格"。 */


 /* 额外检查 */
 "noUnusedLocals": true,                /* 报告未使用的本地人的错误。 */
 "noUnusedParameters": true,            /* 报告未使用参数的错误。 */
 "noImplicitReturns": true,             /* 不是函数中的所有代码路径都返回值时报告错误。 */
 "noFallthroughCasesInSwitch": true,    /* 在 switch 语句中报告失败情况的错误。 */


 /* 模块分辨率选项 */
 "moduleResolution": "node",            /* 指定模块解析策略:'node' (Node.js) 或 'classic' (TypeScript pre-1.6)。 */
 "baseUrl": "./",                       /* 解析非绝对模块名称的基目录。 */
 "paths": {},                           /* 一系列将导入重新映射到相对于"baseUrl"的查找位置的条目。 */
 "rootDirs": [],                        /* 根文件夹列表,其组合内容代表运行时项目的结构。 */
 "typeRoots": [],                       /* 包含类型定义的文件夹列表。 */
 "types": [],                           /* 类型声明文件要包含在编译中。 */
 "allowSyntheticDefaultImports": true,  /* 允许从没有默认导出的模块中默认导入。 这不会影响代码发出,只是类型检查。 */
 "esModuleInterop": true,               /* 通过为所有导入创建命名空间对象,在 CommonJS 和 ES 模块之间启用发射互操作性。 暗示"allowSyntheticDefaultImports"。 */
 "preserveSymlinks": true,              /* 不解析符号链接的真实路径。 */
 "allowUmdGlobalAccess": true,          /* 允许从模块访问 UMD 全局变量。 */


 /* 源映射选项 */
 "sourceRoot": "",                      /* 指定调试器应该定位 TypeScript 文件而不是源位置的位置。 */
 "mapRoot": "",                         /* 指定调试器应该定位映射文件而不是生成位置的位置。 */
 "inlineSourceMap": true,               /* 发出带有源映射的单个文件而不是单独的文件。 */
 "inlineSources": true,                 /* 在单个文件中与源映射一起发出源; 需要设置"--inlineSourceMap"或"--sourceMap"。 */


 /* 实验选项 */
 "experimentalDecorators": true,        /* 启用对 ES7 装饰器的实验性支持。 */
 "emitDecoratorMetadata": true,         /* 为装饰器的发射类型元数据启用实验性支持。 */


 /* 高级选项 */
 "skipLibCheck": true,                     /* 跳过声明文件的类型检查。 */
 "forceConsistentCasingInFileNames": true  /* 禁止对同一文件的大小写不一致的引用。 */
}
}

2. ts 文件引用报红

在 src 下创建文件 vite-env.d.ts

typescript 复制代码
/// <reference types="vite/client" />

interface ImportMetaEnv {
readonly VITE_BASE_URL: string;
readonly VITE_BASE_WS: string;
// 更多环境变量...
}

interface ImportMeta {
readonly env: ImportMetaEnv;
}

declare module "*.vue" {
import type { DefineComponent } from "vue";
const component: DefineComponent<{}, {}, any>;
export default component;
}

// 原生交互参数定义
interface Window {
$message: any
}

declare module 'qrcodejs2-fix';

相对路径写法

'./' -- 当前所在目录,可不写

'.../' -- 上一级目录

'/' -- 根目录

常见图片格式和区别

jpg .jpg/.jpeg 有损压缩 占用空间小
png .png 无损压缩 占用空间略大
bmp .bmp 不压缩 占用空间极大
gif .gif 动态图

目录结构

api 与后端交互的接口,协议

assets

icon 图标

images 图片

style 样式

components 公共组件

layouts 项目整体布局

loacles 多语言

router 路由

store 前端数据缓存 (项目中用 pinia)

types 定义数据结构

utils 工具类

view 视图

JS/TS

1. prototype(原型对象)

类似于继承,所有对象上都有 [[Prototype]] 属性,代表父类中的方法

所有的 JavaScript 对象都会从一个 prototype(原型对象)中继承属性和方法

  • Date 对象从 Date.prototype 继承。
  • Array 对象从 Array.prototype 继承。
  • Person 对象从 Person.prototype 继承。
javascript 复制代码
var TestPrototype = function () {
    this.propA = 1;
    this.methodA = function() {
        return this.propA;
    }
}

TestPrototype.prototype = {
    methodB: function() {
        return this.propA;
    }
}

var objA = new TestPrototype();
var objB = new TestPrototype();

objA.methodA() // 1
objA.methodB() // 1

objA === objB 	// false
objA.methodA === objB.methodA	// false
objA.methodB === objB.methodB	// true

2. 导入/导出

  1. 导出

    typescript 复制代码
    ①默认导出:export default Test(导入时可指定模块任意名称,无需知晓内部真实名称)
    ②单独导出:export const name = "Bruce"
    ③按需导出:export { age, name, sex }(推荐)
    ④改名导出:export { name as newName }
  2. 导入

    typescript 复制代码
    ①默认导入:import Test from "test"
    ②整体导入:import * as Test from "test"
    ③按需导入:import { age, name, sex } from "test"
    ④改名导入:import { name as newName } from "test"

3. 去除字符串两端空格

typescript 复制代码
//trim()例子
let str = ' hello '
console.log(str.trim()) //hello

4. 一些特殊语法糖

  1. !

    非空断言操作符

    用于断言操作对象是非 null 和非 undefined 类型

    typescript 复制代码
    type HandleChange= () => void;
    
    function myFunc(onChange: HandleChange | undefined) {
    	//如果不加!,会报错
    	const a = onChange(); // Error
    	const b = onChange!(); //OK
    }
  2. ?.

    遇到 null 或 undefined 就可以立即停止表达式的运行

  3. ??

    当左侧操作数为 null 或 undefined 时,其返回右侧的操作数,否则返回左侧的操作数

    typescript 复制代码
    console.log(false ?? '哈哈哈')  // false
    console.log(null ?? '哈哈哈')  // 哈哈哈

5. 深拷贝

typescript 复制代码
let deepObj = JSON.parse(JSON.stringify(obj));

6. 拼接两个数组

typescript 复制代码
let arr = [1, 2]
let arr2 = [3, 4]

arr = [...arr, ...arr2]

console.log(arr)
// [1, 2, 3, 4]

7. JSON

  • JSON.parse() 将字符串转换为 JavaScript 对象。

    typescript 复制代码
    // JSON.parse(text[, reviver])	
    // text: 一个有效的 JSON 字符串, reviver: 一个转换结果的函数, 将为对象的每个成员调用此函数。
    let obj = JSON.parse('{ "name":"runoob", "alexa":10000, "site":"www.runoob.com" }', (key, value) => {
        if(key) {
            console.log(`读取到${key}属性,值为:${value}`)
        }
    });
    // 读取到name属性,值为:runoob
    // Game.vue:13 读取到alexa属性,值为:10000
    // Game.vue:13 读取到site属性,值为:www.runoob.com
  • JSON.stringify() 将 JavaScript 对象转换为字符串。

    typescript 复制代码
    // JSON.stringify(value[, replacer[, space]])
    // value: 要转换的 JavaScript 值(通常为对象或数组) replacer 传入每个成员的键和值。使用返回值 
    let obj = { 
        "name":"runoob", 
        "alexa":10000, 
        "site":"www.runoob.com"
    }
    
    let myJson = JSON.stringify(obj)
    console.log(myJson)
    // {"name":"runoob","alexa":10000,"site":"www.runoob.com"}

DOM

一些常用属性

  1. scrollTop, scrollHeight, clientHeight

    • scrollTop:元素顶部到元素可视区域顶部的像素距离(可读写)。
    • scrollHeight:类似于clientHeight,但包括由于overflow属性不可见内容的高度。
    • clientHeight:元素的像素高度,包括盒子内容content和内边距padding, 不包括边框外边距和水平滚动条(只读)

    滚动到底部判断:element.scrollHeight-element.scrollTop=element.clientHeight

HTML

结构代码展示

html 复制代码
<!-- 在 VSCode 中键入一个 '!' 回车可自动补齐 -->

<!DOCTYPE HTML> <!-- HTML5标准网页声明 -->
<HTML lang="en"> <!-- HTML为根标签,代表整个网页  zh-CN -->

<head> <!-- head为头部标签,一般用来描述文档的各种属性和信息, 包括标题等-->
  <meta charset="UTF-8"> <!-- 设置字符集为utf-8 -->
  <title>my HTML</title> <!-- 设置浏览器的标题 -->
</head>

<!-- 网页所有的内容都写在body标签内 -->
<body> 
  我的第一个HTML网页
</body>

</HTML>

块级元素与行内元素

块级元素:独占一行,块级元素内能写任何元素

行内元素:不独占一行,行内元素内能写行内元素,但不能写块级元素

标签参考

容器标签

html 复制代码
<div> </div>

1. 文本标签

常用:

em 用户着重阅读的内容
strong 表示文本十分重要,一般用粗体显示
span 元素是短语内容的通用行内容器,并没有任何特殊语义。

不常用:

cite 表示一个作品的引用,且必须包含作品的标题
dfn 特殊术语,或专属名词
del 与 ins 删除的文字内容【与】插入文档中的文本
sub 与 sup 下标文字【与】上标文字
code 一段代码
samp 标识计算机程序输出
kbd 键盘输入元素,用于表示用户输入
addr 联系信息,说明,配合 title 属性使用
bdo 改写了文本的方向性,配合 dir 属性使用
var 变量
address 某个人或某个组织(等等)的联系信息。

2. 图片标签

标签名 属性 说明
img src(相对路径),alt(图像描述,利于搜索) 单标签

3. 超链接

标签名 属性 说明
img href(跳转网址),target(新页面从哪打开) download="name"(将链接的 URL 视为下载资源) 单标签,超链接

通过超链接跳转锚点:

html 复制代码
<body>
    <a href="#5">测试超链接跳转锚点</a>
    <p>我是锚点1</p>
    <p>我是锚点2</p>
    <p>我是锚点3</p>
    <p>我是锚点4</p>
    <p id="5">我是锚点5</p>
</body>

<a href="#">回到顶部</a> <!-- 回到顶部 -->

超链接唤起指定应用:

html 复制代码
<!-- 唤起设备拨号 -->
<a href="tel:10086">电话联系</a>
<!-- 唤起设备发送邮件 -->
<a href="mailto:10086@qq.com">邮件联系</a>
<!-- 唤起设备发送短信 -->
<a href="sms:10086">短信联系</a>

4. 列表

  • 4.1 ol (有序列表)

    html 复制代码
    <h2>把大象装进冰箱分几步</h2>
    <!-- 有序列表 -->
    <ol>
        <li>打开冰箱门</li>
        <li>大象放进去</li>
        <li>关上冰箱门</li>
    </ol>
  • 4.2 ul (无序列表)

    html 复制代码
    <h2>我想去的几个城市</h2>
    <!-- 无序列表 -->
    <ul>
        <li>云南</li>
        <li>成都</li>
        <li>重庆</li>
    </ul>
  • dl (自定义列表)

    html 复制代码
    <h2>我想去的几个城市</h2>
    <!-- 自定义列表 -->
    <dl>
        <dt>做好笔记</dt>
        <dd>好记性不如烂笔头</dd>
        <dt>多加练习</dt>
        <dd>实践出真知</dd>
        <dt>别怕失败</dt>
        <dd>失败是成功之母</dd>
    </dl>
  • 注意点

    1. 列表可嵌套使用

      html 复制代码
      <ul>
          <li>云南</li>
          <li>成都</li>
          <li>
              <span>上海</span>
              <ul>
                  <li>外滩</li>
                  <li>东方明珠</li>
                  <li>迪士尼乐园</li>
              </ul>
          </li>
      </ul>
    2. 自定义列表一个术语可有多个描述

      <dl>
          <dt>做好笔记</dt>
          <dd>好记性不如烂笔头</dd>
      	<dd>笔记可以是电子版或纸质版</dd>
      </dl>
      

5. 表格

html 复制代码
<!-- 
table属性:  border:外边框厚度  weight,height:宽高,不影响表头和脚注 cellspacing:边框间距离
thead属性:  allign:水平布局方式  vallign:垂直布局方式
tbody属性: 
tfoot属性:
th属性:	  colsspan:跨列  rowspan:跨行
-->
<table border="1">
    <caption>学生信息</caption>   <!-- 表格标题 -->
    <!-- 表格头部 -->
    <thead>               
        <tr>                <!-- 表格中的行 -->
            <th>姓名</th>     <!-- 表头单元格 -->
            <th>性别</th>
            <th>年龄</th>
            <th>民族</th>
            <th>政治面貌</th>
        </tr>
    </thead>

    <!-- 表格主体 -->
    <tbody>
        <tr>
            <td>张三</td>     <!-- 表体单元格 -->
            <td>男</td> 
            <td>18</td> 
            <td>汉族</td> 
            <td>团员</td> 
        </tr>

        <tr>
            <td>李四</td>
            <td>女</td> 
            <td>20</td> 
            <td>满族</td> 
            <td>群众</td> 
        </tr>
    </tbody>

    <!-- 表格脚注 -->
    <tfoot>
        <tr>
            <td></td>     <!-- 表体单元格 -->
            <td></td>
            <td></td>
            <td></td>
            <td>共计:4人</td>
        </tr>
    </tfoot>
</table>

6. 表单

表示文档中的一个区域,此区域包含交互控件,用于向 Web 服务器提交信息

html 复制代码
<!-- 属性:action:表单提交地址, -->
<form action="https://search.jd.com/search">
    用户名:<!-- 禁用 -->
    <input name="userName" value="hwm" disabled>
    性别:<!-- 单选框 -->
    <input type="radio" name="gender" value="male" checked>男   <!-- checked 默认 -->
    <input type="radio" name="gender" value="female">女
    <br>
    爱好:<!-- 复选框 -->
    <input type="checkbox" name="hobby" value="smoke" checked>抽烟
    <input type="checkbox" name="hobby" value="drink">喝酒
    <input type="checkbox" name="hobby" value="perm">烫头
    <br>
    其它:<!-- 文本域-->
    <textarea name="other" cols="23" row="3"></textarea>
    <br>
    籍贯:<!-- 下拉框 -->
    <select name="place">
        <option value="湘" selected>湖南</option>
        <option value="粤">广东</option>
        <option value="鲁">山东</option>
    </select>
    <br>
    用户不可见区域:<!-- 因隐藏域 -->
    <input type="hidden" name="tag" value="abc">
    <br>
    <input type="submit" value="提交">
    <input type="reset" value="重置">
    <button type="button">普通按钮</button>	<!-- 普通按钮 -->
</form>

<!-- 分类 -->
<fieldset>
    <legend> ... </legend>
    ...
</fieldset>

7. 输入框

html 复制代码
<!-- 属性
type:类型  value:默认值  maxlength:最大输入长度
-->

8.文本域

html 复制代码
<textarea name="other" cols="23" row="3"></textarea>

9.下拉框

html 复制代码
<select name="place">
    <option value="湘" selected>湖南</option>
    <option value="粤">广东</option>
    <option value="鲁">山东</option>
</select>

10.label 标签

html 复制代码
<!-- 表示用户界面中某个元素的说明 -->

11.补充常用标签

html 复制代码
<!-- 换行标签 -->
<br>

<!-- 分割线 -->
<hr>

<!-- 按原文显示 -->
<pre>

12.框架标签

html 复制代码
<!-- 将另一个 HTML 页面嵌入到当前页面中 -->
<!-- 可用 name 属性与<a>或<form>的 target 属性配合使用 -->
<iframe src="https://cn.bing.com/" width="1920" height="1080" frameborder="0">
</iframe>

13.字符实体

参考链接

全局属性

  1. id

    给标签指定唯一标识,id 不可重复

    作用:可让标签相关联

    注意:,,,

CSS

css 复制代码
h1 {
    color: red;
    font-size: 40px;
}
h2 {
    color: green;
    font-size: 60px;
}

样式

行内样式:写在标签内,只对改标签生效

内部样式:写在 html 文件 内,对整个 html 文件生效

外部样式:将 css 样式单独写在一个 .css 文件中,在 html 中使用 标签链接

优先级:行内 > 内部样式 = 外部样式 (后渲染的覆盖前渲染的)

选择器

  1. 通配选择器

    css 复制代码
    * {
        属性名: 属性值;
    }
  2. 元素选择器

    css 复制代码
    /* 为页面某种元素统一设置样式 */
    标签名 {
        属性名: 属性值;
    }
  3. 类选择器

    css 复制代码
    /* 为页面所有类名为 className 的元素设置样式 */
    .className {
        属性名: 属性值;
    }

    为标签同时设置两个类

    html 复制代码
    <p class="fish animal">
  4. id 选择器

    css 复制代码
    #IDName {
        属性名: 属性值;
    }
    
    /* html */
    <h1 id="idName">id 选择器</h1>
  5. 交集选择器

    5.1 元素选择器 & 类选择器

    css 复制代码
    标签名.className {
        属性名: 属性值;
    }
  6. 并集选择器

    css 复制代码
    ,类选择器
    ,元素选择器
    ,id 选择器 {
        属性名: 属性值;
    }
  7. 后代选择器(子类,子类的子类)

    CSS 复制代码
    父元素 后代元素 {
        属性名: 属性值;
    }
  8. 子代选择器

    css 复制代码
    父元素>子元素 {
        属性名: 属性值;
    }
  9. 兄弟选择器

    css 复制代码
    /* 往下找紧紧相邻的兄弟元素 */
    元素 + 兄弟元素 {
        属性名: 属性值;
    }
    
    /* 元素后所有兄弟元素 */
    元素 ~ 兄兄弟元素 {
        属性名: 属性值;
    }
  10. 属性选择器

    css 复制代码
    /* 1.选中具有 title 属性的元素 */
    [title] {
        属性名: 属性值;
    }
    
    /* 2.选中具有 title 属性,且 title 属性为 "tt" 的元素 */
    [title="tt"] {
        属性名: 属性值;
    }
    
    /* 3.选中具有 title 属性,且 title 属性为 "tt" 开头的元素 */
    [title^="tt"] {
        属性名: 属性值;
    }
    
    /* 4.选中具有 title 属性,且 title 属性为 "tt" 结尾的元素 */
    [title$="tt"] {
        属性名: 属性值;
    }
    
    /* 4.选中具有 title 属性,且 title 属性为包含 "tt" 的元素 */
    [title*="tt"] {
        属性名: 属性值;
    }
  11. 动态伪类选择器

    css 复制代码
    /* 和类相似,但不是类,元素特殊状态的一种描述 */
    
    /*
    link visited 是 <a> 的特有状态 
    focus 是表单类特有
    */
    
    /* --------------------  动态伪类 ---------------------- */
    /* 没有访问过的 a 元素 */
    a:link {
        属性名: 属性值;
    }
    /* 访问过的 a 元素 */
    a:visited {
        属性名: 属性值;
    }
    /* 鼠标悬浮的 a 元素 */
    a:hover {
        属性名: 属性值;
    }
    /* 激活状态的 a 元素 */
    a:active {
        属性名: 属性值;
    }
    /* 获取焦点 */
    input:focus {
        属性名: 属性值;
    }
    
    /* --------------------  结构伪类 ---------------------- */
    /* 第一个子元素是否满足条件,满足渲染 */
    div>p:first-child {
        属性名: 属性值;
    }
    /* 最后一个子元素是否满足条件,满足渲染 */
    div>p:last-child {
        属性名: 属性值;
    }
    /* 第 n 个子元素是否满足条件,满足渲染,子元素从 1 开始计算*/
    /* n 从 0 开始增加 */
    div>p:nth-child(n) {
        属性名: 属性值;
    }
    
    /* 只在指定类型中找,非此类型不参与 */
    :fist-of-type
    :last-of-type
    :nth-of-type
    
    /* --------------------  否定伪类 ---------------------- */
    :div>p:not(.fial) {
        属性名: 属性值;
    }
    
    /* --------------------  UI伪类 ---------------------- */
    :checked {
        属性名: 属性值;
    }
    :disabled {
        属性名: 属性值;
    }
    
    /* --------------------  目标伪类 ---------------------- */
    :target { /* 锚点指向的元素 */
        属性名: 属性值;
    }
    
    /* --------------------  语言伪类 标签 lang 属性 ---------------------- */
    :lang(语言类型) {
        属性名: 属性值;
    }
    
    /* --------------------  伪元素(像元素,但不是,是元素中的一些特殊位置)选择器 ---------------------- */
    /* 第一个字母 */
    ::first-letter {
        属性名: 属性值;
    }
    /* 第一行 */
    ::first-line {
        属性名: 属性值;
    }
    /* 选中的文字 */
    ::selection {
        属性名: 属性值;
    }
    /* 提示颜色 */
    ::placeholder {
        属性名: 属性值;
    }
    /* 在元素最前面 */
    ::before {
        content: Y
        属性名: 属性值;
    }
    /* 在元素最后面 */
    ::after {
        content: Y
        属性名: 属性值;
    }

选择器优先级

简单的:!important > 行内样式 > id 选择器 > 类选择器 > 元素选择器 > 通配选择器 > 继承样式

公式计算:

(a,b,c)

a:id 选择器个数

b:类,伪类,属性 选择器个数

c:元素,伪元素 选择器个数

从 a -> b -> c 依次比较,大的优先级高

可在 vscode 中将鼠标放到选择器上查看

CSS 三大特性

  • 层叠性

  • 继承性

    元素自动拥有其父元素,或其祖先元素上设置的某些样式

    规则:优先继承近的

    常见可继承属性:text-?? font-?? line-?? color

    可在 MDN 查看元素是否可继承

  • 优先级

字体属性

  1. font-size 字体大小

    • 可以给 body 指定整个页面的文字大小
    • 可在 设置 -> 外观 中调整字体最小字号和字体默认大小
  2. font-family 字体

  3. font-style 字体风格

    • italic 斜体
    • normal 正常
  4. font-weight 字体粗细

    • lighter 细的

    • normal 正常

    • bold 粗体

    • 数字 100 -900(跟字体设计精度有关)

  5. 字体复合属性

    html 复制代码
    body {
    		font: font-style font-weight  font-size/line-height font-family;
    }
    • 使用 font 属性时,必须按上面的语法格式中的顺序书写,不得更换顺序,并且各个属性间以空格隔开。
    • 不需要设置的属性可以省略(取默认值),但必须保留 font-size 和 font-family 属性,否则 font 属性不起作用。

文本属性

  1. color 文本颜色

    css 复制代码
    /* color: red; */
    /* color: rgb(255, 0, 0); */
    /* color: rgba(255, 0, 0, 0.5); */
    color: #ff0000;
  2. 文本间距

    • letter-spacing 字符间距
    • word-spacing 单词间距(根据空格识别单词)
    • 可给负值,缩小字符间距
  3. text-decoration 文本修饰

    属性 说明
    overline 上划线
    underline 下划线
    line-through 删除线
    wavy 波浪线
    css 复制代码
    text-decoration: overline underline wavy blue 5px;
  4. text-indent 文本缩进

    css 复制代码
    text-indent: 40px;
  5. 文本对齐

    • text-align 水平对齐

      left center right

    • line-height 行高

    • 文本垂直对齐

      顶部:默认

      居中:单行文字:height = line-height

      底部:单行文字:line-height = (height x 2) - font-size -x

  6. vertical-align

    参考 MDN

    该属性定义行内元素的基线相对于该元素所在行的基线的垂直对齐。

    只对行内元素、行内块元素和表格单元格元素生效:不能用它垂直对齐块级元素

列表属性

  1. list-style-type:列表符号
  2. list-style-position:指定标记框在主体块框中的位置
  3. list-style-image:自定义列表元素标记的图片

边框属性

  1. border-width
  2. border-style
  3. border-color
  4. border(复合属性)

表格属性

  1. table-layout:控制表格列宽
  2. border-spacing:控制单元格间距
  3. border-collapse:合并相邻单元格的边框

背景属性

  1. background-color:背景颜色,transparent
  2. background-image:会平铺整个区域
  3. background-repeat:设置背景图片的重复方式
  4. background-position:设置背景图片的位置

鼠标相关属性

  1. cursor:光标样式

长度单位

  1. px:像素
  2. em:相对于当前元素的 font-size 的倍数,先找父元素的 font-size,最后浏览器默认 font-size
  3. %:相对于父元素的百分比

元素的显示模式

  1. 块元素(block)

    特点:

    • 在页面独占一行
    • 默认宽度:撑满整个父元素
    • 默认高度:由内容撑开
    • 可以通过 css 修改宽高

    代表元素:

    • 主体结构标签:

    • 排版标签:

      -

      *** ** * ** ***
      复制代码
    • 列表标签:
      *
      1.
      :
      2. 表格相关标签:

  2. 行内元素(inline)

    特点:

    • 在页面不独占一行
    • 默认宽度:由内容撑开
    • 默认高度:由内容撑开
    • 无法通过 css 修改宽高

    代表元素:

    • 文本标签:br em strong sup sub del ins
  3. 行内块元素(inline-block)

    特点:

    • 在页面不独占一行
    • 默认宽度:由内容撑开
    • 默认高度:由内容撑开
    • 可以通过 css 修改宽高

    代表元素:

    • 图片:
    • 单元格:
    • 表单控件:

修改元素显示模式

  • display
    block: 块元素,none:不显示,inline:行内元素,inline-block:行内块元素

盒子模型的组成部分

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l27Gr60g-1689749017403)(C:\Users\cli08\AppData\Roaming\Typora\typora-user-images\image-20230712181229789.png)]

  • content(内容):元素中的文本或后代元素都是它的内容
  • padding(内边距):紧贴内容的补白区域
  • border(边框):盒子的边距
  • margin(外边框):盒子与外界的距离

盒子的大小 = content + 左右 padding + 左右 border

注意:外边距 margin 不会影响盒子的大小,但会影响盒子的位置

  • content

    min-width,max-width,min-height,max-height

    width,height

  • padding

    padding-left...

    padding:(上下)(左右) (上)(右)(下)(左)

    注意:padding 不能为负数,行内元素上下内边距设置会不占位置

  • border

    border-width,border-color,border-style

    border:width,style,color

    border-left-width...,border-left-colo...,border-left-style...

    border-left...

  • margin

    属性同 padding

隐藏元素的方式

  1. visibility:设置为隐藏元素占位
  2. display:设置为隐藏不占位

float 浮动

指定一个元素应沿其容器的左侧或右侧放置,允许文本和内联元素环绕它

属性值:left | right

浮动后的特点

  1. 脱离文档流
  2. 默认宽高被内容撑开,可手动设置宽高
  3. 不会独占一行,能与其它元素公用一行

overflow 处理内容溢出

overflow: visible 可见

overflow: hidden 隐藏

overflow: scroll 滚动条

overflow: auto 超出显示滚动条

overflow-x

overflow-y

元素之间的空白问题

产生原因:行内元素,行内块元素,彼此之间的换行会被浏览器解析为一个空白字符

解决方案:给父元素设置 font-size: 0,再给需要显示文字的元素单独设置字体大小

position 定位

定位的元素层级较高

都写了定位,后写的层级高

relative 相对定位

left | top | right | bottom

特点:

  • 参考系:相对于正常位置的偏移
  • 不会脱离文档流,不会对其它元素产生影响

absolute 绝对定位

left | top | right | bottom

特点:

  • 脱离文档流
  • 绝对定位和浮动不能一起用
  • 开启绝对定位后成为定位元素:宽高由内容撑开,宽高可更改
  • 参考系:包含块
  • 包含块:
    1. 对于没有脱离文档流的元素,包含块为其父元素
    2. 对于脱离文档流的元素,包含块是第一个拥有定位属性的祖先元素(如果内衣,包含块就是整个页面)

fixed 固定定位

left | top | right | bottom

特点:

  • 脱离文档流
  • 参考系:视口,元素一直在视口中
  • 不能和浮动同时使用

sticky 粘性定位

left | top | right | bottom(胶水生效位置)

特点:

  • 不脱离文档流
  • 参考系:离它最近的一个拥有"滚动机制的祖先元素"
  • 可以和浮动一起设置(不推荐)

z-index 定位的层级

auto 默认 | 0 | 1 | 2

只能在设置了定位的元素上设置

CSS3

长度单位

  1. vw:视口宽度的百分比
  2. vh:视口高度的百分比

新增盒子属性

  1. box-sizing

    border-box:设置的边框和内边距的值是包含在 width 内的,如果你将一个元素的 width 设为 100px,那么这 100px 会包含它的 border 和 padding

    content-box:默认值。如果你设置一个元素的宽为 100px,那么这个元素的内容区会有 100px 宽,并且任何边框和内边距的宽度都会被增加到最后绘制出来的元素宽度中。

  2. resize

    both | horizontal | vertical | none 用于设置元素是否可调整尺寸,以及可调整的方向。

    要设置 overflow

  3. box-dhadow

    css 复制代码
    /* x 偏移量 | y 偏移量 | 阴影颜色 */
    box-shadow: 60px -16px teal;
    
    /* x 偏移量 | y 偏移量 | 阴影模糊半径 | 阴影颜色 */
    box-shadow: 10px 5px 5px black;
    
    /* x 偏移量 | y 偏移量 | 阴影模糊半径 | 阴影扩散半径 | 阴影颜色 */
    box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2);
  4. opacity

    透明度

新增背景属性

  1. background-orgin

    背景图原点,起始点

    padding-box | content-box | border-box

  2. background-clip

    对背景图修剪,显示背景图区域

    padding-box | border-box | content-box | text

  3. backgronud-size

    背景图尺寸

    宽高 | %% | contain(宽高等比例缩放,背景再重复) | cover(宽高等比例缩放,宽或高自适应后截取)

多列布局

column-count:直接指定列数

column-width:指定每列宽度

cloumn-gap:列间距

column-rule:边框像素,样式,颜色

column-span:跨列

弹性布局

特点:子元素块状化,变为块元素

属性值:display:flex(弹性布局) | inline-flex(不常用)

  1. 主轴方向

    flex-direction:row(行,左到右) | column(列,上到下) | row-reverse(右到左) | column-reverse(下到上)

  2. 主轴换行方式

    flex-wrap:nowrap(不换行,压缩子元素) | wrap(自动换行,副轴平分空间) | wrap-reverse(反向换行)

  3. 主轴对齐方式

    justify-content:

    1. flex-start:主轴起始位置
    2. flex-end:主轴结束位置
    3. center:中间对齐
    4. space-around:子项均匀分布,子项与子项之间的距离,是子项与边缘之间距离的两倍
    5. space-between:子项均匀分布,子项与子项之间的距离是相等的,子项与边缘无距离
    6. space-evenly:子项均匀分布
  4. 侧轴对齐方式

    单行:align-item:

    1. flex-start:侧轴起始位置对齐
    2. flex-end:侧轴结束位置对齐
    3. center:侧轴中间位置对齐
    4. stretch(默认值):拉伸到整个父容器

    多行:align-content:

    1. flex-start:侧轴起始位置对齐
    2. flex-end:侧轴结束位置对齐
    3. center:侧轴中间位置对齐
    4. space-around:同主轴
    5. space-between:同主轴
    6. space-evenly:同主轴
    7. stretch(默认值):同侧轴
  5. 水平垂直居中

    css 复制代码
    方案一:
    justify-content: center
    align-items:center
    方案二:
    父容器:display: flex
    子项:margin:auto

cas_websited

0. 项目中学到的一些技巧

  1. 给组件传值

    html 复制代码
    <isLike :unlike="msgInfo.unlike" :like="msgInfo.like" :status="msgInfo.status" size="s" :faqID="faqID"></isLike>
    typescript 复制代码
    const props = defineProps({
        // 踩
        unlike:{
            type:Number,
            dafault:0
        },
        // 点赞
        like:{
            type:Number,
            dafault:0
        },
        // 当前用户是否点赞
        status:{
            type:Number,
            default:0
        },
        // 图标尺寸 S M
        size:{
            type:String,
            default:'s'
        },
        //faqid
        faqID:{
            type:Number,
            default:1
        }
    })

1. 指令

npm run dev

npm run dev --mode test

2. 协议对接

  1. 确定开发环境
    .env.development 本地开发环境
    .env.production 生产环境
    .env.test 测试环境
  2. 修改对应环境下的 VITE_BASE_URL

3. 请求服务器

typescript 复制代码
// 示例
interface msgListReq  {
    UpDown: number | null,
    ID: number | null,
}

export const apiMsgList = (data: msgListReq) => {
    return axios.request({
      url: "/msg/list",
      method: "post",
      data
    })
}

export const result = (data: {OrderID: number, Count: number}) => {
  return axios.request({
    url: "/order/info",
    method: "post",
    data,
  })
}

// 使用
apiMsgList({UpDown: 0, ID: msgList.value[0].ID}).then(res => {
    if(!res.data.List || res.data.List.length == 0) return   // 历史消息为空,不处理
    res.data.List.reverse()
    msgList.value = [...res.data.List, ...msgList.value]
})

4. 上拉加载历史消息(滑动条保持原高度)

let scrollTop = document.documentElement.scrollTop;//滚动高度

let clientHeight = document.documentElement.clientHeight;//可视高度

let scrollHeight = document.documentElement.scrollHeight;//内容高度

typescript 复制代码
function handleScroll(e:any) {
  // 滚动条到顶部时,出现loading状态,接口请求完毕,关闭loading状态
  if (msg.value!.scrollTop <= 0) {
      scrollVal = msg.value!.scrollHeight   //  记录下当前的滑动条高度
      apiMsgList({ UpDown: 0, ID: msgList.value[0].ID }).then(res => {
        show.value = true
        if (!res.data.List || res.data.List.length == 0){ // 历史消息为空,不处理
          show.value = false
          return
        }    
        setTimeout(() => {
          res.data.List.reverse()
          msgList.value = [...res.data.List, ...msgList.value]
          nextTick(() => {
            msg.value!.scrollTop = msg.value!.scrollHeight - scrollVal
            show.value = false
          })
        }, 500);  
      })
  } else {
      show.value = false
  }
}

5. 滑动条定位

typescript 复制代码
nextTick(() => {
    var targetDom: any = document.querySelector('.isActive')
    var boxDom: any = document.querySelector('.main_left')
    var st = targetDom.getBoundingClientRect().top
    boxDom.scrollTop = boxDom.scrollTop + st - 75 - 70 - 15
})

Vue 2

0. 总结

  • data

    Vue 实例的数据对象。Vue 会递归地把 data 的 property 转换为 getter/setter,从而让 data 的 property 能够响应数据变化
    : ' v m . : `vm. :'vm.data访问原始数据对象。访问vm.a等价于访问vm. d a t a . a ' 。 v m . data.a`。 vm. data.a'。vm.watch

  • el

    只在用 new 创建实例时生效

    提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标。可以是 CSS 选择器,也可以是一个 HTMLElement 实例。

1. 初识 vue

html 复制代码
<!-- 
    1.想让 Vue 工作,就必须创建一个 Vue 实例,且要传入一个配置对象
    2.root容器里的代码依然符合 html 规范,只不过混入了一些特殊的 Vue 语法
    3.root容器里的代码被称为 Vue 对象
    4.Vue 实例与容器一一对应
    5.真实开发中只有一个 Vue 实例,并且会配合组件一起使用
    6.容器中的 {{}} 可写 vue 实例中对象的属性或者 js 表达式
    7.data 中的数据发生改变,魔板中用到该数据的地方会自动更新
    8.在浏览器中可通过 vue.js devtools Root 中查看或临时更改 data 中的属性
	9.Vue 实例数据结构可嵌套
-->

<div id="root">
    <h1>Hello, {{name.toUpperCase()}},{{age}},{{1+1}}</h1>
    <h1>学校:{{school.name}},地址:{{school.address}}</h1>
</div>

<script type="text/javascript">
    Vue.config.productionTip = false    // 阻止 vue 在启动时生成提示

    // data 对象中的数据会做数据代理,既 get set,method 对象中的数据不会坐数据代理,里面存放方法
    // method 中的方法不要用箭头函数,会导致 this 指向对象为 window (正常为 vm)
    const x = new Vue({
        el:'#root',     // el 指定当前 vue 实例为哪个容器服务,值为 css 选择器
        data:{          // data 用于存储数据,数据提供给 el 所指定的容器使用 {{name}}
            name:"hwm",
            age:18,
            school:{
                name:"hufe",
                address:"changsha"
            },
        methods: {
                showInfo1(event) {
                    console.log(this)
                    console.log(event)
                },
                showInfo2(event, num) {
                    console.log(event, num)
                }
            }
        }
    })
</script>

2. 模板语法(V-bind,v-model)

  1. 插值语法

    html 复制代码
    <h1>Hello, {{name.toUpperCase()}},{{age}},{{1+1}}</h1>
    
    data:{
    	name:"hwm",
    	age:18,
    }
  2. 指令语法

    • v-bind(:):

      单向绑定

      响应式的更新html属性(在元素节点的属性上绑定 vue 的 data 数据)

      语法糖:v-bind: 简写为 :

      注意事项:v-bind: 后的 "" 中的值不是表示字符串,而是表示 vue 中的 data 中的属性

      html 复制代码
      <a v-bind:href="url" target="_blank">点我,去百度</a>
      <!-- vue 中的 date -->
      data:{
      	url:"http://www.baidu.com",
      }
    • v-model(在表单中收集 value 值)

      双向绑定

      只能应用在表单类元素上

      语法糖:省略 value, v-model=""

      修饰符:.number .lazy(失去焦点再收集) trim(去除前后空格)

      html 复制代码
      <div id="root">
          单向数据绑定:<input type="text" :value="iV1"/></br>
      	双向数据绑定:<input type="text" v-model="iV1"/></br>
      	修饰符:<input type="number" v-model.number="age"/></br>
      		   <input type='text' v-model.lazy="age"/></br>
      </div>
      
      data:{
      	iV1: "hwm",
      },

3. vue 实例两种写法

typescript 复制代码
// 第一种
new Vue({
    el:"#root",     // el 指定当前 vue 实例为哪个容器服务,值为 css 选择器
    data:{          // data 用于存储数据,数据提供给 el 所指定的容器使用 {{name}}
    	name:"ming",
    }
})

// 第二种
const vm = new Vue({
    data(){
    	return {
            name:"ming",
        }
    }
})
vm.$model("#root")

4. Object.defineProperty() 给对象添加属性

注意:通过此方法添加的属性,不在枚举内

定义(添加、修改)对象的属性

Object.defineProperty(对象,属性名,配置项(value))

typescript 复制代码
let student = {
    name:"ming",
    sex:"男",
}
let num = 18

Object.defineProperty(student, "age", {
    value:18,
    enumerable: true,   // 控制属性是否可枚举,默认 false
    writable: true,     // 控制属性是否可更改,默认 false
    configurable: true, // 控制属性是否可删除,默认 false
    get() {             // 获取 age 属性时调用
        return num
    },
    set(value) {        // 设置 age 属性时调用
        num = value
    }
})

5. Object.keys(对象)

遍历获取到对象上的所有 key 属性

6. v-on(事件处理)

事件处理

v-on 可简写 @

typescript 复制代码
new Vue({
    el:"#root",
    data() {
        return {

        }
    },
    methods: {
        showInfo1(event) {
            console.log(event)
        },
        showInfo2(event, num) {
            console.log(event, num)
        }
    }
})

// 使用
/* <div id="root">
    <button @click="showInfo1">Hello111(不传参,默认传event)</button>
	<button @click="showInfo2($event, 66)">Hello222(传参, $event 是默认值)</button>
</div> */

7. 事件修饰符

  1. prevent:阻止默认事件
  2. stop:阻止事件冒泡(阻止一层冒泡)
  3. once:事件只触发一次
  4. capture:使用事件的捕获模式
  5. self:只有 event.target 是当前操作的元素时才触发事件
  6. passive:事件的默认行为立即执行,无需等待事件的回调执行完成
html 复制代码
<button @click.once="addPerson">添加一个老刘</button>

8. 键盘事件

@keyup

@keydown

html 复制代码
<!-- 为提供别名的按键可使用按键原始的 key 绑定,两个单词组成的键要写为 caps-lock -->
<input type="text" @keyup.enter="showInfo">

9. methods(方法)

html 复制代码
<button @click.once="addPerson">添加一个老刘</button>
const vm = new Vue({
    el: '#app',
    data: {
        firstName:"张",
        lastName:"三",
    },
    methods: {
        addPerson(e) {
            console.log(e)
        }
    },
}

10. computed(计算属性)

typescript 复制代码
const vm = new Vue({
    el: '#app',
    data: {
        firstName:"张",
        lastName:"三",
    },
    methods: {
        showInfo(e) {
            console.log(e)
        }
    },
    computed: {
        fullName: {
            // get 作用:当有人读取 fullName 时,get 就会被调用,且返回值就作为 fullname 的值
            // 调用时机: 1.初次读取 fullname 时 2.所依赖的数据发生变化时
            // this 指向 vm
            get() {
                return this.firstName + "-" + this.lastName
            },
            // 当 fullName 被修改时调用
            set(value) {
                const arr = value.split("-")
                this.firstName = arr[0]
                this.lastName = arr[1]
            }
        },
        // 简写,当没有 set 函数时可简写成
        fullName_simple() {
            return this.firstName + "-" + this.lastName
        },
    }
})

11. watch(监视属性)

html 复制代码
<body>
    <!-- 
        1.想让 Vue 工作,就必须创建一个 Vue 实例,且要传入一个配置对象
        2.root容器里的代码依然符合 html 规范,只不过混入了一些特殊的 Vue 语法
        3.root容器里的代码被称为 Vue 对象
        4.Vue 实例与容器一一对应
        5.真实开发中只有一个 Vue 实例,并且会配合组件一起使用
        6.容器中的 {{}} 可写 vue 实例中对象的属性或者 js 表达式
        7.data 中的数据发生改变,模板中用到该数据的地方会自动更新
        8.在浏览器中可通过 vue.js devtools Root 中查看或临时更改 data
     -->

 
    <div id="app">
        <h2>今天天气很{{info}}</h2>
        <button @click="showInfo">切换天气</button>
        <hr/>
        <h3>a 的值是:{{numbers.a}}</h3>
        <button @click="numbers.a++">点我a + 1</button>
    </div>
     
    <script lang="ts">
        const vm = new Vue({
            el: '#app',
            data: {
                isHot: false,
                numbers: {
                    a:1,
                    b:1,
                },
            },
            methods: {
                showInfo(e) {
                    this.isHot = !this.isHot
                }
            },
            computed: {
                info () {
                    return this.isHot ? "炎热" : "寒冷"
                }
            },
            watch:{
                // 可监视 vue 中的属性变化,也可监视计算属性中属性的变化
                isHot: {
                    // immediate 为 true 时初始化时 handker 调用一次
                    immediate:true,
                    // handler 当 is hot 修改时调用,带两个参数:newValue:新的值,oldValue:旧的值
                    handler(newValue, oldValue) {
                        console.log("isHot 被修改了", newValue, oldValue)
                    }
                },
                // 简写形式
                isHot(newValue, oldValue) {
                    console.log("isHot 被修改了", newValue, oldValue)
                },
                "numbers.a": {
                    handler(newValue, oldValue) {
                        console.log("numbers.a 被修改了", newValue, oldValue)
                    }
                },
                "numbers.b": {
                    handler(newValue, oldValue) {
                        console.log("numbers.b 被修改了", newValue, oldValue)
                    }
                },
                numbers: {
                    // immediate 为 true 监视多级结构中所有属性,默认为 false
                    deep: true,
                    handler(newValue, oldValue) {
                        console.log("numbers 被修改了", newValue, oldValue)
                    }
                }
            }
        })

        // vm.$watch('isHot', {
        //     immediate:true,
        //     handler(newValue, oldValue) {
        //         console.log("isHot 被修改了", newValue, oldValue)
        //     }
        // })
    </script>
</body>

12. 绑定样式

  • 绑定 class 样式
html 复制代码
<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>初始Vue</title>
    <script src="../js/vue.js"></script>
    <style>
        .basic {
            width: 100px;
            height: 100px;
        }
        .normal {
            background-color: aquamarine;
        }
        .happy {
            background-color: hotpink;
        }
        .sad {
            background-color: green;
        }
        .fontStyle1 {
            font-size: 20px;
        }
        .fontStyle2 {
            font-style: italic;
        }
        .fontStyle3 {
            font-weight: bold;
        }
    </style>
</head>
<body> 
    <div id="app">
        <div class="basic" :class="mood" @click="changeMood">{{name}}</div></br>
        <div class="basic" :class="fontStyles">{{name}}</div></br>
        <div class="basic" :class="classObj">{{name}}</div></br>
    </div>

    <script lang="ts">
        const vm = new Vue({
            el: '#app',
            data: {
                name:"hwm",
                mood:"normal",
                fontStyles:["fontStyle1", "fontStyle2", "fontStyle3", "normal"],
                classObj: {
                    fontStyle1: false,
                    fontStyle2: false,
                    fontStyle3: false,
                    happy: false,
                }
            },
            methods: {
                changeMood() {
                    const moodArr = ["normal", "happy", "sad"]
                    let idx = Math.floor(Math.random()*3)
                    this.mood = moodArr[idx]
                } 
            }
        })

    </script>
</body>

13. 条件渲染(v-show/v-if/v-else-if/v-else)

  • v-show

    控制元素是否显示,设置元素 display 属性,dom元素依旧还在

  • v-if

    控制元素是否显示,比 v-show 更彻底,dom元素整个添加或删除

  • v-else-if

  • v-else

  • 注意点

    v-if v-else-if v-else 组合使用时,元素要紧挨在一起

    html 复制代码
    <div v-if="n===1">Angular</div>
    <div v-else-if="n===2">React</div>
    <div v-else-if="n===3">Vue</div>
    <div v-else>ming</div>
    
    <!-- v-if 可配合 template 使用达到对一个组控制的效果 -->
    <template v-if="n===1">
    	<div>Angular</div>
        <div>React</div>
        <div>Vue</div>
    </template>

14. v-for (列表渲染)

HTML 复制代码
<body> 
    <div id="app">
        <h2>人员列表:</h2>
        <ul>
            <li v-for="(item, index) in persons" :key="item.id">
                {{item.id}}-{{item.name}}-{{item.age}}
                <input/>
            </li>
        </ul>
        
        <button @click.once="addPerson">添加一个老刘</button>
    </div>

    <script lang="ts">
        const vm = new Vue({
            el: '#app',
            data: {
                persons:[
                    {id:"001", name:"张三", age:18},
                    {id:"002", name:"李四", age:19},
                    {id:"003", name:"王五", age:20},
                ]
            },
            methods: {
                addPerson() {
                    let obj = {id: "004", name: "老刘", age: 21}
                    this.persons.unshift(obj)
                }
            }
        })

    </script>
</body>

key 值得作用:

15. 列表过滤和排序

html 复制代码
<body> 
    <div id="app">
        <h2>人员列表:</h2>
        <input placeholder="请输入姓名" type="text" v-model="keyWord"/>
        <button @click="sortType = 2">按年龄升序排列</button>
        <button @click="sortType = 1">按年龄降序排列</button>
        <button @click="sortType = 0">原序排列</button>
        <ul>
            <li v-for="(item, index) in filtPersons" :key="item.id">
                {{item.id}}-{{item.name}}-{{item.age}}-{{item.sex}}
            </li>
        </ul>
    </div>

    <script lang="ts">
        const vm = new Vue({
            el: '#app',
            data: {
                sortType:"",
                keyWord:"",
                persons:[
                    {id:"001", name:"马冬梅", age:22, sex:"女"},
                    {id:"002", name:"周冬雨", age:19, sex:"女"},
                    {id:"003", name:"周杰伦", age:20, sex:"男"},
                    {id:"004", name:"温兆伦", age:21, sex:"男"},
                ],
            },
            methods: {
                
            },
            computed: {
                filtPersons() {
                    console.log("访问了filtPersons")
                    let arr = this.persons.filter((elem => {
                        return elem.name.indexOf(this.keyWord) !== -1
                    }))
                    if(this.sortType) {
                        arr.sort((p1, p2) => {
                            return this.sortType === 1? p2.age - p1.age : p1.age - p2.age
                        })
                    }
                    return arr
                }
            },
        })
    </script>
</body>

16. set(object, key, value) 添加响应式属性

向响应式对象中添加一个 property,并确保这个新 property 同样是响应式的,且触发视图更新

注意:注意对象不能是 Vue 实例,或者 Vue 实例的根数据对象。

html 复制代码
<script lang="ts">
    const vm = new Vue({
        el: '#app',
        data: {
            car: {
                productionNum:"123456789",
                struct:{
                    engine:"engine",
                    tyre:"tyre",
                },
                type:[
                    {name:"jeep", price:200},
                    {name:"bus", price:150},
                    {name:"moto", price:100},
                ]
            }
        },
        methods: {
            addCarPart(event, str) {
                // Vue.set(this.car.struct, str, str)
                this.$set(this.car.struct, str, str)
                // 错误 this.$set(this, str, str)
                
                // 删除属性
                 // Vue.delete(this.car.struct, str, str)
                this.$delete(this.car.struct, str, str)
            }
        }
    })
</script>

17. vue 监测数据总结

  1. vue 会监视 data 所有层次的数据

  2. 监测对象:

    通过 settter 实现监视,且要在 new vue 时就传入要监测的数据

    (1)对象后追加的属性,vue 默认不做响应式处理

    (2)如需给后添加的属性做响应式,以下 API

    Vue.set(target, propertyName/index, value)

    Vue.set(target, propertyName/index, value)

  3. 监测数组:

    (1) 调用原生对应的方法对数组更新(push, pop, unshift, shift, splice, sort, reverse)

    (2) 重新解析魔板,更新页面

    错误:this.student.friends[0] = {...}

    正确:this.student.friends[0].name = ""

18. 收集表单数据示例

html 复制代码
<body> 
    <div id="app">
        <form @submit.prevent="submit">
            账号:<input type="text" v-model="userInfo.account"/></br>
            密码:<input type="password" v-model="userInfo.password"/>
            </br></br>
            性别:
            <input type="radio" name="sex" value="male" v-model="userInfo.sex"/>男
            <input type="radio" name="sex" value="female" v-model="userInfo.sex"/>女
            </br></br>
            爱好:
            <input type="checkbox" v-model="userInfo.hobby" value="smoke"/>抽烟
            <input type="checkbox" v-model="userInfo.hobby" value="drink"/>喝酒
            <input type="checkbox" v-model="userInfo.hobby" value="perm"/>烫头
            </br></br>
            所属校区:
            <select v-model="userInfo.city">
                <option value="">请选择校区</option>
                <option value="beijing">北京</option>
                <option value="shanghai">上海</option>
                <option value="shenzhen">深圳</option>
                <option value="changsha">长沙</option>
            </select>
            </br></br>
            其它信息:
            <textarea v-model="userInfo.other"></textarea>
            </br></br>
            <input type="checkbox" v-model="userInfo.agree"/>阅读并接受<a href="https://www.baidu.com">《用户协议》</a>
            </br></br>
            <button>提交</button>
        </form>
    </div>

    <script lang="ts">
        const vm = new Vue({
            el: '#app',
            data: {
              userInfo: {
                account:'',
                password:'',
                sex:'male',
                hobby:[],
                city:'changsha',
                other:'',
                agree:'',
              }
            },
            methods: {
                submit() {
                    console.log(JSON.stringify(this.userInfo))
                }
            }
        })
    </script>
</body>

19. vue 内部指令

v-text:向其所在的节点中渲染文本内容,不支持标签文本解析

v-html:向其所在的节点中渲染文本内容,支持标签文本解析

v-cloak:没有值,vue 实例创建完毕并接管容器后,会删掉 v-cloak 属性,配合 css 选择器使用

v-once:在初次动态渲染后,就视为静态内容(没有响应式)

v-pre:跳过所在节点的编译过程(可利用它跳过没有使用指令语法,插值语法的节点,加快编译)

20. 生命周期

21. 非单文件组件

命名规则:

错误:myCom: myCom

正确:'myCom': myCom

html 复制代码
<body> 
    <div id="app">
        <school></school>
        </br>
        <student></student>
    </div>

    <script lang="ts">
        const school = {
            template:`
                <div>
                    <h2>学校名称:{{name}}</h2>
                    <h2>学校地址:{{address}}</h2>
                </div>
            `,

            data() {
                return {
                    name: "HUFE",
                    address: "长沙",
                }
            },
        }

        const student = {
            template:`
                <div>
                    <h2>学生名称:{{name}}</h2>
                    <h2>学生年龄:{{age}}</h2>
                </div>
            `,

            data() {
                return {
                    name: "ming",
                    age: 18,
                }
            },
        }
        
        const vm = new Vue({
            el: '#app',

            data: {
              
            },
            methods: {

            },
            components: {
                school,	// 简写 = school:school
                student:student,
            },
        })
    </script>
</body>

22. vm 与 vc

  1. vm
    • Vue 实例
    • 通过 el 配置项决定为哪个容器服务
    • data 配置项可写成对象或函数
    • this 指向 vm
  2. vc
    • VueComponent 实例
    • 没有 el 配置项,可复用
    • data 配置项只能写成函数
    • this 指向 vc
  3. VueComponent.protptype.[[Prototype]]=== Vue.prototypr

23. 单文件组件(.vue)

脚手架下载:vue2 文档 -> 生态系统 -> Vue CLI

基础样式:

html 复制代码
<template>
    <!-- 组件结构 -->
    <div class="demo">
        <hello></hello>
        <h2>学校名称:{{name}}</h2>
        <h2>学校地址:{{address}}</h2>
        <button @click="showName">点我提示学校名</button>
    </div>
</template>

<script>
    // 组件交互相关代码(数据、方法等)
    export default {
        name:'MySchool',
        data() {
            return {
                name: "HUFE",
                address: "ChangSha"
            }
        },
        methods: {
            showName() {
                alert(this.name)
            }
        }
    }
</script>

<style>
    /* 组件样式 */
    .demo {
        background-color: orange;
    }
</style>

使用组件:

html 复制代码
<template>
  <div>
    <img src="./assets/logo.png" alt="logo"/>
    <School></School>
    <Student name="ming" age="18" sex="男"></Student>
  </div>
</template>

<script>
    // 引入组件
    import School from "./components/School.vue";
    import Student from "./components/Student.vue";

    export default {
        name:'App',

        components: {
            School,
            Student,
        }
    }
</script>

<style>
</style>

24. ref 属性

  1. 用来给元素或子组件注册引用信息(id 的替代者)

  2. 应用在 html 标签上获取的是真实 DOM 元素,应用在组件标签上是组件实例对象(vc)

  3. 使用方式:

    html 复制代码
    <!-- 打标识 -->
    <h1 ref="xxx"></h1> 或 <School ref="xxx"></School>
    <!-- 获取 -->
    this.$refs.xxx

25. props 属性(父传子)

props 主要用于组件的传值

props 定义的属性不要去修改

如果需要为 props 中的属性做响应式,可在 data 中声明属性并指向 props 中的属性

html 复制代码
<!-- 组件导出 -->
<template>
    <!-- 组件结构 -->
    <div class="stu">
        <hello></hello>
        <h2 ref="title">学生姓名:{{stuName}}</h2>
        <h2>年龄:{{stuAge}}</h2>
        <h2>性别:{{sex}}</h2>
        <button @click="addAge">点我 age+1</button>
    </div>
</template>

<script>
    // 组件交互相关代码(数据、方法等)
    export default {
        name:'MyStudent',
        data() {
            return {
                stuName: this.name,
                stuAge: this.age,
            }
        },
        methods: {
            addAge() {
                this.stuAge++
            }
        },
        // 写法一:无特殊限制,在使用组件时注意使用 v-bind(:)
        // props:['name', 'age', 'sex'],
        // 写法二:限制类型,使用组件传入值类型不对时会报错
        // props: {
        //     name: String,
        //     age: Number,
        //     sex: String,
        // }
        // 写法三:限制类型,可选,默认值
        props: {
            name: {
                type: String,   
                required: false, // 必须传的参数
            },
            age: {
                type: Number,
                default: 18,    // 默认值
            },
            sex: String,
        }
    }
</script>

<style>
    /* 组件样式 */
    .stu {
        font-style: italic;
    }
</style>

<!-- 使用 -->
<Student name="ming" :age="18+1" sex="男"></Student>	<!-- 使用 : 进行绑定 -->

26. mixin(混合)

提取 vc 对象中的公共属性实现在不同组件中复用

javascript 复制代码
// 定义 mixin
export const h	unhe = {
    data: {
        return{
        	x: 100,
        	y: 200,
    	}   
    }
	methods: {
		showName() {
            alert(this.name)
        }
	},
	mounted() {
        console.log("mounted")
    },
}

// 使用 mixin
<script>
	import {hunhe} from ...
    export default {
		name:'',
         data() {
            return {
                
            }
        },
        mixins:[hunhe]
	}
</script>

27. scoped(局部样式)

html 复制代码
<!-- 局部的样式,只在该.vue文件中使用 -->
<style scoped>
</style>

28. less

[使用手册](Less 快速入门 | Less.js 中文文档 - Less 中文网 (bootcss.com))

[安装]((22条消息) Vue 安装 Less(CSS 预处理器)_vue中如何安装less_卡尔特斯的博客-CSDN博客)

html 复制代码
<style lang="less"></style>

29. 路由

安装router:npm install vue-router@3

基本用法:

router/index.ts:

typescript 复制代码
import VueRouter from "vue-router";
import Login from '../components/Login.vue'
import Main from '../components/Main.vue'
import Register from '../components/Register.vue'

export default new VueRouter({
    routes: [
        {
            path: '/login', // 跳转路径
            name: 'login',  // 名称
            component: Login,
        },
        {
            path: '/main', // 跳转路径
            name: 'main',  // 名称
            component: Main,
        },
        {
            path: '/register', // 跳转路径
            name: 'register',  // 名称
            component: Register,
        },
    ]
})

mian.js 中

javascript 复制代码
Vue.use(VueRouter)

new Vue({
  router,
  render: h => h(App),
}).$mount('#app')

单个页面中(其它类似):

html 复制代码
<template>
    <h2>我是Login组件</h2>
</template>

<script>
    export default {
        name: 'Login',
    }
</script>

App.vue:

html 复制代码
<template>
  <div id="app">
    <router-link to="/main">Main</router-link><br>
    <router-link to="/login">Login</router-link><br>
    <router-link to="/register">Register</router-link><br>
    <router-view></router-view>
  </div>
</template>

30. 浏览器本地存储

  1. localStorage

    在 Application -> Local storage 中查看

    在清除浏览器缓存时会清空

    typescript 复制代码
    saveData() {
     localStorage.setItem("msg", "666")
     localStorage.setItem("person", JSON.stringify(this.p))
    },
    removeData() {  // 清除某个缓存
     localStorage.removeItem("msg")
    },
    clearData() { // 清除所有缓存
     localStorage.clear()
    }
  2. sessionStorage

    在 Application -> Session storage 中查看

    关闭浏览器清空缓存

    Api 同上,localStorage -> sessionStorage

31. $emit $on 组件自定义事件(子传父)

vm. e m i t ( e v e n t , a r g ) / / 触发当前组件上的事件, e v e n t :事件名, a r g :参数 v m . emit(event, arg) // 触发当前组件上的事件,event:事件名,arg:参数 vm. emit(event,arg)//触发当前组件上的事件,event:事件名,arg:参数vm.on(event, fn) // 监听event事件后运行 fn

  1. 父组件可以使用 props 把数据传给子组件
  2. 子组件可以使用 $emit,让父组件监听到自定义事件
  1. App.vue

    vue 复制代码
    <template>
      <div id="app">
        <h1>{{ msg }}</h1>
        <School :getSchoolName="getSchoolName"></School>
        <Student @stuName="getStudentName"></Student>
        <Student ref="student"></Student>
      </div>
    </template>
    
    <script>
    import Main from './components/Main.vue';
    import Student from './components/Student.vue';
    import School from './components/School.vue';
    
    export default {
      name: 'App',
      data() {
        return {
          msg: "你好啊",
        }
      },
      methods: {
        getSchoolName(name) {
            console.log("App 收到了学校名:", name)
        },
        getStudentName(name) {
          console.log("App 收到了学生名:", name)
        },
      },
      components:{Student, School},
      mounted() {
        this.$refs.student.$on('stuName', this.getStudentName)
        // 只执行一次
        // this.$refs.student.$once('stuName', this.getStudentName)
      }
    }
    </script>
  2. 通过父组件给子组件传递函数类型的 props 实现:子给父传数据:

    vue 复制代码
    <template>
        <div class="school">
            <h2>学校名:{{ name }}</h2>
            <h2>学校地址:{{ address }}</h2>
            <button @click="sendSchoolName()">把学校名给App</button>
        </div>
    </template>
    
    <script>
        export default {
            name: 'school',
            props: ['getSchoolName'],
            data() {
                return {
                    name: 'HUFE',
                    address: "changsha"
                }
            },
            methods:{
                sendSchoolName() {
                    this.getSchoolName(this.name)
                }
            }
        }
    </script>
  3. 通过父组件给子组件绑定一个自定义事件实现:子给父传数据:

    vue 复制代码
    <template>
      <div id="app">
        <h1>{{ msg }}</h1>
        <School :getSchoolName="getSchoolName"></School>
        <!-- 写法一 -->
        <Student @stuName="getStudentName" @click.native="stuClick"></Student>
        <!-- 写法二 -->
        <Student ref="student"></Student>
      </div>
    </template>
    
    <script>
    import Main from './components/Main.vue';
    import Student from './components/Student.vue';
    import School from './components/School.vue';
    
    export default {
      name: 'App',
      data() {
        return {
          msg: "你好啊",
        }
      },
      methods: {
        getSchoolName(name) {
            console.log("App 收到了学校名:", name)
        },
        getStudentName(name) {
          console.log("App 收到了学生名:", name)
        },
        stuClick() {
          alert("stuClick")
        }
      },
      components:{Student, School},
      mounted() {
        this.$refs.student.$on('stuName', this.getStudentName)
        // 只执行一次
        // this.$refs.student.$once('stuName', this.getStudentName)
      }
    }
    </script>

32. nextTick()

下一次 DOM 更新结束后执行器指定回调

typescript 复制代码
this.$nextTick(function(){
 this.$refs.inputTitle.focus()
})

33. 插槽

  1. 默认插槽

    vue 复制代码
    <template>
        <div class="sch">
            <h2>ming</h2>
            <slot>默认值,组件使用者没传时显示</slot>
        </div>
    </template>

    使用:

    vue 复制代码
    <template>
      <div class="app">
        <Student>
          <img src="./assets/4.png" alt="">
        </Student>
      </div>
    </template>

Vue 3

注意事项

导入 .vue 组件

typescript 复制代码
import Child from './components/Child.vue' 	// 不需要带 {}

0. 创建 vue3 工程

  1. 通过 cli 创建 vue3 js 工程

    1. 查看 cli 版本,版本需在 4.5.0 以上
      vue -V
      npm install -g @vue/cli (默认安装最新版本cli)
    2. 创建工程,选择 vue 版本
      vue create vue3_test (工程名)
  2. 通过 cli 创建 vue3 ts 工程

    1. 确认版本:
      node(14.x 以上):node -v 若版本不够,去 node 官网下载
      vue-cli(4.x 以上):vue -V 若版本不够,npm install -g @vue/cli
    2. 创建项目
      vue create vue3ts_demo(项目名)
      选择第三项,自定义配置(光标移动到对应处,按空格选择)
  3. 通过 vite 创建 vue3 ts 工程

    typescript 复制代码
    npm create vite@latest my-vue-app --template vue-ts

    创建工程后使用:npm -i 安装模块

1. setup 函数

html 复制代码
<template>
  <h2>{{name}}</h2>
  <h2>{{age}}</h2>
  <button @click="sayHello">SayHello</button>
</template>

<script>
  export default{
    setup() {
      let name = "ming"
      let age = 18

      function sayHello() {
        alert(`Hello, I am ${name},my age is ${age}`)
      }

      return {
        name,
        age,
        sayHello,
      }
  }
  }
</script>

setup 语法糖

html 复制代码
<template>
  <h2>{{name}}</h2>
  <h2>{{age}}</h2>
  <button @click="sayHello">SayHello</button>
</template>

<script setup>
    let name = "ming"
    let age = 18

    function sayHello() {
      alert(`Hello, I am ${name},my age is ${age}`)
    }
</script>

2. ref 函数(为数据做响应式)

html 复制代码
<template>
  <h2>姓名:{{ name }}</h2>
  <h2>年龄:{{ age }}</h2>
  <h2>职位:{{ job.type }}</h2>
  <h2>薪水:{{ job.salary }}</h2>
  <button @click="fixName">点我修改名字</button>
  <br>
  <button @click="fixAge">点我修改年龄</button>
  <br>
  <button @click="fixJob">点我修改工作</button>
</template>

<script setup>
  import { ref } from 'vue';

  // ref 处理基本类型
  let name = ref("ming")
  let age = ref(18)
  // ref 处理对象
  let job = ref ({
    type: "前端工程师",
    salary: "30k",
  })

  function fixName() {
    name.value = "hhh"
  }

  function fixAge() {
    age.value = 20
  }

  function fixJob() {
    job.value.type = "UI工程师"
    job.value.salary = "50k"
  }
</script>

3. reactive 函数(处理对象响应式)

html 复制代码
<template>
  <h2>姓名:{{ name }}</h2>
  <h2>年龄:{{ age }}</h2>
  <h2>职位:{{ job.type }}</h2>
  <h2>薪水:{{ job.salary }}</h2>
  <h2>修改深层次对象属性:{{ job.a.b.c }}</h2>
  <h2>爱好:{{ hobby }}</h2>
  <button @click="fixName">点我修改名字</button><br>
  <button @click="fixAge">点我修改年龄</button><br>
  <button @click="fixJob">点我修改工作</button><br>
  <button @click="fixHobby">点我修改爱好</button>
</template>

<script setup>
  import { reactive, ref } from 'vue';

  // ref 处理基本类型响应式
  let name = ref("ming")
  let age = ref(18)
  // reactive 处理对象响应式
  let job = reactive ({
    type: "前端工程师",
    salary: "30k",
    // 测试深层次
    a: {
      b: {
        c: 666
      }
    }
  })
  // reactive 处理对象(数组)响应式
  let hobby = reactive(['抽烟', '喝酒', '烫头'])

  function fixName() {
    name.value = "hhh"
  }

  function fixAge() {
    age.value = 20
  }

  function fixJob() {
    job.type = "UI工程师"
    job.salary = "50k"
    job.a.b.c = 999
  }

  function fixHobby() {
    hobby[0] = '学习'
  }
</script>

4. 新增/删除属性

html 复制代码
<template>
  <h2>姓名:{{ person.name }}</h2>
  <h2>年龄:{{ person.age }}</h2>
  <h2>性别:{{ person.sex }}</h2>
  <button @click="addInfo">添加信息</button><br>
  <button @click="delInfo">删除信息</button><br>
</template>

<script setup>
  import { reactive, } from 'vue';

  let person = reactive({
    name: "ming",
    age: 18
  })

  function addInfo() {
    person.sex = "男"
  }

  function delInfo() {
    delete person.name
  }
</script>

5. computed 计算属性

html 复制代码
<template>
  姓:<input type="text" v-model="person.firstName"/><br>
  名:<input type="text" v-model="person.lastName"/><br>
  名:<input type="text" v-model="person.fullName"/><br>
</template>

<script setup>
  import { reactive, computed} from 'vue';

  let person = reactive({
    firstName: "ming",
    lastName: "ming",
  })

  // 简写,没有 setter
  // let fullName = computed(() => {
  //   return person.firstName + '-' + person.lastName
  // })
  // 完整写法
  person.fullName = computed({
    get() {
      return person.firstName + '-' + person.lastName
    },
    set(value) {
      const nameArr = value.split('-')
      person.firstName = nameArr[0]
      person.lastName = nameArr[1]
    }
  })
</script>

6. watch 数据监视

html 复制代码
<template>
  <h2>num:{{ num }}</h2>
  <button @click="num++">点我num+1</button><br>
  <h2>num:{{ str }}</h2>
  <button @click="str+='!'">点我str+!</button><br>
  <h2>姓名{{ person.name }}</h2>
  <h2>年龄:{{ person.age }}</h2> 
  <h2>薪资:{{ person.job.salary }}</h2> 
  <button @click="person.name+='~'">点我修改姓名</button>
  <button @click="person.age++">点我修改年龄</button>
  <button @click="person.job.salary++">点我修改薪资</button>
</template>

<script setup>
  import {ref, reactive, computed, watch} from 'vue';

  let num = ref(0)
  let str = ref("Hello")

  let person = reactive({
    name: "ming",
    age: 18,
    job: {
      type: "前端工程师",
      salary: "20",
    }
  })

  // 情况一:监视一个 ref 所定义的响应式数据
  // watch(num, (newV, oldV) => {
  //   console.log(`newV${newV},old:${oldV}`)
  // }, {immediate: true})
  // 情况二:监视多个 ref 所定义的响应式数据 newV:[newNum, newStr] oldV:[oldNum, oldStr]
  // watch([num, str], (newV, oldV) => {
  //   console.log(newV,oldV)
  // })
  /* 情况三:监视 reactive 所定义的一个响应式数据,
     踩坑点:
     1. 无法正确获取 oldValue
     2. 强制开启了深度监视(deep 配置无效)
  */
  // watch(person, (newV) => {
  //   console.log('person 变化了', newV)
  // })
  // 情况四:监视 reactive 所定义的一个响应式数据的某个属性
  watch(() => person.age, (newV, oldV) => {
    console.log('person.age 变化了', newV, oldV)
  })

</script>

7. watchEffect

typescript 复制代码
/* 
    1.初始就会执行一次
    2.监视函数体中使用到某个属性,若该属性改变了就会执行一次
  */
  watchEffect(() => {
    console.log("watchEffect 调用了")
    let x = num.value
    let y = person.job.salary
  })

8. 生命周期

图:官网查看

beforeCreate == setup()

beforeCreate == setup()

9. hook (复用代码)

创建一个 usePoints.js 代码

javascript 复制代码
import { onBeforeUnmount, onMounted, reactive } from "vue";

export default function() {
    // 实现竖版"打点"相关数据
    let point = reactive({
        x:0,
        y:0,
    })

    // 实现鼠标"打点"相关方法
    function savePoint(event) {
        point.x = event.pageX
        point.y = event.pageY
        console.log(event.pageX, event.pageY)
    }

    // 实现鼠标"打点"相关的生命周期狗子
    onMounted(() => {
        window.addEventListener('click', savePoint)
    })

    onBeforeUnmount(() => {
        window.removeEventListener('click', savePoint)
    })

    return point
}

在组件中复用:

html 复制代码
<template>
    <!-- 组件结构 -->
    <div class="demo">
        <h2>鼠标点击X坐标:{{ point.x }}</h2>
        <h2>鼠标点击Y坐标:{{ point.y }}</h2>
    </div>
</template>

<script setup>
    import usePoint from '../hook/usePoints'
    let point = usePoint()
</script>

<style scoped>
    /* 组件样式 */
    .demo {
        background-color: orange;
    }
</style>

10. toRef 和 toRefs

  • toRef: 复制 reactive 里的单个属性并转成 ref
  • toRefs: 复制 reactive 里的所有属性并转成 ref
html 复制代码
<template>
  <h2>
    reactive-greet: {{ info.greet }} 
  </h2>
  <h2>
    toRef-greet: {{ rGreet }}
  </h2>
  <button @click="onChangeGreet">更换问候语</button>
</template>

<script>
import { reactive, toRef } from 'vue'
export default {
	setup() {
    let info = reactive({
      name: 'Tony',
      greet: 'Hello'
    })
    // 复制整个 info
    let rInfo = toRefs(info)
	// 复制 info 里的 greet 属性
    let rGreet = toRef(info, 'greet')
    // 更改 rGreet
    const onChangeGreet = () => {
      rGreet.value = 'world!'
    }
    return {
      info,
      rGreet,
      onChangeGreet
    }
  }
}
</script>

11. shallowReactive

只处理对象最外层属性的响应式(浅响应式)

12. readonly 和 shallowReadOnly

  • readonly: 让一个响应式数据变为只读的(深只读)。
  • shallowReadOnly: 让一个响应式数据变为只读的(浅只读)

13. toRaw 和 markRaw

  • toRaw : 将一个 reactive 生成的响应式对象转为普通对象
  • markRaw: 标记一个对象,使其永远不会再成为响应式对象

14. provide 和 inject

作用:实现祖孙间通信

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QXKRhQah-1689749017405)(C:\Users\cli08\AppData\Roaming\Typora\typora-user-images\image-20230530234850863.png)]

html 复制代码
<!-- app -->
<script setup>
  let car = {
    name: "奔驰",
    price: "70w"
  }

  provide('car', car)

  components:{Child}
</script>

<!-- 子组件 -->
<script setup>
    let car = inject('car')

    components:{Son}
</script>

<!-- 孙组件 -->
<template>
    <div class="son">
        <h3>我是孙组件 {{ car.name }}---{{ car.price }}</h3>
    </div>
</template>

<script setup>
    import { inject } from 'vue';

    let car = inject('car')
</script>

15.响应式数据判断

  • isRef,是否是由ref定义的响应式数据
  • isReactive,是否是由reactive定义的响应式数据
  • isReadonly,是否是由readonly定义的数据
  • isProxy,是否是由reactivereadonly定义的数据

16. Router (路由)

  1. 安装:npm install vue-router@4
  2. useRouter:对路由的控制,用来路由跳转
    useRoute:路由的信息,用来路由传参
  1. 使用示例

    单个页面(Login.vue 和 Main.vue):

    html 复制代码
    <template>
        <h2>我是Login组件</h2>
    </template>
    
    <script setup>
        
    </script>

    Game.vue

    vue 复制代码
    <template>
        <div class="game">
            <h2>我是Game组件</h2>
            <router-link to="/game/game_1">Game_1</router-link><br>
            <router-link to="/game/game_2">Game_2</router-link><br>
            <router-link to="/game/game_3">Game_3</router-link><br>
            <router-view></router-view>
        </div>
    </template>
    
    <script setup lang="ts">
        
    </script>
        
    <style scoped>
        .game {
            background-color: pink;
            padding: 10px;
        }
    </style>

    Game_1.vue(Game_2.vue, Game_3.vue 类似)

    vue 复制代码
    <template>
        <div class="game_1">
            <h2>我是Game_1组件</h2>
        </div>
    </template>
    
    <script setup lang="ts">
    </script>
    
    <style scoped>
        .game_1 {
            background-color: goldenrod;
        }
    </style>

    main.js

    javascript 复制代码
    import { createApp } from 'vue'
    import App from './App.vue'
    import router from './router/index.ts'
    
    createApp(App).use(router).mount('#app')

    router/index.ts

    typescript 复制代码
    // history模式
    import {createRouter, createWebHashHistory, RouteRecordRaw} from 'vue-router'
    
    const routes : RouteRecordRaw[] = [
        {
            path: '/login', // 跳转路径
            name: 'login',  // 名称
            component: () => import('../components/Login.vue'),
        },
        {
            path: '/main', // 跳转路径
            name: 'main',  // 名称
            component: () => import('../components/Main.vue'),
        },
        {
            path: '/game', // 跳转路径
            name: 'game',  // 名称
            component: () => import('../components/Game.vue'),
            children:[
            {
                path: 'game_1',
                name: 'game_1',
                component: () => import('../components/Game_1.vue'),
            },
            {
                path: 'game_2',
                name: 'game_2',
                component: () => import('../components/Game_2.vue'),
            },
            {
                path: 'game_3',
                name: 'game_3',
                component: () => import('../components/Game_3.vue'),
            },
            ]
        },
    ]
    
    // 创建路由对象
    const router = createRouter({
        history: createWebHashHistory(),
        routes,
    })
    
    export default router

    App.vue

    vue 复制代码
    <template>
      <router-link to="/main">Main</router-link><br>
      <router-link to="/login">Login</router-link><br>
      <router-link to="/register">Register</router-link><br>
      <router-view></router-view>
    </template>
    
    <script>
      export default {
        name: 'App',
      }
    </script>
  2. 路由传参

    • query

      vue 复制代码
      <router-link :to="{
         path: '/main',
         query: {
         	p1: 'ming',
         	p2: 18
         }
      }">
          Main
      </router-link><br>
      
      <!-- 在对应组件上接收参数 -->
      <script setup lang="ts">
          import { useRouter, useRoute } from 'vue-router';
          const route = useRoute()
          console.log(route.query)
      </script>
    • param

      vue 复制代码
      <router-link :to="{
            name: 'login',
            params: {
              p3: 'ming',
              p4: 18
            }
      }">Login</router-link><br>
      
      <!-- 在对应组件上接收参数 -->
      <script setup lang="ts">
          import { useRoute, useRouter } from 'vue-router';
          const route = useRoute()
          console.log(route.params)
      </script>
  3. 编程式路由导航

    typescript 复制代码
    const router = useRouter()
    // 跳转页面
    router.push('path', query: {})		// 压入历史记录栈顶
    router.push(name: 'name', param: {})		// 压入历史记录栈顶
    router.replace('path', query: {})	// 替换历史记录栈顶
    router.replace(name: 'name', param: {})		// 替换历史记录栈顶
    router.go(1)	// 向前移动一条历史记录
    router.go(-1)	// 向后移动一条历史记录

17. pinia 状态管理器使用

  1. 安装 pinia :npm install pinia

  2. 修改main.js,引入pinia提供的createPinia方法,创建根存储。

    typescript 复制代码
    // main.ts
    
    import { createApp } from "vue";
    import App from "./App.vue";
    import { createPinia } from "pinia";
    const pinia = createPinia();
    
    const app = createApp(App);
    app.use(pinia);
    app.mount("#app");
  3. src 下创建文件夹 store,用来存放共享数据

  1. 创建 store

    typescript 复制代码
    import { defineStore } from 'pinia'
    import { reactive } from 'vue';
    
    interface Student {
      name: string,
      age: number,
      sex: string,
      job: {
        type: string,
        salary: string,
      }
    }
    
    export const useUsersStore = defineStore("users", () => {
        const student = reactive<Student>({
          name: 'ming',
          age: 18,
          sex: '男',
          job: {
            type: '前端工程师',
            salary: '30k',
          }
        })
    
        const addAge = (add: number) => {
          student.age += add
        }
    
        return {
          student,
          addAge
        };
      });
  2. 使用

    vue 复制代码
    <template>
      <img alt="Vue logo" src="./assets/4.png" />
      <h2>姓名:{{ student.name }}</h2>
      <h2>年龄:{{ student.age }}</h2>
      <h2>性别:{{ student.sex }}</h2>
      <h2>职位:{{ student.job.type }}</h2>
      <h2>薪水:{{ student.job.salary }}</h2>
      <button @click="addAge(1)">点我年龄+1</button>
    </template>
    
    <script setup lang="ts">
      import { ref, reactive } from "vue";
      import { useUsersStore } from "../src/store/user";
    
      const userStore = useUsersStore();
      const {student, addAge} = userStore
      
      console.log(userStore)
    </script>
    
    <style scoped>
    </style>

18. ref 获取 DOM 元素

vue 复制代码
<script setup lang="ts">
    const ctx = ref<HTMLDivElement>()
    onMounted(() => {
      console.log("hwm", ctx.value)
    })
</script>

<template>
	<div class="game-list" ref="ctx"></div>
</template>
相关推荐
丶Darling.22 分钟前
LeetCode Hot100 | Day1 | 二叉树:二叉树的直径
数据结构·c++·学习·算法·leetcode·二叉树
安冬的码畜日常43 分钟前
【D3.js in Action 3 精译_029】3.5 给 D3 条形图加注图表标签(上)
开发语言·前端·javascript·信息可视化·数据可视化·d3.js
小白学习日记2 小时前
【复习】HTML常用标签<table>
前端·html
程序员大金2 小时前
基于SpringBoot+Vue+MySQL的装修公司管理系统
vue.js·spring boot·mysql
丁总学Java2 小时前
微信小程序-npm支持-如何使用npm包
前端·微信小程序·npm·node.js
z樾2 小时前
Github界面学习
学习
yanlele2 小时前
前瞻 - 盘点 ES2025 已经定稿的语法规范
前端·javascript·代码规范
懒羊羊大王呀2 小时前
CSS——属性值计算
前端·css
DOKE3 小时前
VSCode终端:提升命令行使用体验
前端