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

文章目录

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

小白 Vue 3 学习

一些名词

  • Node.js

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

  • NPM (Node Package Manager)

    软件包仓库

软件安装

  • Node
    Node.js 安装配置 | 菜鸟教程 (runoob.com)

VSCode 中的一些设置

1. 关闭eslint检查

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

module.exports = {
// 避免Eslint报错
lintOnSave: false
}

tsconfig.json 配置文件

{
"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

/// 

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 继承。
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. 导出

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

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

3. 去除字符串两端空格

//trim()例子
let str = ' hello '
console.log(str.trim()) //hello

4. 一些特殊语法糖

  1. !

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

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

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

  3. ??

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

    console.log(false ?? '哈哈哈')  // false
    console.log(null ?? '哈哈哈')  // 哈哈哈
    

5. 深拷贝

let deepObj = JSON.parse(JSON.stringify(obj));

6. 拼接两个数组

let arr = [1, 2]
let arr2 = [3, 4]

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

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

7. JSON

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

    // 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 对象转换为字符串。

    // 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

结构代码展示



DOCTYPE HTML> 
<HTML lang="en"> 

<head> 
  <meta charset="UTF-8"> 
  <title>my HTMLtitle> 
head>


<body> 
  我的第一个HTML网页
body>

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 视为下载资源) 单标签,超链接

通过超链接跳转锚点:

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

<a href="#">回到顶部a> 

超链接唤起指定应用:


<a href="tel:10086">电话联系a>

<a href="mailto:[email protected]">邮件联系a>

<a href="sms:10086">短信联系a>

4. 列表

  • 4.1 ol (有序列表)

    <h2>把大象装进冰箱分几步h2>
    
    <ol>
        <li>打开冰箱门li>
        <li>大象放进去li>
        <li>关上冰箱门li>
    ol>
    
  • 4.2 ul (无序列表)

    <h2>我想去的几个城市h2>
    
    <ul>
        <li>云南li>
        <li>成都li>
        <li>重庆li>
    ul>
    
  • dl (自定义列表)

    <h2>我想去的几个城市h2>
    
    <dl>
        <dt>做好笔记dt>
        <dd>好记性不如烂笔头dd>
        <dt>多加练习dt>
        <dd>实践出真知dd>
        <dt>别怕失败dt>
        <dd>失败是成功之母dd>
    dl>
    
  • 注意点

    1. 列表可嵌套使用

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

      做好笔记
      好记性不如烂笔头
      笔记可以是电子版或纸质版

5. 表格


<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>18td> 
            <td>汉族td> 
            <td>团员td> 
        tr>

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

    
    <tfoot>
        <tr>
            <td>td>     
            <td>td>
            <td>td>
            <td>td>
            <td>共计:4人td>
        tr>
    tfoot>
table>

6. 表单

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


<form action="https://search.jd.com/search">
    用户名:
    <input name="userName" value="hwm" disabled>
    性别:
    <input type="radio" name="gender" value="male" 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. 输入框


8.文本域

<textarea name="other" cols="23" row="3">textarea>

9.下拉框

<select name="place">
    <option value="" selected>湖南option>
    <option value="">广东option>
    <option value="">山东option>
select>

10.label 标签



11.补充常用标签


<br>


<hr>


<pre>

12.框架标签



<iframe src="https://cn.bing.com/" width="1920" height="1080" frameborder="0">
iframe>

13.字符实体

参考链接

全局属性

  1. id

    给标签指定唯一标识,id 不可重复
    作用:可让标签相关联
    注意:,,,

CSS

h1 {
    color: red;
    font-size: 40px;
}
h2 {
    color: green;
    font-size: 60px;
}

样式

行内样式:写在标签内,只对改标签生效
内部样式:写在 html 文件 内,对整个 html 文件生效
外部样式:将 css 样式单独写在一个 .css 文件中,在 html 中使用 标签链接

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

选择器

  1. 通配选择器

    * {
        属性名: 属性值;
    }
    
  2. 元素选择器

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

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

    为标签同时设置两个类

    <p class="fish animal">
    
  4. id 选择器

    #IDName {
        属性名: 属性值;
    }
    
    /* html */
    

    "idName">id 选择器

  5. 交集选择器
    5.1 元素选择器 & 类选择器

    标签名.className {
        属性名: 属性值;
    }
    
  6. 并集选择器

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

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

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

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

    /* 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. 动态伪类选择器

    /* 和类相似,但不是类,元素特殊状态的一种描述 */
    
    /*
    link visited 是  的特有状态 
    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. 字体复合属性

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

文本属性

  1. color 文本颜色

    /* 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 波浪线
    text-decoration: overline underline wavy blue 5px;
    
  4. text-indent 文本缩进

    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. 行内元素(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

    /* 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. 水平垂直居中

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

cas_websited

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

  1. 给组件传值

    <isLike :unlike="msgInfo.unlike" :like="msgInfo.like" :status="msgInfo.status" size="s" :faqID="faqID">isLike>
    
    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. 请求服务器

// 示例
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;//内容高度

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. 滑动条定位

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.avm.watch

  • el

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

1. 初识 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. 插值语法

    <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 中的属性

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

      双向绑定
      只能应用在表单类元素上
      语法糖:省略 value, v-model=“”
      修饰符:.number .lazy(失去焦点再收集) trim(去除前后空格)

      <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 实例两种写法

// 第一种
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))

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 可简写 @

new Vue({
    el:"#root",
    data() {
        return {

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

// 使用
/* 
*/

