梦里 - Vue
type: channel
link: https://www.sunshine966.com/category/vue/
description: vue
items: 在shopify站点上，每个section里，代码复用实例，该怎么优化？
items: shopify 增加youtube视频和选项卡
items: Vue3 学习笔记（七）
items: Vue3 学习笔记（六）
items: Vue3 学习笔记（五）
items: Vue3 学习笔记（四）
items: Vue3 学习笔记（三）
items: Vue3 学习笔记（二）
items: Vue3学习笔记（一）
items: Vue3学习笔记

在shopify站点上，每个section里，代码复用实例，该怎么优化？
type: item
date: 2025-10-28T15:10:29+08:00
description: 在 Shopify 里，一个 .liquid Section 就是一块「彼此独立、可重复、可排序」的积木。 核心限制是：每个 Section 的代码最终会被 碎片式地 拼到同一个页面上；你 不能保证 两个 Section 谁在前谁在后，也 不能保证 只出现一次；Shopify 没有「公共 JS 打包器」——不能 在 Section 里直接写 import 然后让主题统一去 type="module" 合并；浏览器仍然 重复下载 同一个 CDN 地址，除非你用 nomodule/defer 做全局去重。因此，「单模块复用」那一套在 Section 级别 是行不通的；必须把 Vue 3 当全局库来用，并且保证：只加载一次；每个 Section 只负责「自己挂载自己」；即使两个相同 Section 被拖到同一页面，也能各自独立运行。下面给出 Shopify 官方推荐 的「Section-内自闭环 + 全局单例脚本」方案。一、theme.liquid（或 head 标签里）统一引入 Vue 3{%- comment -%} 仅当页面至少有一个需要 Vue 的 Section 时才加载 {%- endcomment -%} {%- if request.page_type contains 'index' or section_blocks_contains_vendor 'vue' -%} {%- endif -%}说明vue.global.prod.js 是 IIFE 版本，会把 Vue 暴露成全局 Vue;defer 保证执行顺序在 DOM 解析之后，且 只下载一次；用 section_blocks_contains_vendor 是 Shopify 2.0 的过滤器，可自己换成任意条件。二、写一个通用 Section：sections/vue-counter.liquid {{ section.settings.heading }} Counter 1: {{ count }} Counter 2: {{ count2 }} + Counter 1 + Counter 2 {% schema %} { "name": "Vue Counter", "settings": [ { "type": "text", "id": "heading", "label": "Heading", "default": "Counter Block" } ], "presets": [{ "name": "Vue Counter" }] } {% endschema %}三、同一个页面拖 N 个「Vue Counter」Section每个 Section 输出 独立 DOM + 独立脚本；由于 section.id 不同，变量名、挂载点互不影响；Vue 全局库只加载 一次；即使后续用「主题编辑器」再拖一个进来，也能立刻工作（document.currentScript 永远指向当前脚本块）。四、如果「多个不同 Section」都要用 Vue统一在 theme.liquid 里加一次 然后在每个 Section 里只写： 五、小结目标Shopify Section 内的正确姿势只加载一次 Vue在 theme.liquid 用 不重复下载浏览器缓存 + 全局变量每个 Section 独立用 section.id 做命名空间，自闭环脚本可重复拖放document.currentScript 保证永远拿到当前块不依赖打包器直接用 IIFE 版本，不写 type="module"按上面模板，无论多少个 Section、多少个实例，都能做到「零重复下载、零全局污染、零冲突」。

shopify 增加youtube视频和选项卡
type: item
date: 2023-07-18T11:39:00+08:00
description: 引入相关资源 sun-tab-video-css style liquid <el-tabs id="sun-video-tab-content" v-model="activeName" @tab-click="handleClick" type="card"> </el-tabs> html section {% if customer.id or true %} {% if section.settings.render_first %} {% render 'sun-tab-video-css' %} {% endif %} {% if section.settings.tab_title == blank %} {% endif %} {% if section.settings.tab_title %} <el-tab-pane label="{{ section.settings.tab_title }}" name="{% if section.settings.render_first %}first{% else %} {{ section.id }}{% endif %}"> {% endif %} {% for block in section.blocks %} {{ block.settings.title }} {% endfor %} {% if section.settings.tab_title %} </el-tab-pane> {% endif %} {% if section.settings.render_last %} {% render 'sun-tab-video-js' %} {% endif %} {% endif %} {% schema %} { "name": "Sun Tab Video", "settings": [ { "type":"checkbox", "label":"Render First", "id":"render_first", "default": false }, { "type":"checkbox", "label":"Render Last", "id":"render_last", "default": false }, { "type":"number", "label":"Tab Count", "id":"tab_count" }, { "type":"text", "label":"Tab Title", "id":"tab_title" } ], "blocks":[ { "type":"text", "name":"Tab Item", "settings": [ { "type":"text", "id":"title", "label":"Item Title" }, { "type":"text", "id":"embed_id", "label":"Youtube Embed Id" }, { "type":"checkbox", "id":"max", "label":"Thumb Image Max?", "default":true } ] } ], "presets":[ { "name":"Sun Tab Video" } ] } {% endschema %}sun-tab-video-js