7. 事件修饰符

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

8. 键盘事件

@keyup
@keydown


<input type="text" @keyup.enter="showInfo">

9. methods(方法)

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

10. computed(计算属性)

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(监视属性)

<body>
    

 
    <div id="app">
        <h2>今天天气很{{info}}h2>
        <button @click="showInfo">切换天气button>
        <hr/>
        <h3>a 的值是:{{numbers.a}}h3>
        <button @click="numbers.a++">点我a + 1button>
    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 样式
<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>初始Vuetitle>
    <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 组合使用时,元素要紧挨在一起

    <div v-if="n===1">Angulardiv>
    <div v-else-if="n===2">Reactdiv>
    <div v-else-if="n===3">Vuediv>
    <div v-else>mingdiv>
    
    
    <template v-if="n===1">
    	<div>Angulardiv>
        <div>Reactdiv>
        <div>Vuediv>
    template>
    

14. v-for (列表渲染)

 
    

人员列表:

  • {{item.id}}-{{item.name}}-{{item.age}}

key 值得作用:

vue(html,css,vue2,vue3) 学习总结_第1张图片

15. 列表过滤和排序

<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 实例的根数据对象。

<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. 收集表单数据示例

<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. 生命周期

img

21. 非单文件组件

命名规则:
错误:myCom: myCom
正确:‘myCom’: myCom

<body> 
    <div id="app">
        <school>school>
        br>
        <student>student>
    div>

    <script lang="ts">
        const school = {
            template:`
                

学校名称:{{name}}

学校地址:{{address}}

`
, data() { return { name: "HUFE", address: "长沙", } }, } const student = { template:`

学生名称:{{name}}

学生年龄:{{age}}

`
, 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

基础样式:

<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>

使用组件:

<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. 使用方式:

    
    <h1 ref="xxx">h1><School ref="xxx">School>
    
    this.$refs.xxx
    

25. props 属性(父传子)

props 主要用于组件的传值
props 定义的属性不要去修改
如果需要为 props 中的属性做响应式,可在 data 中声明属性并指向 props 中的属性


<template>
    
    <div class="stu">
        <hello>hello>
        <h2 ref="title">学生姓名:{{stuName}}h2>
        <h2>年龄:{{stuAge}}h2>
        <h2>性别:{{sex}}h2>
        <button @click="addAge">点我 age+1button>
    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 对象中的公共属性实现在不同组件中复用

// 定义 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(局部样式)


<style scoped>
style>

28. less

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

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

<style lang="less">style>

29. 路由

安装router:npm install vue-router@3

基本用法:
router/index.ts:

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 中

Vue.use(VueRouter)

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

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

<template>
    <h2>我是Login组件h2>
template>

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

App.vue:

<template>
  <div id="app">
    <router-link to="/main">Mainrouter-link><br>
    <router-link to="/login">Loginrouter-link><br>
    <router-link to="/register">Registerrouter-link><br>
    <router-view>router-view>
  div>
template>

30. 浏览器本地存储

  1. localStorage

    在 Application -> Local storage 中查看
    在清除浏览器缓存时会清空

    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

    
    
    
    
  2. 通过父组件给子组件传递函数类型的 props 实现:子给父传数据:

    
    
    
    
  3. 通过父组件给子组件绑定一个自定义事件实现:子给父传数据:

    
    
    
    

32. nextTick()

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

this.$nextTick(function(){
 this.$refs.inputTitle.focus()
})

33. 插槽

  1. 默认插槽

    
    

    使用:

    
    

Vue 3

注意事项

导入 .vue 组件

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(项目名)
      选择第三项,自定义配置(光标移动到对应处,按空格选择)
      vue(html,css,vue2,vue3) 学习总结_第2张图片
  3. 通过 vite 创建 vue3 ts 工程

    npm create vite@latest my-vue-app --template vue-ts
    

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

1. setup 函数

<template>
  <h2>{{name}}h2>
  <h2>{{age}}h2>
  <button @click="sayHello">SayHellobutton>
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 语法糖

<template>
  <h2>{{name}}h2>
  <h2>{{age}}h2>
  <button @click="sayHello">SayHellobutton>
template>

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

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

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

<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 函数(处理对象响应式)

<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. 新增/删除属性

<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 计算属性

<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 数据监视

<template>
  <h2>num:{{ num }}h2>
  <button @click="num++">点我num+1button><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

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

8. 生命周期

图:官网查看

beforeCreate == setup()
beforeCreate == setup()

9. hook (复用代码)

创建一个 usePoints.js 代码

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
}

在组件中复用:

<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
<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)]


<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):

    <template>
        <h2>我是Login组件h2>
    template>
    
    <script setup>
        
    script>
    

    Game.vue

    
    
    
        
    
    

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

    
    
    
    
    
    

    main.js

    import { createApp } from 'vue'
    import App from './App.vue'
    import router from './router/index.ts'
    
    createApp(App).use(router).mount('#app')
    

    router/index.ts

    // 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

    
    
    
    
  2. 路由传参

    • query

      
          Main
      
    • param

      Login
  3. 编程式路由导航

    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方法,创建根存储。

    // 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

    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. 使用

    
    
    
    
    
    
    

18. ref 获取 DOM 元素





你可能感兴趣的:(vue,vue.js,学习,前端)