Vue3 学习笔记（七）
type: item
date: 2022-12-24T14:01:00+08:00
description: 02-详解接口与类型别名之间区别03-字面量类型和keyof关键字04-类型保护与自定义类型保护05-定义泛型和泛型常见操作06-类型兼容性详解07-映射类型与内置工具类型08-条件类型和infer关键字09-类中如何使用类型详解接口与类型别名之间区别接口接口是一系列抽象方法的声明，是一些方法特征的集合。简单来说，接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约。接口跟类型别名类似都是用来定义类型注解的，接口是用interface关键字来实现的，如下：interface A { username: string; age: number; } let a: A = { username: 'xiaoming', age: 20 }因为接口跟类型别名功能类似，所以接口也具备像索引签名，可调用注解等功能。interface A { [index: number]: number; } let a: A = [1, 2, 3]; interface A { (): void; } let a: A = () => {}接口与别名的区别那么接口跟类型别名除了很多功能相似外，他们之间也是具备某些区别的。对象类型接口合并接口继承映射类型第一个区别，类型别名可以操作任意类型，而接口只能操作对象类型。第二个区别，接口可以进行合并操作。interface A { username: string; } interface A { age: number; } let a: A = { username: 'xiaoming', age: 20 }第三个区别，接口具备继承能力。interface A { username: string } interface B extends A { age: number } let b: B = { username: 'xiaoming', age: 20 }B这个接口继承了A接口，所以B类型就有了username这个属性。在指定类型的时候，b变量要求同时具备A类型和B类型。第四个区别，接口不具备定义成接口的映射类型，而别名是可以做成映射类型的，关于映射类型的用法后面小节中会详细的进行讲解，这里先看一下效果。type A = { // success [P in 'username'|'age']: string; } interface A { // error [P in 'username'|'age']: string; }字面量类型和keyof关键字字面量类型在TS中可以把字面量作为具体的类型来使用，当使用字面量作为具体类型时, 该类型的取值就必须是该字面量的值。type A = 1; let a: A = 1;这里的A对应一个1这样的值，所以A类型就是字面量类型，那么a变量就只能选择1作为可选的值，除了1作为值以外，那么其他值都不能赋值给a变量。那么字面量类型到底有什么作用呢？实际上字面量类型可以把类型进行缩小，只在指定的范围内生效，这样可以保证值不易写错。type A = 'linear'|'swing'; let a: A = 'ease' // error比如a变量，只有两个选择，要么是linear要么是swing，不能是其他的第三个值作为选项存在。keyof关键字在一个定义好的接口中，想把接口中的每一个属性提取出来，形成一个联合的字面量类型，那么就可以利用keyof关键字来实现。interface A { username: string; age: number; } //keyof A -> 'username'|'age' let a: keyof A = 'username';如果我们利用typeof语法去引用一个变量，可以得到这个变量所对应的类型，如下：let a = 'hello'; type A = typeof a; // string 那么利用这样一个特性，可以通过一个对象得到对应的字面量类型，把typeof和keyof两个关键字结合使用。let obj: { username: 'xiaoming', age: 20 } let a: keyof typeof obj = 'username'类型保护与自定义类型保护类型保护类型保护允许你使用更小范围下的对象类型。这样可以缩小类型的范围保证类型的正确性，防止TS报错。这段代码在没有类型保护的情况下就会报错，如下：function foo(n: string|number){ n.length // error }因为n有可能是number，所以TS会进行错误提示，可以利用类型断言来解决，但是这种方式只是欺骗TS，如果在运行阶段还是可能报错的，所以并不是最好的方式。利用类型保护可以更好的解决这个问题。类型…

Vue3 学习笔记（六）
type: item
date: 2022-12-24T11:34:00+08:00
description: 为什么使用TS和TS运行环境搭建TypeScript是微软开发的一个开源的编程语言，通过在JavaScript的基础上添加静态类型定义构建而成。TypeScript通过TypeScript编译器或Babel转译为JavaScript代码，可运行在任何浏览器，任何操作系统。TS文件需要编译成JS文件首先我们的浏览器是不认识TS文件的，所以需要把TS编译成JS文件才可以，TS官网提供了一种方式，就是去全局安装typescript这个模块，命令如下：npm install -g typescript安装好后，就可以使用 tsc xxx.ts命名把TS文件自动转化成对应的JS文件了，在同级目录下就会生成一个xxx.js的文件，这个文件就是编译后的文件，浏览器是可以认识的。在TS编译JS文件的时候，会有一些细节，我们一起来看一下：第一，在tsc命令进行转换操作的时候，是不能实时进行转换的，那么可以通过添加一个-w的参数来完成实时转换的操作tsc xxx.ts -w第二，在编译后，我们会发现TS文件中定义的变量会产生错误的波浪线，这主要是因为TS默认是全局环境下的，所以跟其他文件中的同名变量冲突了，那么该如何解决呢？可以把全局环境改成局部的环境，只需要把TS文件变成一个模块化的文件，那么变量就只在模块内起作用，这样就不会产生冲突，从而引发错误的波浪线。let foo = 123; export {};第三，如果不想采用默认的编译方式，那么可以通过修改配置文件来改变一些默认的行为。配置文件需要叫做，tsconfig.json。可以通过tsc --init命令自动化的创建tsconfig.json这个文件，这个文件中的配置选项非常的多，我们会在后面小节中给大家进行详解的讲解，这里先修改其中的一两个配置，来感受一下配置文件的一个作用。{ “compilerOptions”: { "outDir": "./dist", //编译后文件输出的位置 "module": "ES6", //转换后模块的风格 "target": "ES5" //转换成JS不同语法版本 }, "include": ["xxx.ts"] //只对那些文件进行编译 }通过命令行输入tsc命令就可以自动去调用tsconfig.json这个文件了，非常的方便。为什么要使用TS去写程序TS编写代码的好处诸多，下面我们列出几点：友好的IDE提示强制类型，防止报错语言编写更加严谨快速查找到拼写错误JS的超集，扩展新功能下面通过几个小例子来感受一下TS比JS要优秀的点，let a = 123; a.map(()=>{}) // error这段代码在TS中是会报错的，因为a是一个数字，不会有map方法，而JS是不会给我们进行提示的。let a = 1; if(a === 1 && a === 2) { // error }这段代码在TS中是会报错的，因为从逻辑上来看这段代码并没有意义，因为a同一时间不可能既是1又是2。let a = { username: 'xiaoming', age: 20 }这段代码TS提示会非常的好，不会夹杂一些其他的提示信息，而且一旦单词写错了，TS会有非常好的提示效果。类型声明空间与变量声明空间变量声明空间在JS中我们只有变量声明空间，比如let a = 123。但是在TS中我们不仅存在变量声明空间，而且还存在类型声明空间。下面就让我们一起去探索一下类型声明空间的特点吧。类型声明空间可以通过type关键字来定义类型声明空间，type在TS中叫做类型别名。为了能够更好的区分两个空间，所以人为规定类型空间定义的名字首字母要大写，例如：type A = number。这里要注意，不要把两个空间进行互相赋值，会产生错误的，如下： let a = 'hello'; type B = a; // error type A = string; let a = A; // error但是在TS中，有的语法它既是变量声明空间也是类型声明空间，比如：类语法。class Foo {} // 类在TS中既是变量声明空间，也是类型声明空间 let a = Foo; // success type A = Foo; // success那么两个空间之间的关系有是什么呢？下一小节来进行学习。类型注解与类型推断上一个小节中，给大家留了一个思考题，那就是如何把两个空间联系到一起？主要采用类型注解来实现的。类型注解通过把变量空间与类型空间结合在一起的操作，就叫做类型注解，具体语法是通过冒号连接在一起的。let a: string = 'hello' //也可以通过类型别名进行连接 type A = string let a: A = 'hello'这样定义的a变量就具备了字符串类型，那么我们尝试给…

Vue3 学习笔记（五）
type: item
date: 2022-12-24T10:52:00+08:00
description: 章节介绍本章将学习VueRouter路由与Vuex状态管理 - 组织与架构应用。本章学习目标本章将学习Vue3中的路由与状态管理，随着前后端分离式开发的兴起，单页面应用开发（即SPA页面）也越来越流行，所以前端路由与共享状态也越来越重要！安排-什么是前端路由以及路由两种模式实现原理-路由的基本搭建与嵌套路由模式-动态路由模式与编程式路由模式-命名路由与命名视图与路由元信息-路由传递参数的多种方式及应用场景-详解route对象与router对象-路由守卫详解及应用场景-Vuex状态管理的概念及组件通信的总结-Vuex共享状态的基本开发流程-Vuex处理异步状态及应用场景-Vuex计算属性和辅助函数的使用-Vuex-persist对数据进行持久化处理-Vuex分割模块及多状态管理-组合式API中使用Router和Vuex注意事项-Router_Vuex的任务列表综合案例-Vue状态管理之Pinia存储库-搭建 Vite3 + Pinia2 组合模式路由的基本搭建与嵌套路由模式在前面的小节中，已经介绍了什么是前端路由以及前端路由所具备的特点。本小节就来对路由进行实际搭建吧。vue路由的搭建路由在vue中属于第三方插件，需要下载安装后进行使用。版本说明一下，Vue3搭配的是Vue Router4，目前正常安装的话，就是路由4的版本。如下：npm install vue-router安装好后，需要对路由进行配置，并且与Vue进行结合，让路由插件生效。在/src/router/index.js创建配置文件。 配置路由信息 可以通过 createWebHistory()来创建history模式的路由，也可以通过createWebHashHistory()来创建hash模式的路由。那么在浏览器中输入的URL该如何展示对应的组件呢？可以通过这个组件来实现。除了进行展示外，还可以通过方式进行声明式的路由跳转，代码如下： <router-link to="/">首页</router-link> | <router-link to="/about">关于</router-link> <router-view></router-view> 嵌套路由模式往往我们的路由是比较复杂的，需要的层级也比较多，那么就会产生嵌套路由的模式，比如：localhost:8080/about/foo和localhost:8080/about/barimport Foo from '@/views/Foo.vue' import Bar from '@/views/Bar.vue' const routes = [ { path: '/about', component: About, children: [ { path: 'foo', component: Foo }, { path: 'bar', component: Bar } ] } ]可以看到嵌套路由是通过children属性来完成的，那么对于这种嵌套路由写法，我们对应的也要在一级路由对应页面中添加一个，这样才能切换显示二级路由所对应的页面。动态路由模式与编程式路由模式动态路由模式所谓的动态路由其实就是不同的URL可以对应同一个页面，这种动态路由一般URL还是有规律可循的，所以非常适合做类似于详情页的功能。 动态路由 // router/index.js，定义动态路由 const routes = [ { path: 'foo/:id', component: Foo } ] // views/Foo.vue，获取动态路由的id export default { mounted(){ console.log( this.$route.params.id ); } }编程式路由前面介绍过如何在页面中对路由进行切换，可以采用声明式写法来完成，但是往往这种方式不够灵活，首先不能更灵活的控制结构和样式，其次不能自动进行路由的跳转，必须点击操作才行。那么编程式路由就会在JavaScript中通过逻辑的方式进行路由跳转，我们把这种写在JS中进行跳转路由的方式叫做编程式路由，这样方式会更加的灵活。 编程式路由跳转 可以看到在动态路由中使用到了一个route对象，而在编程式路由中使用了一个router对象，那么这两个比较重要的路由对象，会在后面的小节中给大家进行详细的讲解。命名路由与命名视图与路由元信息命名路由在路由跳转中，除了path 之外，你还可以为任何路由提供 name 的形式进行路由跳转。那么name方式的好处如下：没有硬编码的 URLparams 的自动编码/解码防止你在 url 中出现打字错误绕过路径排序（如显示一个）// router/index.js，定义命名路由 const routes = [ { path…

Vue3 学习笔记（四）
type: item
date: 2022-12-24T10:14:00+08:00
description: 章节介绍本章将学习Vue3组合式API详解 - 大型应用的高端写法。本章学习目标本章将学习Vue3组合式API（即：Composition API），组合式API是Vue3组织代码的一种新型写法，有别于选项式的API。学会使用这种风格进行编程，并应用在项目之中。什么是组合式API组合式API是有别于选项式API的另一种新型写法，它更适合编写复杂的应用，假如我们要完成一个搜索功能，可能会有如下功能需要实现：搜索提示列表搜索结果列表搜索记录列表 搜索案例 那么分别通过选项式和组合式是如何组织和实现代码的呢？可以发现选项式组织代码的时候，代码的跳跃性特别的强，对于后期维护特别的不方便；而组合式则是把相同功能的代码放到一起，功能独立，易于维护。 选项式VS组合式 课程安排-setup方法与script_setup及ref响应式-事件方法_计算属性_reactive_toRefs-生命周期_watch_watchEffect-跨组件通信方案provide_inject-复用组件功能之use函数-利用defineProps与defineEmits进行组件通信-利用组合式API开发复杂的搜索功能-利用组合式API开发搜索提示列表-利用组合式API开发搜索结果列表-利用组合式API开发搜索历史列表setup方法与script_setup及ref响应式setup方法与script_setup在Vue3.1版本的时候，提供了setup方法；而在Vue3.2版本的时候，提供了script_setup属性。那么setup属性比setup方法对于操作组合式API来说会更加的简易。 setup方法 {{ count }} // Vue3.1 // Vue3.2 setup方法是需要把数据进行return后，才可以在template标签中进行使用，而setup属性方式定义好后就可以直接在template标签中进行使用。ref响应式如何在组合式API中来完成数据的响应式操作，通过的就是ref()方法，需要从vue模块中引入这个方法后才可以使用。 事件方法_计算属性 reactive_toRefs事件方法与计算属性下面看一下在组合式API中是如何实现事件方法和计算属性的。 点击 {{ count }}, {{ doubleCount }} 事件方法直接就定义成一个函数，计算属性需要引入computed方法，使用起来是非常简单的。reactive与toRefsreactive()方法是组合式API中另一种定义响应式数据的实现方式，它是对象的响应式副本。 reactive {{ state.count }} reactive()方法返回的本身就是一个state对象，那么在修改的时候就不需要.value操作了，直接可以通过state.count的方式进行数据的改变，从而影响到视图的变化。ref()和reactive()这两种方式都是可以使用的，一般ref()方法针对基本类型的响应式处理，而reactive()针对对象类型的响应式处理，当然还可以通过toRefs()方法把reactive的代码转换成ref形式。 reactive {{ state.count }}, {{ count }} 生命周期_watch_watchEffect生命周期钩子函数在学习选项式API的时候，我们学习了生命周期钩子函数，那么在组合式API中生命周期又是如何使用的呢？下面我们从图中先看一下对比的情况吧。 生命周期对比 那么具体的区别如下：组合式中是没有beforeCreate和created这两个生命周期，因为本身在组合式中默认就在created当中，直接定义完响应式数据后就可以直接拿到响应式数据，所以不需要再有beforeCreate和created这两个钩子组合式的钩子前面会有一个on，类似于事件的特性，那就是可以多次重复调用 watch与watchEffect这里先说一下watchEffect的用法，为了根据响应式状态自动应用和重新应用副作用，我们可以使用 watchEffect 函数。它立即执行传入的一个函数，同时响应式追踪其依赖，并在其依赖变更时重新运行该函数。watchEffect常见特性：一开始会初始触发一次，然后所依赖的数据发生改变的时候，才会再次触发触发的时机是数据响应后，DOM更新前，通过flush: 'post' 修改成DOM更新后进行触发返回结果是一个stop方法，可以停止watchEffect的监听提供一个形参，形参主要就是用于清除上一次的行为 watchEffect {{ count }} 再来看一下watch侦听器的使用方式，如下： 那么watch与watchEffect的区别是什么呢？懒执行副作用更具体地说明什么状态应该触发侦听器重新运行访问侦听状态变化前…

Vue3 学习笔记（三）
type: item
date: 2022-12-23T17:56:00+08:00
description: -ref属性在元素和组件上的分别使用-利用nextTick监听DOM更新后的情况-自定义指令与自定义全局属性及应用场景-复用组件功能之Mixin混入-插件的概念及插件的实现-Element Plus框架的安装与使用-transition动画与过渡的实现-动态组件与keep-alive组件缓存-异步组件与Suspense一起使用-跨组件间通信方案 Provide_Inject-Teleport实现传送门功能-虚拟DOM与render函数及Diff算法ref属性在元素和组件上的分别使用ref属性Vue是基于MVVM设计模式进行实现的，视图与数据不直接进行通信，但是Vue并没有完全遵循这一原则，而是允许开发者直接进行原生DOM操作。在Vue中可通过ref属性来完成这一行为，通过给标签添加ref属性，然后再通过vm.$refs来获取DOM，代码如下： ref属性 点击 aaaaaaaaa bbbbbbbbb 除了可以把ref属性添加给DOM元素外，还可以把ref属性添加给组件，这样可以获取到组件的实例对象，可以间接的实现组件之间的通信，代码如下： ref属性 <my-head ref="elem3"></my-head> 2_头部组件.vue文件： hello myhead 利用nextTick监听DOM更新后的情况nextTick方法，它的主要作用是将回调推迟到下一个 DOM 更新周期之后执行。在更改了一些数据以等待 DOM 更新后立即使用它。默认情况下，数据的更新会产生一个很小的异步延迟，所以直接再数据改变后取获取DOM是得不到DOM更新后的结果，而得到的是DOM更新前的结果。 hello nextTick {{ message }} 如何才能得到DOM更新后的结果呢，可以有两种方案，第一种就是利用生命周期updated这个钩子函数，第二种就是利用我们讲的nextTick方法，支持两种风格即回调和promise。 hello nextTick {{ message }} 自定义指令与自定义全局属性及应用场景除了核心功能默认内置的指令 (例如 v-model 和 v-show)，Vue 也允许注册自定义指令，来实现一些封装功能。自定义指令的实现首先来实现一个简单的v-color指令，用于给元素添加背景色，代码如下： 自定义指令 aaaaaaa 这里的回调函数是指令中mounted生命周期和updated生命周期的简写方式。下面我们来完成一个实际可以应用的指令，按钮权限指令，一般情况下这种指令不会局部使用，而是全局使用，所以可以通过vue来实现一个全局的按钮权限指令，代码如下：// main.js app.directive('auth', (el, binding) => { let auths = ['edit', 'delete']; let ret = auths.includes(binding.value); if(!ret){ el.style.display = 'none'; } }); // demo.vue 编辑 自定义全局属性添加一个可以在应用的任何组件实例中访问的全局 property，这样在引入一些第三方模块的时候，就不用每一次进行import操作，而是直接通过this对象去访问全局属性即可，下面举一个例子，实现一个http的全局属性。// main.js app.config.globalProperties.$http = http; //demo.vue 复用组件功能之Mixin混入Mixin混入了解一下mixin混入，它是选项式API的一种复用代码的形式，可以非常灵活的复用功能。// mymixin.js const myMixin = { data(){ return { message: '复用的数据' } }, computed: { message2(){ return '复用的数据2' } } }; export { myMixin } // mymixin.vue mixin混入 {{ message }} {{ message2 }} 这样就可以直接在.vue中使用这些混入的功能。当然这种方式是局部混入写法，也可以进行全局混入的写法，代码如下：// main.js import { myMixin } from '@/mymixin.js' app.mixin(myMixin)mixin存在的问题也是有的，那就是不够灵活，不支持传递参数，这样无法做到差异化的处理，所以目前比较推荐的复用操作还是选择使用组合式API中的use函数来完成复用的逻辑处理。插件的概念及插件的实现插件是自包含的代码，通常向 Vue 添加全局级功能。例如：全局方法、全局组件、全局指令、全局mixin等等。基于Vue…

Vue3 学习笔记（二）
type: item
date: 2022-12-23T16:13:00+08:00
description: 02-组件的概念及组件的基本使用方式03-组件之间是如何进行互相通信的04-组件的属性与事件是如何进行处理的05-组件的内容是如何组合与分发处理的06-仿Element Plus框架的el-button按钮组件实现07-单文件组件SFC及Vue CLI脚手架的安装使用08-脚手架原理之webpack处理html文件和模块打包09-脚手架原理之webpack启动服务器和处理sourcemap10-脚手架原理之webpack处理样式模块和图片模块11-脚手架原理之webpack处理单文件组件及loader转换12-Vite3介绍及基本使用13-仿Element Plus的el-rate评分组件实现(单文件组件)官网地址：https://cn.vuejs.org/Vue.js文件下载地址下载地址：https://unpkg.com/vue@3.2.36/dist/vue.global.js组件的概念及组件的基本使用方式组件的概念组件是带有名称的可复用实例，通常一个应用会以一棵嵌套的组件树的形式来组织，比如：页头、侧边栏、内容区等组件。 vue组件 组件可以拥有自己独立的结构，样式，逻辑。这样对于后期的维护是非常方便的。下面给出评分组件与按钮组件的抽离过程。 组件的划分 组件的命名方式与规范定义组件可通过驼峰、短线两种风格定义调用组件推荐短线方式 <my-head></my-head> 根组件app容器可以看成根组件，所以根组件跟普通组件都具备相同的配置信息，例如：data、computed、methods等等选项。 <my-head></my-head> 根组件与MyHead组件形成了父子组件。局部组件与全局组件局部组件只能在指定的组件内进行使用，而全局组件可以在容器app下的任意位置进行使用。组件之间是如何进行互相通信的上一个小节中，我们了解了组件是可以组合的，那么就形成了父子组件，父子组件之间是可以进行通信的， 那么为什么要通信呢？主要是为了让组件满足不同的需求。 组件之间差异化 父子通信最常见的通信方式就是父传子，或者子传父，那么父传子通过props实现，而子传父则通过emits自定义事件实现。 父子通信 <my-head :count="count" @custom-click="handleClick"></my-head> 父子通信需要注意的点组件通信的props是可以定义类型的，在运行期间会进行检测组件之间的数据是单向流动的，子组件不能直接修改传递过来的值但是有时候也需要数据的双向流动，可利用v-model来实现组件的属性与事件是如何进行处理的有时候组件上的属性或事件并不想进行组件通信，那么Vue是如何处理的呢？组件的属性与事件默认不通过props接收的话，属性会直接挂载到组件容器上，事件也是如此，会直接挂载到组件容器上。可通过 inheritAttrs 选项阻止这种行为，通过指定这个属性为false，可以避免组件属性和事件向容器传递。可通过 $attrs 内置语法，给指定元素传递属性和事件，代码如下： <my-head title="hello world" class="box" @click="handleClick"></my-head> $attrs也可以实现组件之间的间接通信。组件的内容是如何组合与分发处理的在前面的小节中，我们学习了组件之间的通信，让组件之间实现了不同的需求，我们通过给组件添加不同的属性来实现。那么在Vue中如何去传递不同的组件结构呢？这就涉及到了组件内容的分发处理。插槽slot在Vue中是通过插槽slot方式来进行分发处理的，Vue 实现了一套内容分发的 API，这套 API 的设计灵感源自 Web Components 规范草案，将 元素作为承载分发内容的出口。 <my-head> logo </my-head> 组件内的结构，即 logo 会被分发到<slot></slot>所在的区域。内容分发与插槽的注意点渲染作用域 -> 插槽只能获取当前组件的作用域具名插槽 -> 处理多个插槽的需求，通过v-slot指令实现，简写为#作用域插槽 -> 希望插槽能访问子组件的数据完整代码如下： <my-head> logo, {{ message }}, {{ count }} {{ item }} </my-head> 单文件组件SFC及Vue CLI脚手架的安装使用Vue 单文件组件（又名 *.vue 文件，缩写为 SFC）是一种特殊的文件格式，它允许将 Vue 组件的模板、逻辑 与 样式封装在单个文件中。为什么要使用 SFC使用 SFC 必须使用构建工具，但作为回报带来了以下优点：使用熟悉的 HTML、CSS 和 JavaScript 语法编写模块化的组件让本来就强相关的关注点自然内聚预编译…

Vue3学习笔记（一）
type: item
date: 2022-12-23T13:51:00+08:00
description: 03-选项式API的编程风格与优势04-声明式渲染及响应式数据实现原理05-指令系统与事件方法及传参处理06-计算属性与侦听器区别与原理（一）06-计算属性与侦听器区别与原理（二）07-条件渲染与列表渲染及注意点08-class样式与style样式的三种形态09-表单处理与双向数据绑定原理10-生命周期钩子函数及原理分析11-搜索关键词加筛选条件的综合案例选项式API的编程风格与优势选项式API，即：options APIlet vm = createApp({ methods: {}, computed: {}, watch: {}, data(){}, mounted(){} })这种写法的优势：只有一个参数，不会出现参数顺序的问题，随意调整配置的位置非常清晰，语法化特别强非常适合添加默认值的声明式渲染及响应式数据实现原理Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统： Counter: {{ counter }} const Counter = { data() { return { counter: 0 } } } Vue.createApp(Counter).mount('#counter')声明式编程：不需要编写具体是如何实现的，直接调用声明就可以实现功能。SQL就是比较经典的声明式语言：SELECT * from user WHERE username = xiaomingfor(var i=0;i<user.length;i++) { if(user[i].username == "xiaoming") { print("find"); break; } }注意：数据是通过 {{ }} 模板语法来完成的，模板语法支持编写JS表达式响应式数据实现的原理：利用JS的Proxy对象。Proxy 用于修改某些操作的默认行为，等同于在语言层面做出修改，其实就是直接监控值的修改，当值发生改变的时候，可以监控到。 指令系统与事件方法及传参处理指令系统就是通过自定义属性实现的一套功能，也是声明式编程的体现。通常在标签上添加 v-* 字样，常见的指令有：v-bind -> 操作标签属性，可通过 : 简写v-on -> 操作事件，可通过 @ 简写 这是一个段落 点击 {{ message }} 如何添加事件方法，通过methods选项API实现，并且Vue框架已经帮我们帮事件传参机制处理好了。 点击 计算属性与侦听器区别与原理计算属性模板内的表达式非常便利，但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护，所以过于复杂的逻辑可以移植到计算属性中进行处理。 {{ reverseMessage }} 计算属性与方法比较像，如下所示： {{ reverseMessageMethod() }} {{ reverseMessageMethod() }} {{ reverseMessage }} {{ reverseMessage }} 计算属性跟方法相比，具备缓存的能力，而方法不具备缓存，所以上面代码执行完，会弹出两次1和一次2。注意：默认是只读的，一般不会直接更改计算属性，如果想更改也是可以做到的，通过Setter写法实现，官方地址。既然计算属性编写的是一个函数，而调用的时候以函数名的形式进行使用，其实实现起来也不是特别难的事情：let computed = { num(){ return 123; } } let vm = {} for(let attr in computed){ Object.defineProperty(vm, attr, { value: computed[attr]() }) }侦听器虽然计算属性在大多数情况下更合适，但有时也需要一个自定义的侦听器。侦听器的目的：侦听器用来观察和响应Vue实例上的数据变动,类似于临听机制+事件机制。当有一些数据需要随着其它数据变化而变化时,就可以使用侦听器。 {{ message }} 有时候，计算属性 和 侦听器 往往能实现同样的需求，那么他们有何区别呢？计算属性适合：多个值去影响一个值的应用；而侦听器适合：一个值去影响多个值的应用侦听器支持异步的程序，而计算属性不支持异步的程序class样式与style样式的三种形态操作元素的 class 列表和内联样式是数据绑定的一个常见需求。因为它们都是 attribute，所以我们可以用 v-bind 处理它们：只需要通过表达式计算出字符串结果即可。不过，字符串拼接麻烦且易错。因此，在将 v-bind 用于 class 和 style 时，Vue.js 做了专门的增强。表达式结果的类型除了字符串之外，还可以是对象或数组。字符串数组对象let vm = Vue.cr…

Vue3学习笔记
type: item
date: 2022-11-10T11:20:00+08:00
description: Vue3全家桶：Vue3,Composition API,Options API,Element Plus,Vue Router,Vue CLI,Vuex,Pinia,ViteVue3核心知识点：MVVM设计模式、响应式数据实现原理、指令系统、计算属性与侦听器、条件渲染与列表渲染、class样式与style样式的三种形态、表单处理、生命周期钩子函数、组件通信、组件属性与事件、组件内容分发、脚手架使用及原理实现、ref属性在元素和组件上、nextTick监听DOM、自定义指令及应用场景、组件功能之Mixin混入、插件的概念及插件的实现、动态组件与keep-alive组件缓存、transition动画与过渡的实现、异步组件与Suspense, Provide_Inject、Teleport、虚拟DOM与render函数及Diff算法、setup方法与script_setup及ref响应式、reactive,toRefs, watchEffect, defineProps...TypeScript与框架结合Vue组合式+TS，状态管理+TSVue选项式+TS，组件库+TSReact类组件+TS，Axios+TSReact函数组件+TS，路由+TSTypeScript核心知识点类型声明空间与变量声明空间、类型注解与类型推断、类型分类与联合类型与交叉类型、never类型与any类型与unknown类型、类型断言与非空断言、数组类型与元祖类型、对象类型与索引签名、函数类型与void类型、函数重载与可调用注解、枚举类型与const枚举、详解接口与类型别名之间区别、字面量类型和keyof关键字、类型保护与自定义类型保护、定义泛型和泛型常见操作、类型兼容性详解、映射类型与内置工具类型、条件类型和infer关键字、类中如何使用类型、模块系统与命名空间、d.ts声明文件和declare关键字、@types和DefinitelyTyped仓库、lib.d.ts和global.d.ts、tsconfig.json...MVC设计模式与MVVM设计模式选项式API的编程风格与优势指令系统与事件方法及传参处理声明式宣染及响应式数据实现原理计算属性与侦听器区别与原理条件渲染与列表宣染及注意点class样式与style样式的三种形态表单处理与双向数据绑定原理生命周期钩子函数及原理分析MVC设计模式与MVVM设计模式为什么使用Vue框架?◆最大的优点:就是不用自己完成复杂的DOM操作了,而由框架帮我们去完成选项式API的编程风格与优势：let vm = createApp( /* 选项*/ methods: {}, computed: {}, watch:{}, data(){}, mounted(){} }).mount(' #app');💠只有一个参数,不会出现参数顺序的问题,随意调整配置的位置 💠 非常清晰,语法化特别强 💠 非常适合添加默认值的声明式宣染及响应式数据实现原理💠利用ES6的Proxy对象对底层进行了监控计算属性与侦听器区别与原理🔸计算属性适合: 多个值去影响一个值的应用;而侦听器适合一个值去影响多个值的应用🔸侦听器支持异步的程序,而计算属性不支持异步的程序🔷 条件渲染:使用v-if指令条件性地宣染一块内容。这块内容只会在指令的表达式返回truthy真值的时候被渲染🔷 falsy假值 (即 false,0,-0, On, "“,null, undefined和NaN)条件宣染与列表渲染及注意点：列表宣染需要添加key属性 -> 用来跟踪列表的身份v-if和v-for尽量不要一起使用 -> 利用计算属性来完成这类功能template标签起到的作用 -> 形成一个整体容器并且不会被宣染 <!-- <input- type="text" - v-model="message">-->