关于vue.js:React-vue-常见问题

1. webpack 解决依赖,反复打包的问题 装置webpack-bundle-analyzer插件来剖析打包形成,发现有一些包被反复的打包了屡次,在webpack 配置中设置别名就能够。 module.exports = [ ... resolve: { alias: { 'text-encoding' : path.resolve(process.cwd(), 'node_modules', 'text-encoding') } }, ...]

June 24, 2022 · 1 min · jiezi

关于vue.js:Vue-异步组件的实现原理

异步组件为什么须要异步组件Vue 作为单页面利用在加载首页时常会遇到加载迟缓的问题,导致在应用体验较差,这是因为在打包单页面利用时,页面会吧脚本打包成一个文件,这个文件蕴含了所有业务和非业务的代码, 脚本文件过大导致渲染页面时迟缓。在进行首屏性能优化时,最罕用的办法就是对于文件的拆分和代理的拆散,按需加载的概念也是在这个前提下引入的。因而在 Vue 开发过程中,咱们会把一些非首屏的组件设计成异部组件,局部不影响首次视觉体验的组件也能够设计成异步组件。定义异步组件在 Vue 中,在注册组件时应用一个工厂函数定义组件,这个工厂函数会异步解析组件定义,只有当这个组件须要被渲染时才会触发该工厂函数,并且会把后果缓存起来以便后续应用。 // 注册全局组件时,定义为异步组件Vue.component("async-component", (resolve, reject)=>{ setTimeout(()=>{ // 应用一个定时器来模仿异步加载过程 // resolve 须要返回一个组件的定义对象,该对象的属性与定义一般组件的属性统一 resolve({ template: "<div>async-component</div>" }) }, 2000)})// 注册部分异步组件const vm = new Vue({ components:{ asyncComponent: ()=> import('./test.vue') }})异步组件流程剖析在组件根底的剖析过程中,咱们剖析了实例的挂载流程分为依据渲染函数创立 Vnode 和依据 Vnode 创立实在 DOM 的过程。在创立 Vnode 的过程中,如果遇到组件占位符,会调用 createComponent ,在该办法中,会为子组件做选项合并和装置钩子函数。异步组件的解决也是在该函数中进行的。 function createComponent ( Ctor: Class<Component> | Function | Object | void, data: ?VNodeData, context: Component, children: ?Array<VNode>, tag?: string): VNode | Array<VNode> | void { if (isUndef(Ctor)) { return } /** * 这里的 baseCtor 为 Vue 构造函数 */ const baseCtor = context.$options._base // async component // 异步组件 let asyncFactory if (isUndef(Ctor.cid)) { asyncFactory = Ctor Ctor = resolveAsyncComponent(asyncFactory, baseCtor) if (Ctor === undefined) { // return a placeholder node for async component, which is rendered // as a comment node but preserves all the raw information for the node. // the information will be used for async server-rendering and hydration. return createAsyncPlaceholder( asyncFactory, data, context, children, tag ) } } data = data || {} // 合并结构器配置 resolveConstructorOptions(Ctor) // 装置组件钩子函数 installComponentHooks(data) const name = Ctor.options.name || tag const vnode = new VNode( `vue-component-${Ctor.cid}${name ? `-${name}` : ''}`, data, undefined, undefined, undefined, context, { Ctor, propsData, listeners, tag, children }, asyncFactory ) return vnode}在注册异步组件时, Vue.component(name, options) 第二个参数工厂函数不是一个一般对象,因而无论是全局注册还是部分注册, 都不会执行 Vue.extend 办法生成子类结构器,所以在下面的 createComponent 办法中, Ctor.cid 不会存在,代码进入异步组件的分支。 ...

June 24, 2022 · 4 min · jiezi

关于vue.js:Vue基础点梳理

1、vue指令-v-model修饰符 语法: v-model.修饰符="vue数据变量" .number 以parseFloat转成数字类型.trim 去除首尾空白字符.lazy 在失去焦点时触发更改而非inupt时2、计算属性 计算属性有缓存,进步渲染性能。 如果在页面上须要用到 对现有的数据进行加工失去新数据,则时要应用计算属性。 写法: computed: { "属性名": { set(值){ }, get() { return "值" } }}3、vue监听器 能够监听数据(data/computed等)的值的扭转。数据的值有类型:根本数据类型,援用数据类型 深度监听 watch: { "要监听的属性名": { immediate: true, // 立刻执行 deep: true, // 深度监听简单类型内变动 handler (newVal, oldVal) { } }}4、scoped实现组件的公有款式 <stype scoped> h2 {} // 款式只会在以后组件内失效</style>5、父传子 父组件 <template> <div> <child :users="user"></child> <!-- 子组件绑定users变量--> </div></template> <script>import { child } from "./child";export default { components: { child }, data() { return { user: '张三' }; }};</script>子组件 ...

June 23, 2022 · 2 min · jiezi

关于vue.js:Vue3响应式源码分析-reactive篇

最近一阶段在学习Vue3,Vue3中用 reactive、ref 等办法将数据转化为响应式数据,在获取时应用 track 往 effect 中收集依赖,在值扭转时,应用 trigger 触发依赖,执行对应的监听函数,这次就先来看一下 reactive 的源码。 reactive的源码在官网源码的packages/reactivity/src/reactive.ts文件中,源码中提供了四个Api来创立reactive类对象: reactive:创立可深刻响应的可读写对象readonly:创立可深刻响应的只读对象shallowReactive:创立只有第一层响应的浅可读写对象(其余层,值扭转视图不更新)shallowReadonly:创立只有一层响应的浅只读对象它们都是调用createReactiveObject办法来创立响应式对象,区别在于传入不同的参数,本文只讲reactive,其余几个大同小异: export function reactive(target: object) { // 如果是只读的话间接返回 if (isReadonly(target)) { return target } return createReactiveObject( // 指标对象 target, // 标识是否是只读 false, // 罕用类型拦截器 mutableHandlers, // 汇合类型拦截器 mutableCollectionHandlers, // 储了每个对象与代理的map关系 reactiveMap )}export const reactiveMap = new WeakMap<Target, any>()createReactiveObject代码如下: function createReactiveObject( target: Target, isReadonly: boolean, baseHandlers: ProxyHandler<any>, collectionHandlers: ProxyHandler<any>, proxyMap: WeakMap<Target, any>) { // 如果代理的数据不是对象,则间接返回原对象 if (!isObject(target)) { return target } // 如果传入的曾经是代理了 并且 不是readonly 转换 reactive的间接返回 if ( target[ReactiveFlags.RAW] && !(isReadonly && target[ReactiveFlags.IS_REACTIVE]) ) { return target } // 查看以后代理对象之前是不是创立过以后代理,如果创立过间接返回之前缓存的代理对象 // proxyMap 是一个全局的缓存WeakMap const existingProxy = proxyMap.get(target) if (existingProxy) { return existingProxy } // 如果以后对象无奈创立代理,则间接返回源对象 const targetType = getTargetType(target) if (targetType === TargetType.INVALID) { return target } // 依据targetType 抉择汇合拦截器还是根底拦截器 const proxy = new Proxy( target, targetType === TargetType.COLLECTION ? collectionHandlers : baseHandlers ) // 向全局缓存Map里存储 proxyMap.set(target, proxy) return proxy}其中有个办法是 getTargetType,用来获取传入target的类型: ...

June 22, 2022 · 6 min · jiezi

关于vue.js:vue轻松实现折叠面板功能

如上图的折叠面板性能你是否有去实现过呢?如果有那你的实现形式是什么样的?遇到了什么问题?如果没有那就看看我的实现形式吧 1、最大的难题这种折叠成果理论管制的是元素的高度,css、js管制元素高度的属性有height、max-height。 既然是通过height来实现,那很简略,我间接通过款式来解决,如下: .collapse-transition-enter-from,.collapse-transition-leave-to{ height: 0;}.collapse-transition-enter-active,.collapse-transition-leave-active{ overflow: hidden; transition: height .3s ease-in-out, padding .3s ease-in-out, max-height .3s ease-in-out;}.collapse-transition-enter-to,.collapse-transition-leave-from{ height: auto;}自信的写完上述代码并运行后你会发现,这并任何没有过渡成果,并且元素在暗藏的时候还有点卡顿的感觉 这是为什么呢? 起因是:transition对height: auto有效,height必须设置除auto外的有效值才会失效 那么问题来了,该什么时候获取并设置元素的高度?什么时候该复原元素的高度?答案是: 1、进入时,过渡成果进入后获取并设置元素的高度,进入过渡成果实现后立刻复原2、来到时,过渡成果来到前获取并设置元素的高度,来到过渡成果实现后立刻复原这里波及到了4个机会,因而光靠css是实现不了的,还需依附<transition>组件的钩子2、残缺代码<template> <transition :name="transitionName" @before-enter="collapseBeforeEnter" @enter="collapseEnter" @after-enter="collapseAfterEnter" @before-leave="collapseBeforeLeave" @leave="collapseLeave" @after-leave="collapseAfterLeave"> <slot></slot> </transition></template><script>/** * 元素折叠适度成果 */export default { name: 'CollapseTransition', props: { transitionName: { type: String, default: 'collapse-transition' } }, data () { return { oldPaddingTop: '', oldPaddingBottom: '', oldOverflow: '' } }, methods: { collapseBeforeEnter (el) { // console.log('11, collapseBeforeEnter'); this.oldPaddingBottom = el.style.paddingBottom; this.oldPaddingTop = el.style.paddingTop; // 过渡成果开始前设置元素的maxHeight为0,让元素maxHeight有一个初始值 el.style.paddingTop = '0'; el.style.paddingBottom = '0'; el.style.maxHeight = '0'; }, collapseEnter (el, done) { // console.log('22, collapseEnter'); // this.oldOverflow = el.style.overflow; let elHeight = el.scrollHeight; // 过渡成果进入后将元素的maxHeight设置为元素自身的高度,将元素maxHeight设置为auto不会有过渡成果 if (elHeight > 0) { el.style.maxHeight = elHeight + 'px'; } else { el.style.maxHeight = '0'; } el.style.paddingTop = this.oldPaddingTop; el.style.paddingBottom = this.oldPaddingBottom; el.style.overflow = 'hidden'; // done(); let onTransitionDone = function () { done(); // console.log('enter onTransitionDone'); el.removeEventListener('transitionend', onTransitionDone, false); el.removeEventListener('transitioncancel', onTransitionDone, false); }; // 绑定元素的transition实现事件,在transition实现后立刻实现vue的适度动效 el.addEventListener('transitionend', onTransitionDone, false); el.addEventListener('transitioncancel', onTransitionDone, false); }, collapseAfterEnter (el) { // console.log('33, collapseAfterEnter'); // 过渡成果实现后复原元素的maxHeight el.style.maxHeight = ''; el.style.overflow = this.oldOverflow; }, collapseBeforeLeave (el) { // console.log('44, collapseBeforeLeave', el.scrollHeight); this.oldPaddingBottom = el.style.paddingBottom; this.oldPaddingTop = el.style.paddingTop; this.oldOverflow = el.style.overflow; el.style.maxHeight = el.scrollHeight + 'px'; el.style.overflow = 'hidden'; }, collapseLeave (el, done) { // console.log('55, collapseLeave', el.scrollHeight); if (el.scrollHeight !== 0) { el.style.maxHeight = '0'; el.style.paddingBottom = '0'; el.style.paddingTop = '0'; } // done(); let onTransitionDone = function () { done(); // console.log('leave onTransitionDone'); el.removeEventListener('transitionend', onTransitionDone, false); el.removeEventListener('transitioncancel', onTransitionDone, false); }; // 绑定元素的transition实现事件,在transition实现后立刻实现vue的适度动效 el.addEventListener('transitionend', onTransitionDone, false); el.addEventListener('transitioncancel', onTransitionDone, false); }, collapseAfterLeave (el) { // console.log('66, collapseAfterLeave'); el.style.maxHeight = ''; el.style.overflow = this.oldOverflow; el.style.paddingBottom = this.oldPaddingBottom; el.style.paddingTop = this.oldPaddingTop; this.oldOverflow = this.oldPaddingBottom = this.oldPaddingTop = ''; } }};</script><style lang="less">.collapse-transition-enter-active,.collapse-transition-leave-active{ transition: height .3s ease-in-out, padding .3s ease-in-out, max-height .3s ease-in-out;}</style>看完代码后你可能会奇怪为什么是设置元素的max-height而不是元素的height?这么做的起因是:不论元素自身有没有通过style设置height,都不会影响元素高度的计算 ...

June 22, 2022 · 2 min · jiezi

关于vue.js:Vue中使用echarts以及项目部署Nginx

vue我的项目中应用echarts原生js的话,须要引入cdn;vue开发的话,npm i echarts --save main.js中引入echarts,和service、element-ui一样,先导入,再全局挂载 // main.jsimport echarts from 'echarts'Vue.prototype.$echarts = echarts// 在特定文件中应用echartsimport echarts from "echarts"办法总结如下: 给容器,容器得有高度给数据初始化绘图表<div class="main1" style="height:300px"></div><div class="main2" style="height:300px"></div>let myChart1 = this.$echarts.init(document.getElementClassName("main1"))myChart1.setOption({ title:{ text:"题目" }, xAxis:{ data:["广东","江苏","山东","陕西"] }, yAxis:{}, series:[{ name:"资产状况", type:"bar", data:[34,23,54,56] }] })let myChart2 = this.$echarts.init(document.getElementClassName("main2"))let option = { title:{ text:"题目" }, xAxis:{ data:["广东","江苏","山东","陕西"] }, legend:{ data:["线条1","线条2","线条2","线条3"] }, yAxis:{}, series:[{ name:"线条1", type:"line", data:[34,23,54,56] }, name:"线条2", type:"line", data:[24,13,55,36] },{ name:"线条3", type:"line", data:[31,86,25,86] },{ name:"线条4", type:"line", data:[14,53,25,06] }]}myChart2.setOption(option);express启动nodeJS后端服务初始化,失去一个package.json文件 npm init -y下载配置文件内文件 ...

June 22, 2022 · 1 min · jiezi

关于vue.js:非常漂亮的后台Vue3ElementPlusPiniaEchartsAPIMock双接口Composition-api

TodoAdmin-Vue版:是一个集成治理后盾端模板解决方案,我的项目采纳TS(TypeScript)脚本语言,基于Vue 3.2+/Vue-cli 5.0+/Vue-router 4.0+、Axios0.2.7、Element-plus 2.2+、Pinia 2.0+、ECharts 5.3.2以及Mockjs等搭建,我的项目是以Composition api格调编写,采纳近程API接口和本地Mock双接口模式加载数据。Demo体验&仓库地址Todoadmin-pro Pro专业版演示地址(vue3.2+ 反对 PC、平板、手机)Todoadmin-base 根本版演示地址(vue3.2+ 反对 PC、平板、手机)Github 地址Gitee 码云地址用户名:guest明码:123456我的项目生态插件【依赖】列表题目名称 版本 形容vue 3.2+ 构建用户界面的渐进式框架vue-router 4.0+ 单页应用程序路由vue-cli 5+ 我的项目脚手架axios 0.2.7 基于promise的网络申请库element-plus 2.2+ 基于Vue3的组件库element-plus-icons 2.2+ 基于Vue3的组件图标库vue-quill 1.0.0.beta.8 可视化在线文本编辑器quill-image-resize 3.0+ 文本编辑器图片重置尺寸vue-cropper 1.0+ 基于Vue3的图片裁剪pinia 2.0+ 状态治理vue-i18n-next 9.1+ 多国语言文字切换js-md5 0.7.3 MD5加密nprogress 0.2.0 进度条加载echarts 5.3.2 多功能图表 我的项目装置(依赖装置)npm install or yarn install运行开发环境npm run serve or yarn serve生产环境打包npm run build or yarn build修复文件npm run lint克隆我的项目 拜访Github仓库# 克隆我的项目git clone -b https://github.com/todoadmin-com/vue3-elementPlus-pinia.git# 装置依赖npm i# 本地开发 启动我的项目npm run serve克隆我的项目 拜访Gitee仓库# 克隆我的项目git clone -b https://gitee.com/todoadmin-com/vue3-element-plus-pinia.git# 装置依赖npm i# 本地开发 启动我的项目npm run serve后盾效果图预览以下是截取效果图展现: ...

June 21, 2022 · 1 min · jiezi

关于vue.js:View-UI-Plus-发布-130-版本新增-SpaceImagePreview-组件

View UI Plus 1.3.0 版本已于 2022-06-21 公布。 更新日志请到官网 www.iviewui.com 查看最新版。新增间距组件 Space。ImagePreview 新增下载图片性能。ImagePreview 新增属性 toolbar,可抉择开启的快捷性能并排序。图片预览反对 $ImagePreview 实例化调用。ImagePreview 新增拖拽手势款式。Skeleton 默认款式,减少最初一个段落成果。Result 属性 type 新增 warning。优化大量文档示例。修复 Select 近程搜寻的问题。修复 ImagePreview 点击管制条敞开预览的问题。修复 Layout 款式问题。修复局部组件 types 谬误的问题。更新办法1.批改 package.json 中 view-ui-plus 版本号: "dependencies": { "view-ui-plus": "^1.3.0" }2.运行 npm update view-ui-plus。 内容简介Space 间距组件间距组件能够很不便地设置相邻组件之间的对立间距。比方上面的场景,在没有应用 Space 间距组件时的成果是: <Button>在线预览</Button><Button>购买受权</Button><Button>申请演示</Button>PC端: 挪动端: 应用 Space 组件: <Space wrap> <Button>在线预览</Button> <Button>购买受权</Button> <Button>申请演示</Button></Space>PC端: 挪动端: Space 组件也反对 垂直方向 的排列: <Space wrap direction="vertical"> <Button>在线预览</Button> <Button>购买受权</Button> <Button>申请演示</Button></Space> 还反对各种对齐形式: ...

June 21, 2022 · 1 min · jiezi

关于vue.js:Vue3如何通过ref获取真实DOM元素

在Vue2中咱们能够在<template>中的元素标签应用ref属性(相似于原生HTML标签的id属性)在<script>标签通过this.$refs拿到实在DOM标签的元素。 获取具体到<button>体,能够通过this.$refs.btn来获取。 然而在Vue3中,咱们在setup函数中,无奈获取this,它的指向是undefined。那咱们如何获取呢? 这里咱们须要用到Vue3提出的一个新APIgetCurrentInstance,英语翻译过去就是失去以后实例,这个函数调用的返回值就是以后组件实例对象,相当于vue2中组件的this。 首先引入这个API, 而后给button打上ref属性。留神! 这里的ref不等同于返回响应式属性的那个refAPI。 随后咱们调用函数,并且打印一下变量instance 如下图所示,看到这个refs对象了吗? 而后咱们就可进行dom操作了,比方更改button的innerHTML

June 20, 2022 · 1 min · jiezi

关于vue.js:前端项目中如何保证请求时序

前端我的项目中常常遇到申请输出查找场景,防抖与截流很好解决了频繁输出问题,然而不能解决最先发动申请后果后返回,笼罩了最初一次的搜寻后果,导致搜寻后果不正确。我总结一下本人罕用的两种办法。 应用工夫戳来过滤返回后果,如果申请回调函数中的工夫戳小于以后工夫戳则返回,阐明曾经解决了之后的申请后果了,这个申请过期了。// 近程搜寻商品    searchGoods(data) {      if (!data) {        return      }      if (this.isRemote) {        const reqCount = new Date().getTime()        this.OrderInquireQuerySpuAndUnit({ keyWord: data }).then(res => {          if (this.reqCount < currentReqCount) {           return          }          if (res.data) {            if (res.data.length > 0) {              this.goodsList = res.data            }          }        }).catch(err => {          console.log(err)        }).finally(() => {          this.currentReqCount = reqCount        })      }    },基于axios封装对立的申请办法,前面发动的申请会勾销之前期待返回后果的申请,须要多传一个cancelTokenPath,示意以后同一个输出组件发动的申请export const getRequest = param => {  const { cancelTokenPath, ...restQuery } = (param && param.query) || {} // cancelTokenPath是为了防止页面中多处申请的同一个接,导致谬误的勾销  if (cancelTokenPath) {    const CancelToken = axios.CancelToken    const source = CancelToken.source()    if (store[cancelTokenPath]) {      store[cancelTokenPath].cancel('Canceled by the last request')    }    store[cancelTokenPath] = source  }  return new Promise((resolve, reject) => {    Vue.axios      .get(param.url, {        params: restQuery || {},        headers: param.headers || {},        cancelToken: cancelTokenPath && store[cancelTokenPath].token      })      .then(res => { resolve(res) })      .catch(err => {        reject(err)      })  })}

June 19, 2022 · 1 min · jiezi

关于vue.js:vue面试题

一、生命周期二、组件首次渲染时,哪些生命周期被执行beforecreate,created,beforemount,mounted,如果有keep-alive,减少activated 三、组件缓存 keep-alive同一个组件再次进入时,组件会缓存,只执行一个生命周期:activated用<keep-alive></keep-alive>包裹组件 <keep-alive> <component :is="currentComponent"></component> </keep-alive>四、v-if和v-show的区别v-if:dom节点的创立和删除,性能耗费较大v-show:display:block/none,管制显示暗藏。不占地位会造成重绘和回流,相比v-if性能耗费较小。 五、v-if和v-for的优先级:v-for的优先级更高是在源码中体现的:function getElement 六、ref是什么获取dom节点 <div ref="abd">mounted(){ console.log(this.$refs.abd); }this.$ref.childComponent.show() //调用子组件的show办法七、nextTick是什么获取更新后的dom应用场景:(1)在nextTick里调用插件,避免数据变更dom更新后,插件未更新到最新的dom (2)dom节点的数据变更后,须要获取dom内容,要用nextTick八、scoped原理款式只在本组件中失效,<style scoped>原理:给节点加了一个自定义属性,而后依据属性选择器增加款式scss的款式穿透:父元素/deep/子元素,如下: 九、 组件传值父传子:自定义属性,props接管子传父:$emit 自定义事件,通过事件参数传值,兄弟组件:(1)vue2bus.js import Vue from 'vue';export default new VueA组件 import bus from './bus.js'bus.$emit("transfer","params")B组件 import bus from './bus.js'bus.$on("transfer",(data)=>{ console.log(data)})(2)vue3装置mitt npm install --save mittmitt.js import mitt from 'mitt'export default new mitt()A组件 import mitt from '../common/bus'mitt.emit("transferValue",this.msg)B组件 import mitt from '../common/bus'mitt.on("transferValue",(data)=>{ this.msg = data })provide-inject组件间的数据穿透A组件: provide(){ return { webName: this.teacher } },B组件: inject:['webName']如果心愿provide传的数据变动,接管组件该数据跟着变动,两种形式:(1)、把根本数据类型改成援用数据类型(2)、利用computed属性 ...

June 18, 2022 · 1 min · jiezi

关于vue.js:理解Vue-SSR原理搭建项目框架

一、为什么应用SSR ?在传统vue单页面利用中,页面的渲染都是由js实现,如下图所示,在服务端返回的html文件中,body中只有一个div标签和一个script标签,页面其余的dom构造都将由bundle.js生成,而后挂载到<div id="app"></div>上。这让搜索引擎爬虫抓取工具无奈爬取页面的内容,如果 SEO 对你的站点很重要,则你可能须要服务器端渲染(SSR)解决此问题。 除了SEO,应用SSR还能放慢首屏的出现速度,因为服务端间接返回渲染好的页面html,不须要js就能看到残缺渲染的页面。比起单页利用通常比拟大的js文件,这部分代码量很小,所以首屏的达到工夫会更快,白屏的工夫更短。 当然,SSR的应用也有一些局限性,首先,开发条件受限,在服务端渲染中,created和beforeCreate之外的生命周期钩子不可用。其次,更多的服务器端负载,在服务端中渲染残缺的应用程序,显然会比仅仅提供动态文件的服务器更加占用 CPU 资源。此外,SSR在部署方面有更多要求。与能够部署在任何动态文件服务器上的齐全动态单页面应用程序(SPA)不同,服务器渲染应用程序,须要处于Node.js的运行环境。所以波及到SSR技术选型的时候,要综合思考它的优缺点,看看是否有必要应用。 二、根底性能实现SSR的实质就服务端返回渲染好的html文档。咱们先在我的项目根目录启动一个服务器,而后返回一个html文档。这里咱们应用koa作为服务端框架。 //server.jsconst Koa = require('koa')const router = require('koa-router')()const koa = new Koa()koa.use(router.routes())router.get('/',(ctx)=>{ ctx.body = `<!DOCTYPE html> //要返回给客户端的html <html lang="en"> <head><title>Vue SSR</title></head> <body> <div>This is a server render page</div> </body> </html>`})koa.listen(9000, () => { console.log('server is listening in 9000');})在命令行启动服务器: node server.js, 而后在浏览器拜访http://localhost:9000/,服务端回返回的内容如下,浏览会依据这段html,渲染出页面。 vue-server-renderer当然,要返回的html字符串能够是由vue模板生成的,这就须要用到vue-server-renderer,它会基于Vue实例生成html字符串,是Vue SSR的外围。在下面的server.js中稍作批改: const Koa = require('koa')const router = require('koa-router')()const koa = new Koa()koa.use(router.routes())const Vue = require('Vue') //导入Vue,用于创立Vue实例const renderer = require('vue-server-renderer').createRenderer() //创立一个 renderer 实例const app = new Vue({ //创立Vue实例 template: `<div>{{msg}}</div>`, data(){ return { msg: 'This is renderred by vue-server-renderer' } }})router.get('/',(ctx)=>{ //调用renderer实例的renderToString办法,将Vue实例渲染成字符串 //该办法承受两个参数,第一个是Vue实例,第二个是一个回调函数,在渲染实现后执行 renderer.renderToString(app, (err, html) => { //渲染失去的字符串作为回调函数的第二个参数传入 ctx.body = `<!DOCTYPE html> <html lang="en"> <head><title>Vue SSR</title></head> <body> ${html} //将渲染失去的字符串拼接到要返回的后果中 </body> </html>` })})koa.listen(9000, () => { console.log('server is listening in 9000');})重启服务器,再拜访: ...

June 17, 2022 · 4 min · jiezi

关于vue.js:Vuejs-监听属性

本章节,咱们将为大家介绍 Vue.js 监听属性 watch,咱们能够通过 watch 来响应数据的变动。 以下实例通过应用 watch 实现计数器: 实例<div id = "app"> <p style = "font-size:25px;">计数器: {{ counter }}</p> <button @click = "counter++" style = "font-size:25px;">点我</button></div><script type = "text/javascript">var vm = new Vue({ el: '#app', data: { counter: 1 }});vm.$watch('counter', function(nval, oval) { alert('计数器值的变动 :' + oval + ' 变为 ' + nval + '!');});</script>以下实例进行千米与米之间的换算: 实例<div id = "computed_props"> 千米 : <input type = "text" v-model = "kilometers"> 米 : <input type = "text" v-model = "meters"></div><p id="info"></p><script type = "text/javascript"> var vm = new Vue({ el: '#computed_props', data: { kilometers : 0, meters:0 }, methods: { }, computed :{ }, watch : { kilometers:function(val) { this.kilometers = val; this.meters = this.kilometers * 1000 }, meters : function (val) { this.kilometers = val/ 1000; this.meters = val; } } }); // $watch 是一个实例办法 vm.$watch('kilometers', function (newValue, oldValue) { // 这个回调将在 vm.kilometers 扭转后调用 document.getElementById ("info").innerHTML = "批改前值为: " + oldValue + ",批改后值为: " + newValue;})</script>

June 17, 2022 · 1 min · jiezi

关于vue.js:Vue组件中如何引入外部的js文件

在Vue中,通常咱们引入一个js插件都是应用npm 形式下载而后import应用的。然而我当初本地有了js文件或者是一个近程js文件链接,我不想应用npm install xxx 的形式,有什么方法吗? 办法1简略粗犷,间接在Vue我的项目的index.html 中应用全局的形式引入,比方: <!DOCTYPE html><html><head> <!-- ... 省略--></head><body> <div id="app"></div></body><script src="../xxx.js"></script> // 暴力引入</html>毛病:不应用该js插件的组件也会加载,而我只想在某个Vue组件中应用该js插件。 办法2如果是下载到本地的动态文件,能够应用import 的形式导入。 import { xxx } from '门路' 毛病:下载的动态文件才能够 办法3在Vue组件加载完后,手动操作DOM插入js插件。 export default { mounted() { let script = document.createElement('script'); script.type = 'text/javascript'; script.src = '你的js文件地址'; document.body.appendChild(script); },}该形式间接操作DOM,只在以后组件插入js插件。 办法4应用render办法 export default { components: { 'xxx-js': { render(createElement) { return createElement( 'script', { attrs: { type: 'text/javascript', src: '你的js文件地址', }, }, ); }, }, },}// 应用 <xxx-js></xxx-js> 组件形式在页面中调用办法5高阶玩法。将形式三包装成一个js插件,应用 Promise,js加载胜利,调用resolve,js加载失败,调用reject。 ...

June 17, 2022 · 1 min · jiezi

关于vue.js:组件库Mint-UI上拉加载更多插件Loadmore的使用tips

引入import { Loadmore } from "mint-ui";html <top-loadmore :distanceIndex="2" :bottom-method="addMoreData" :auto-fill="false" ref="loadmore" :bottomPullText="bottomPullText"> <div class="list-item" v-for="(item,index) in listArr" :key="index" @click="toRecordDetail(item.user_exchange_id)"> 列表内容 </div></top-loadmore>js import { Loadmore } from "mint-ui";export default { components: { "top-loadmore": Loadmore, }, data(){ return{ page_num:1, bottomPullText:"上拉加载更多", } }, methods:{ loadList(){ if(_this.page_num!=1){ _this.$refs.loadmore.onBottomLoaded();//这里数据回调胜利之后要从新获取mt-loadmore外部的高度,避免上拉后不复位,首次申请或查问第一页不执行,避免头部scroll遮挡问题 } }, addMoreData(){ if(this.flag) return false if (this.totalPageNum > this.page_num) { this.page_num++ this.loadList() } this.$refs.loadmore.onBottomLoaded();//这里数据回调胜利之后要从新获取mt-loadmore外部的高度,避免上拉后不复位。如果是下拉刷新页面,则须要执行: this.$refs.loadmore.onTopLoaded(); }, },}上拉过程中容易触发列表点击事件修复需批改两个文件:\node_modules\mint-ui\lib\mint-ui.common.js\node_modules\mint-ui\lib\loadmore\index.js批改内容: handleTouchEnd: function handleTouchEnd(event) { if (this.direction === 'down' && this.getScrollTop(this.scrollEventTarget) === 0 && this.translate > 0) { event.preventDefault();//此处为阻止滑动时点击click,自定义增加 event.stopPropagation();//此处为阻止滑动时点击click,自定义增加 this.topDropped = true; if (this.topStatus === 'drop') { this.translate = '50'; this.topStatus = 'loading'; this.topMethod(); } else { this.translate = '0'; this.topStatus = 'pull'; } } if (this.direction === 'up' && this.bottomReached && this.translate < 0) { event.preventDefault();//此处为阻止滑动时点击click,自定义增加 event.stopPropagation();//此处为阻止滑动时点击click,自定义增加 this.bottomDropped = true; this.bottomReached = false; if (this.bottomStatus === 'drop') { this.translate = '-50'; this.bottomStatus = 'loading'; this.bottomMethod(); } else { this.translate = '0'; this.bottomStatus = 'pull'; } } this.$emit('translate-change', this.translate); this.direction = '';} ...

June 16, 2022 · 1 min · jiezi

关于vue.js:封装vue20组件基于elementui并发布npm包

1、初始我的项目 mkdir vue-test & cd vue-test2、安装包 npm init一路回车,创立package.json,外面的name能够视状况本人更改 3、思考通过webpack按需安装包(因为vue-cli装置了很多额定的包) npm i webpack webpack-cli webpack-dev-server html-webpack-plugin -D4、调整目录构造,新建assets、example、packages、src、webpack assets寄存动态资源,如images、less、scss、font等example寄存示例packages寄存行将开发的vue组件src寄存启动我的项目的入口js等webpack寄存不同配置 5、思考webpack配置(1)vue我的项目,必然须要装置vue、vue-loader、vue-template-compiler,具体参考https://vue-loader.vuejs.org/(这里有一个留神点:须要装置vue@2和vue-loader@15,更高版本的话,就须要做vue3的解决了,目前尚未摸索vue3的相干配置)(2)vue组件中蕴含了less、scss等,必然须要装置vue-style-loader、css-loader、less、less-loader、sass、sass-loader、node-sass(3)我的项目中有js文件,须要反对es6语法,必然须要装置babel-loader 6、在/webpack目录下,新建develop.js const webpack = require('webpack')const path = require('path')const resolve = path.resolveconst HtmlWebpackPlugin = require('html-webpack-plugin')const { VueLoaderPlugin } = require('vue-loader')module.exports = { mode: 'development', mode: 'none', entry: resolve(__dirname, '../src/index'), output: { clean: true }, module: { rules: [ { test: /\.vue$/i, loader: 'vue-loader' }, { test: /\.js$/, loader: 'babel-loader' }, { test: /\.s[ac]ss$/, use: ['vue-style-loader', 'css-loader', 'sass-loader'] }, { test: /\.less$/, use: ['vue-style-loader', 'css-loader', 'less-loader'] }, { test: /\.css$/, use: ['vue-style-loader', 'css-loader'] }, { test: /\.(png|svg|jpg|jpeg|gif)$/i, type: 'asset/resource' } ] }, devtool: 'inline-source-map', devServer: { static: './dist' }, resolve: { alias: { '@': process.cwd() } }, plugins: [ new VueLoaderPlugin(), new HtmlWebpackPlugin({ template: resolve(__dirname, '../src/index.html') }) ]}具体配置,能够参考webpack官网,https://webpack.docschina.org... ...

June 16, 2022 · 2 min · jiezi

关于vue.js:vue-使用此方法初始化数据数据-Objectassignthisdatathisoptionsdata

应用此办法初始化数据数据 Object.assign(this.$data,this.$options.data());

June 16, 2022 · 1 min · jiezi

关于vue.js:Vuejs设计与实现学习总结第四章1

响应式数据与副作用函数副作用函数就是会产生副作用的函数, 例如: function effect () { document.body.innerText = 'hello vue3'}当函数effect运行后, 会设置body的文本使其扭转, 而其余函数也能够扭转与获取body中的文本, 也就是说effect函数的执行间接或间接影响了其余其余函数的执行后果, 这是effect的副作用. 副作用函数有很多也十分常见比方扭转某一个全局变量的值. 响应式的根本思维const obj = { text: 'hello world' }function effect () { document.body.innerText = obj.text}obj.text = 'hello no world'如上代码, 副作用函数effect执行时会触发obj.text的读取[[GET]]操作, 而对obj.text赋值时会触发设置[[SET]]操作, 因而读取操作时, 能够把副作用函数effect存储到某一数据结构中, 当设置时能够把副作用函数effect取出在运行, 这就实现了最根本的响应式如下图: 对于监听读取与设置操作, 能够应用代理对象Prosy实现: // 存储副作用函数 const bucket = new Set() // 原始数据 const data = { text: 'hello world' } // 解决原函数数据 const obj = new Proxy(data, { // 拦挡读取操作 get (target, key) { // 存储副作用函数effect bucket.add(effect) // 返回属性值 return target[key] }, // 拦挡设置操作 set (target, key, newVal) { console.log(newVal); // 设置属性值 target[key] = newVal // 把副作用函数取出并执行 bucket.forEach(fn => fn()) // 返回 true 代表操作胜利 return true } })目前尽管能够实现, 然而还有许多缺点, 比方这里间接通过名字获取副作用函数, 这种硬编码的形式不灵便, 并且没有在副作用函数与被操作的指标对象的属性没有建设明确的关系, 此时若读取obj中的属性, 都会把副作用函数存储, 若设置某一个属性都会把副作用函数取出并执行, 因而能够应用某一全局变量贮存副作用属性: ...

June 15, 2022 · 2 min · jiezi

关于vue.js:混合开发入门-Vue结合AndroidiOS开发仿京东项目App

混合开发入门 Vue联合Android/iOS开发仿京东我的项目App百度网盘链接Java 基础常见学识点&面试题总结面向对象基础面向对象和面向过程的区别两者的次要区别在于解决问题的形式不同: 面向过程把解决问题的过程拆成一个个方法,通过一个个方法的执行解决问题。面向对象会先抽象出对象,而后用对象执行方法的形式解决问题。 另外,面向对象开发的程序一般更易保护、易复用、易扩大。相干 issue : 面向过程 :面向过程性能比面向对象高??成员变量与局部变量的区别 语法形式 :从语法形式上看,成员变量是属于类的,而局部变量是在代码块或方法中定义的变量或是方法的参数;成员变量可能被 public,private,static 等修饰符所润饰,而局部变量不能被访问控制修饰符及 static 所润饰;然而,成员变量和局部变量都能被 final 所润饰。存储形式 :从变量在内存中的存储形式来看,如果成员变量是使用 static 润饰的,那么这个成员变量是属于类的,如果没有使用 static 润饰,这个成员变量是属于实例的。而对象存在于堆内存,局部变量则存在于栈内存。生存工夫 :从变量在内存中的生存工夫上看,成员变量是对象的一部分,它随着对象的创建而存在,而局部变量随着方法的调用而主动生成,随着方法的调用结束而沦亡。默认值 :从变量是否有默认值来看,成员变量如果没有被赋初始值,则会主动以类型的默认值而赋值(一种情况例外:被 final 润饰的成员变量也必须显式地赋值),而局部变量则不会主动赋值。 创建一个对象用什么运算符?对象实体与对象引用有何不同?new 运算符,new 创建对象实例(对象实例在堆内存中),对象引用指向对象实例(对象引用存放在栈内存中)。一个对象引用可能指向 0 个或 1 个对象(一根绳子可能不系气球,也可能系一个气球);一个对象可能有 n 个引用指向它(可能用 n 条绳子系住一个气球)。对象的相等和引用相等的区别 对象的相等一般比较的是内存中存放的内容是否相等。引用相等一般比较的是他们指向的内存地址是否相等。 类的构造方法的作用是什么?构造方法是一种非凡的方法,次要作用是实现对象的初始化工作。如果一个类没有申明构造方法,该程序能正确执行吗?如果一个类没有申明构造方法,也可能执行!因为一个类即使没有申明构造方法也会有默认的不带参数的构造方法。如果咱们自己增加了类的构造方法(无论是否有参),Java 就不会再增加默认的无参数的构造方法了,咱们一直在人不知;鬼不觉地使用构造方法,这也是为什么咱们在创建对象的时候前面要加一个括号(因为要调用无参的构造方法)。如果咱们重载了有参的构造方法,记得都要把无参的构造方法也写进去(无论是否用到),因为这可能帮助咱们在创建对象的时候少踩坑。构造方法有哪些个性?是否可被 override?构造方法个性如下: 名字与类名雷同。没有返回值,但不能用 void 申明结构函数。生成类的对象时主动执行,无需调用。 构造方法不能被 override(重写),然而可能 overload(重载),所以你可能看到一个类中有多个结构函数的情况。面向对象三大特色封装封装是指把一个对象的状态信息(也就是属性)躲藏在对象外部,不容许内部对象间接拜访对象的外部信息。然而可能提供一些可能被外界拜访的方法来操作属性。就好像咱们看不到挂在墙上的空调的外部的整机信息(也就是属性),然而可能通过遥控器(方法)来管制空调。如果属性不想被外界拜访,咱们大可不必提供方法给外界拜访。然而如果一个类没有提供应外界拜访的方法,那么这个类也没有什么意义了。就好像如果没有空调遥控器,那么咱们就无奈操控空凋制冷,空调本身就没有意义了(当然现在还有很多其余方法 ,这里只是为了举例子)。public class Student { private int id;//id属性私有化private String name;//name属性私有化//获取id的方法public int getId() { return id;}//设置id的方法public void setId(int id) { this.id = id;}//获取name的方法public String getName() { return name;}//设置name的方法public void setName(String name) { this.name = name;}}复制代码继承不同类型的对象,相互之间常常有肯定数量的共同点。例如,小明同学、小红同学、小李同学,都共享学生的个性(班级、学号等)。同时,每一个对象还定义了额定的个性使得他们不同凡响。例如小明的数学比较好,小红的性情惹人喜爱;小李的力量比较大。继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可能减少新的数据或新的功能,也可能用父类的功能,但不能选择性地继承父类。通过使用继承,可能疾速地创建新的类,可能提高代码的重用,程序的可维护性,俭约大量创建新类的工夫 ,提高咱们的开发效率。对于继承如下 3 点请记住: ...

June 15, 2022 · 2 min · jiezi

关于vue.js:svg类型本地图片展示

一、背景在elementUI+vue3,展现svg本地图片,可用于菜单前,表格内二、步骤1、src/components/SvgIcon目录下创立index.vue,代码如下: <template> <svg :class="svgClass" aria-hidden="true" > <use :xlink:href="iconName" /> </svg></template><script>/* icon组件实现主动引入 ../../Icons/svg 上面所有的图标了*之后咱们就要应用到 webpack 的 require.context。很多人对于 require.context可能比拟生疏,直白的解释就是require.context("./test", false, /.test.js$/); 这行代码就会去 test 文件夹(不蕴含子目录)上面的找所有文件名以 .test.js 结尾的文件能被 require 的文件。 更直白的说就是 咱们能够通过正则匹配引入相应的文件模块*/const requireAll = requireContext => requireContext.keys().map(requireContext)const req = require.context('../../assets/svg', false, /\.svg$/)//svg图片地位requireAll(req)export default { name: 'SvgIcon', props: { iconClass: { type: String, required: true }, className: { type: String, default: '' } }, computed: { iconName () { return `#icon-${this.iconClass}` }, svgClass () { if (this.className) { return 'svg-icon ' + this.className } else { return 'svg-icon' } } }}</script><style scoped>.svg-icon { width: 1em; height: 1em; vertical-align: -0.15em; fill: currentColor; overflow: hidden;}</style>2、在src/main.js里注册全局组件 ...

June 15, 2022 · 1 min · jiezi

关于vue.js:vue-antd-UI-table表格展开行展开多行共存

背景:我的项目中须要table开展的操作;查看其余文章说只能保留一个开展的内容;实测是能够多个的要的成果业务中须要开展行的操作;依照antd官网的写法;并没有实现本人的成果;查github材料后失去了想要的后果;间接上代码吧 html构造代码# advance-table 是本人2次封装的table组件;理论中间接用a-table就行了<advance-table class="m-t-10" bordered :scroll="{ x:'100%',y: tableY }" :columns="columns_customer_complaint" :data-source="tableData" :loading="loading" :rowKey="(row,index) => row.recordId" :pagination="pagination" @change="handleTableChange" @expand="expandedRowRender" # 这个办法是开展行的回调办法 :expandedRowKeys.sync="expandedRowKeys" # 这个属性很重要;就是用它来管制某行是否开展和收起;分页再次获取数据的时候;也要把它给置空数组;外面的每项对应rowKey返回的recordId > <advance-table slot="expandedRowRender" slot-scope="{text, record}" style="width: 30%;padding: 10px 0;" :columns="columns_customer_complaint_inner" :data-source="record.innerData" # 这个数据起源;做法是往每一项外面都减少一个innerData来用作开展行外面的数据 :pagination="false" :showToolbar="false" > <template slot="dealwithProgress" slot-scope="{text, record}"> {{record.dealwithProgress === 1 ? '进行中' : record.dealwithProgress === 5 ? '已实现' : record.dealwithProgress === 0 ? '待处理' : ''}} </template> </advance-table> </advance-table>JS代码data(){ return { # ...其余代码 tableData: [], expandedRowKeys: [], }},methods: { // 开展行的回调办法 async expandedRowRender(expanded, record) { const { recordId, rowKey } = record const { data } = await Api.CustomerServiceRecordLogList({ recordId }) // 获取数据后放到外层tableData外面的innerData属性身上 this.$set(this.tableData[rowKey], 'innerData', data) // 操作以后行是否开展;通过外面有无`recordId`进行逻辑操作 if (this.expandedRowKeys.includes(recordId)) { this.expandedRowKeys.splice(this.expandedRowKeys.findIndex(f => f === recordId), 1) } else { this.expandedRowKeys.push(recordId) } }, async getData(){ // 其余代码 // 从新获取tableData数据后;将开展行id数组置空 this.expandedRowKeys = [] }}实现成果 ...

June 14, 2022 · 1 min · jiezi

关于vue.js:vue3-tsx-pinia-jest开发模板整理

 公司我的项目应用react,然而作为vue2的一名coder,周末花了两天的工夫,整顿了一波vue3 + tsx + vite + axios 的开发模板,外面涵盖jest、tailwindcss、pinia、element-plus等一些日常工具包,以及退出了eslint、prettier保障日常开发代码品质工具,基本上可能保障大家可能开箱即用,上面附上模板代码地址,对于代码目录构造能够参考代码仓库的阐明文档,喜爱的敌人能够转评赞给一个,点个珍藏不失落,上面呢我介绍一下根本构建思路; 1、对于我的项目中应用tsx 要想我的项目中运行tsx,咱们就得思考到tsx语法糖编译的问题,这里就得用到@vitejs/plugin-vue-jsx插件,具体用法参考github文档,装置后,在vite的plugin中间接调用即可; import { defineConfig } from 'vite'import vue from '@vitejs/plugin-vue'import vueJsx from '@vitejs/plugin-vue-jsx'// https://vitejs.dev/config/export default defineConfig({ plugins: [vue(), vueJsx()]}) 2、装置tailwindcss 对于tailwindcss + vite计划,它的官网有了很敌对的计划,这块大家循序渐进的装置就够了,没有多少复杂度,参考地址,抉择tailwindcss次要是它提供了一些疾速款式,比方padding、margin、background等,如果咱们我的项目是后盾管理系统,tailwindcss会大大降低咱们写css款式的工作,大家能够去学习一波在我的项目中用起来,相熟了当前就感觉他是在是太不便了。 这里不做用法的介绍,就举荐一个vscode插件Tailwind CSS IntelliSense,装置后,在我的项目中咱们就能够只能提醒,如下所示: 3、对于eslint + prettier 代码对立标准 对于代码标准,个别小一点公司不太会做这方面的工程化配置,然而eslint等这些代码标准工具,会让咱们团队的代码更标准,格调更对立,团队合作更加不便,我简略说一下配置eslint及prettier的方法 (1)首先装置eslint工具库pnpm add eslint -D pnpm eslint --init (2)装置内部的语法eslint标准及import校验标准 抉择对应的我的项目内容,这里我的我的项目用到(vue, typescript,browser)这个,当然有这个还不够,咱们须要装置如下两个工具包 pnpm add eslint-plugin-import // 次要对于es与typescript import 门路的一个eslint校验 pnpm add eslint-config-airbnb-base // 这个是airbnb出的一套eslint语法标准的工具库,如果本人公司没有对应的代码标准,这个是很实用的一套 (3)编写vue3相干的标准 我的项目中咱们用到的是eslint-plugin-vue这个vue代码校验标准工具,外面有很多内容及配置项性能,咱们这里举荐大家在配置代码标准,能够参考官网的阐明文档,链接放在这里; ...

June 14, 2022 · 4 min · jiezi

关于vue.js:vue3

环境配置装置yarn npm install -g yarn配置vuevue3官网文档地址: https://v3.cn.vuejs.org/guide/installation.html一、装置vue3.X调试工具vue-devtools-6.0.0博客地址: https://blog.csdn.net/qq_48731430/article/details/123313928二、创立我的项目1、装置脚手架npm install -g @vue/cli2、创立我的项目(第1种) vue create project1第二种形式yarn create vite project 3、装置sass,用来解决scss文件yarn add -D sass遇到问题:can not resolve sass-loader解决办法:cnpm install sass-loader -Dcnpm install node-sass -D 4、vscode配置vue代码模板1、唤出vscode控制台, 输出win: Ctrl + Shift + Pmac: command + Shift + P2、输出snippets3、选中vue.json4、配置内容 { "vue-template":{ "prefix": "vue", "body": [ "<template>", "<div>", " ", "</div>", "</template>", "<script>", " export default {", " data(){", " return {", "" " }", " }", " }", "</script>", "<style lang=\"scss\" scoped>", "</style>" ] } }

June 13, 2022 · 1 min · jiezi

关于vue.js:View-UI-Plus-发布-120-版本新增-ImageSkeletonTypography-组件

View UI Plus 1.2.0 版本已于 2022-06-13 公布。 更新日志请到官网 www.iviewui.com 查看最新版。新增排版组件 Typography,内置丰盛的内容排版 UI,反对拷贝、可编辑、省略等性能。Typography 共蕴含 5 个组件: Typography 内容构造Title 题目Paragraph 段落Text 行内文本Link 链接新增骨架屏组件 Skeleton。新增图片组件 Image。蕴含两个组件: Image 图片ImagePreview 图片预览修复局部 CSS 在局部环境下出错的问题。修复 Row 组件 types 谬误的问题。修复 Alert 组件图标不居中的问题。更新办法1.批改 package.json 中 view-ui-plus 版本号: "dependencies": { "view-ui-plus": "^1.2.0" }2.运行 npm update view-ui-plus。 内容简介Image 图片组件图片组件能够不便地对一张图进行各种排版,应用 fit 属性设置图片各种缩放成果,width 和 height 能够设置图片的宽高,src 指定图片地址,比方: <Image src="https://file.iviewui.com/images/image-demo-11.jpg" fit="contain" width="100px" height="100px"/>设置属性 lazy 能够对图片进行懒加载,默认会主动寻找最近一个 overflow 值为 auto 或 scroll 的父元素。当滚动到图片可见区域时,才会加载该图片。当然,也能够设置属性 scroll-container 来指定容器。能够到这里在线体验图片懒加载:https://run.iviewui.com/HoVFMqS7 除此之外,图片组件还能够自定义加载中提醒、加载失败提醒等罕用属性。具体能够查看 文档 API ...

June 13, 2022 · 1 min · jiezi

关于vue.js:巧妙使用Vueextend继承组件实现eltable双击可编辑不使用vif和velse

问题形容有一个简略的表格,产品要求实现双击可编辑 看了一下网上的帖子,大多数都是搞两局部dom,一块是输入框,用于编辑状态填写;另一块是一般标签,用于在不编辑显示状态下出现单元格文字内容。再加上一个flag标识搭配v-if和v-else去管制编辑状态、还是显示状态。大抵代码如下: <el-table-column align="center" label="姓名" > <template slot-scope="scope"> <!--isClick就是标识状态,状态处于编辑时候,显示输入框,状态属于出现状态就显示文本内容--> <el-input v-if="scope.row.isClick" v-model="scope.row.name" @blur="blurFn(scope.row)"></el-input> <span @click="clickCell(scope.row)" v-else>{{scope.row.name}}</span> </template> </el-table-column>这种形式有其实用场景,然而得每个el-table-column列中都加上el-input和span以及v-if和v-else。咱们尝试一下动静增加el-input,就是点击那个单元格,给那个单元格增加el-input让其处于可编辑状态,而后适时移除即可。这样的话,很多列的时候,就不必加很多个v-if和v-else啦。咱们先看一下效果图 效果图 代码思路第1步:给el-table绑定双击事件 @cell-dblclick='dblclick',再双击事件的回调函数中,能够得悉点击的是哪一行、那一列、那个单元格dom,以及点击事件。dblclick(row, column, cell, event) {...},这个是饿了么官网提供的,没啥好说的第2步:重点来喽 第2.1步:单元格双击事件当前,咱们首先创立一个el-input标签,而后把点击的这个单元格的值,作为参数props让这个el-input接管,这样的话el-input就会显示这个单元格的值了,就能够编辑了。问题一:如何创立一个el-input标签? ,客官稍等,下方会解答第2.2步:把创立好的el-input标签替换掉原来的单元格span标签,这样的话,就能够看到单元格变成了可输出的输入框了。问题二:如何把新创建的el-input标签,替换原有的span标签 ,客官稍等,下方会解答第2.3步,当用户编辑完了点击别处时候,即输入框失去焦点的时候,再把el-input输入框标签移除掉,复原默认的span标签(当然失去焦点的时候,就要发申请批改数据了)问题三:如何移除el-input标签,并复原原有的span标签,客官稍等,下方会解答这样的话,每次双击搞一个input标签用于批改,每次改完了失去焦点,就复原默认单元格展现状态了,性能就实现了代码思路中的三个问题解答问题一:如何创立一个el-input标签?咱们晓得,如果是创立原生的input标签并指定一个值,比较简单,间接: let input = document.createElement('input') // 创立一个input标签input.value = '孙悟空' // 给input标签赋值document.body.appendChild(input) // 把input标签追加到文档body中不过el-input标签不能通过上述形式创立,因为document.createElement()办法尽管能够创立进去el-input标签,然而dom并不意识这个el-input标签,所以页面没有变动。毕竟饿了么的el-input也是把input标签做一个二次封装的 所以,这里咱们能够应用Vue.extend()办法去继承一个组件并裸露进来,而继承的这个组件中又有一个input标签,所以那个须要应用,那里就能够引入并new进去一个el-input了。对于Vue.extend()的定义啥的,这里不赘述,详情看官网文档。笔者之前也写过一篇Vue.extend文章,传送门:https://segmentfault.com/a/11... 首先搞一个.vue文件,用于继承// input.vue文件<template> <div class="cell"> <el-input ref="elInputRef" size="mini" v-model.trim="cellValue" ></el-input> </div></template>props: { cellValue: { type: String | Number, default: "", },}而后定义一个data.js文件,继承input.vue文件,并裸露// data.jsimport Vue from "vue";import definedInput from "./input.vue";// vue继承这个input组件,就相当于一个构造函数了const inputC = Vue.extend(definedInput);// 裸露进来,哪里须要哪里引入export default { inputC,}页面中引入并应用// page.vueimport extendComponents from "./threeC/data"; // 1. 引入new extendComponents.inputC({ // 2. 实例化 propsData: { // 应用propsData对象传递参数,子组件在props中能够接管到 cellValue: cellValue, // 传递单元格的值 }, }).$mount(cell.children[0]);// 3. 挂载propsData对象用于给继承的组件传递参数,也能够传递一个函数,从而继承组件通过这个函数告诉内部应用组件,详情见后续残缺代码问题二三:el-input标签和span标签的来回替换复原应用$mount办法去做来回替换,$mount能够把一个子dom元素追加到父dom元素外部,相当于appendChild ...

June 13, 2022 · 3 min · jiezi

关于vue.js:在一段很长的文字中间用省略显示

应用场景:当table表格数据遇到一串很长很长很长很长很长长长长长长长长长的字符串的时候,要渲染在页面上会把单元格撑大影响表格的好看。批改前效果图:批改后效果图: 办法:应用slice()办法进行截取 <div class="chart_form"> <el-table :data="records" style="width: 100%" @cell-click="txidUrl"> <el-table-column prop="burnTime" label="工夫" width="180"></el-table-column> <el-table-column prop="txid" :formatter="(row,column,cellValue,index) => {return ellipseText(cellValue);}" label="单元格头2" width="180"> </el-table-column> <el-table-column prop="amount" :formatter="(row,column,cellValue,index) => {return convertNum(cellValue);}" label="数量"></el-table-column> <el-table-column prop="amount" :formatter=" (row,column, cellValue,index) => {return convertText(cellValue);}" label="单元格头4"></el-table-column> </el-table> <div class="tabListPage" :xs="24"> <el-pagination @current-change="handleCurrentChange" :current-page.sync="currentPage" :page-size="pageSize" layout="total, prev, pager, next" :total="total"> </el-pagination> </div></div><script>import { api } from "../api/api";export default { data() { return { records: [], textId: "", pageSize: 9, total: 0, currentPage: 1, } }, created() { this.getDestruction(); }, async mounted() { async getDestruction() { let that = this; let res = await api.getDestructionRecords({ pageNum: that.currentPage, pageSize: that.pageSize }); // console.log('Destruction',res) if (res.data.code == 1) { // console.log('Destruction',res) that.records = res.data.data.records; //总数 that.total = res.data.data.total * 1; } else { that.$layer.msg(res.data.msg); } }, //交易ID单元格点击跳转 txidUrl(row, column, cell, event){ console.log('row',row) console.log('column',column) console.log('cell',cell) console.log('event',event) if (column.label == "交易ID") { console.log(row.txExplorer) //跳转链接 window.location.href= row.txExplorer; } }, //分页:页面切换办法 handleCurrentChange(val) { this.currentPage = val; this.getDestruction(); // console.log(`当前页: ${val}`); }, ellipseText(val) { // console.log(val) if (!val) return ""; //截取前六位、后四位,在进行拼接 return val.slice(0, 6) + "******" + val.slice(-4); }, convertNum(val) { if (!val) return ""; return val.substring(0, val.indexOf(".") + 3); }, convertText(val) { if (!val) return ""; return "US$" + (val * this.price).toFixed(2); } }}</script>

June 13, 2022 · 1 min · jiezi

关于vue.js:如何在-Vue-项目中通过点击-DOM-自动定位VSCode中的代码行

作者:vivo 互联网大前端团队- Youchen一、背景当初大型的 Vue我的项目基本上都是多人合作开发,并且随着版本的迭代,Vue 我的项目中的组件数也会越来越多,如果此时让你负责不相熟的页面性能开发,甚至你才刚刚退出这个我的项目,那么怎么样能力疾速找到相干组件在整个我的项目代码中的文件地位呢?想必大家都有采取过以下这几种办法: 【搜类名】,在工程文件里搜寻页面 DOM元素中的款式类名【找路由】,依据页面链接找到Vue路由匹配的页面组件【找人】,找到当初负责开发该页面的人询问对应的代码门路以上几种办法的确可能帮忙咱们找到具体的代码文件门路,但都须要人工去搜寻,并不是很高效,那有没有其它更高效的形式呢? 答案是有的。Vue官网就提供了一款 vue-devtools  插件,应用该插件就能主动在 VSCode 中关上对应页面组件的源代码文件,操作门路如下: 应用vue-devtools插件能够很好地进步咱们查找对应页面组件代码的效率,但只能定位到对应的组件代码,如果咱们想要间接找到页面上某个元素相干的具体代码地位,还须要在以后组件源代码中进行二次查找,并且每次都要先抉择组件,再点击关上按钮能力关上代码文件,不是特地快捷。 针对这个问题,咱们开发了轻量级的页面元素代码映射插件,应用该插件能够通过点击页面元素的形式,一键关上对应代码源文件,并且精准定位对应代码行,无需手动查找,可能极大地提高开发效率和体验,理论的应用成果如下: 二、实现原理整个插件次要分为3个功能模块:client、server、add-code-location,client端发送特定申请给server端,server端接管到该申请后执行定位代码行命令,而add-code-location模块用于源码的转换。 2.1 clientclient端这里其实就是指浏览器,咱们在点击页面元素时,浏览器就会发送一个特定申请给server端,该申请信息蕴含了具体的代码文件门路和对应代码行号信息。 function openEditor(filePath) { axios .get(`${protocol}//${host}:${port}/code`, { params: { filePath: `${filePath}` } }) .catch(error => { console.log(error) })}而监听页面元素的点击事件则通过事件代理的形式全局监听,给document绑定了点击事件,监听键盘和鼠标点击组合事件来发动定位代码行申请,防止和页面原生的click事件发生冲突。 function openCode(e) { if (isShiftKey || isMetaKey || e.metaKey || e.shiftKey) { e.preventDefault() const filePath = getFilePath(e.target) openEditor(filePath) } ...}2.2 serverserver端是指本地起的一个服务器,能够监听client端发送的特定申请,当接管到执行定位命令的申请时,执行VSCode关上代码文件命令,并定位到对应的代码行。 2.2.1 webpack devServer如果是采纳webpack构建的我的项目,webpack的devServer开发服务器曾经提供了一个before属性,能够通过它来监听发送给开发服务器的申请。 before: function (app) { app.get('/code', function (req, res) { if (req.query.filePath) { // 执行vscode定位代码行命令 openCodeFile(req.query.filePath) ... } ... })}2.2.2 vite configureServer如果是采纳Vite构建的我的项目,能够应用Vite插件来实现server端监听特定申请,Vite插件扩大于rollup插件接口,并且在原有的根底上减少了一些特有的钩子函数,例如configureServer钩子,通过该钩子函数能够用于配置开发服务器来监听特定的申请。 ...

June 13, 2022 · 2 min · jiezi

关于vue.js:在vue的模版中和react的一些小区别

明天在学习vue的过程中,遇到了一个小问题,在vue的模版<template>标签中无奈间接调用windows对象身上的办法,而react中能够,感觉这个问题还挺容易遇到的,来记录一下。 首先React先看上面的简略的代码, 实现的页面如下: 点击按钮能够在控制台看到 接下来是Vue 代码如下,首先就会看到 @click事件绑定就呈现了报错。 页面如下 当咱们点击按钮的时候,控制台会提醒,找不到log这个属性或者办法。 间接说论断,在vue的template里都是应用了vue实例中或者Vue构造函数身上的属性和办法,当你在template里调用console.log办法时候,它会去vm(假如vm=new Vue())这个实例对象身上找console.log这个办法,后果没有,那么就回去vm__proto__原型对象身上找,那必定也没有。 如果要用怎么办呢? 能够在<script>标签中拿到window对象,而后本人应用。 至于为什么,目前对我来说还得持续学习Vue才能够下定论。

June 12, 2022 · 1 min · jiezi

关于vue.js:用Vue30写出一个简单的TodoList案例

因为工作须要,当前可能会敲vue代码了,所以明天开始会零散的记录一下本人学Vue3.0的一些案例。就从经典的TodoList案例开始吧~也算补上之前react的todolist案例的坑吧 简略的在草稿纸上写出页面的整体设计思路为3层div包裹,心愿刚开始学习的时候,肯定要本人去理论入手去画出大略的效果图。再简略不过的页面设计了。 一.在vue的template标签中编写html文件 依据下面的草图来写出简略的构造,非常简单的代码。三个<div>来实现草稿的大略实现。 设计动态页面为下图所示。 二.最首先的性能就是,如何获取用户输入框的值 在vue里是用v-model这样的绑定形式来双向绑定一个变量的,我这里用的是vue3中<script>标签的setup语法糖编写的代码,书写格调和react十分类似,也是我比拟喜爱的写法。 这里咱们须要用到vue里的的ref办法,先引入在说吧。 看一下Vue官网对ref的解释 在我看来,这个和react的useRef返回一个带有current属性的对象很相似。 通过理解,在vue中,定义一个根本类型,要用ref,定义一个援用类型要用reactive,实质上应用ref(hhh)其实就是调用了reactive({value:"hhh"})。 (补充阐明一下:vue在<template>标签中能够主动获取ref变量对象的value,然而在<script>标签中应用时,要带上.value才能够。) 回到正题 理解了ref的应用,咱们就先定义一个变量叫做newTodo来绑定input框来获取用户的输出。 此时newTodo.value就和input框的value绑定了。 三.设计增加button性能的实现 在这个按钮之前,咱们要设定一个空的数组,来接管用户的输出数据,并且在外面再增加一些默认的数据来显示。 接下来先渲染出咱们默认的数据。在template标签中写 这里我在<ul>标签里加了v-if判断语句,判断这个doLists数组是否为空数组,如果为空,则不渲染。<li>标签就是简略的v-for遍历。 别忘了绑定一个key 按钮的逻辑其实很简略,就是往这个todoLists数组外面增加数据,而后将用户输出的值清空。 (再揭示一下,在<script>标签里通过ref返回对象须要本人去调用value属性才能够应用) 试一下成果 能够失常增加并且显示。 四.设置一下增加按钮的逻辑判断 当初有一个状况就是我点击增加的时候,如果用户输出的值是空值,仍旧能增加,当初设计不容许这种状况产生。实现的形式有很多,我集体想设计为:当用户输出值为空,按钮禁止应用。 刚开始十分不习惯,因为在react里写js代码很明确须要在{}里写,然而vue全是引号里编写,在这里先暂且这样了解吧,当你应用v-指令语法时候,是个属性的=前面的""里就是要写js代码了。 所以这里咱们不能写原生的disabled属性,这样vue会把前面的三元表达式认为是字符串。 成果如下: 五.实现item的删除性能 咱们心愿在每个item的前面呈现一个删除按钮,当咱们不喜爱这个事件的时候,能够间接删除。 页面成果如下 这时候开始思考删除按钮的逻辑。我这里有两种设计思路;1.用filter去筛选出不等于以后index索引值的数组从新渲染2.用slice去组合以后item之前和之后的数据从新渲染。 办法一. 咱们须要拿到以后我的项目的index值,很简略,去拿v-for指令的第二个参数,同时将该值传入给咱们的del函数 (如果之前你理解过react,那么这里你肯定会有纳闷,因为react这种场景是须要应用高阶函数返回这个del函数的,不然就会造成组件刚挂载就执行的成果,然而vue不会,然而其实vue背地帮你写成了这样的代码) 我也更习惯这样的写法。 接下来就是办法的逻辑了。因为我点击的时候,拿到的index是以后我要在todoLists里删除的那个选项索引,那么咱们反向思考,我把那些索引不等于这个值的那些item从新渲染不就好了吗? 这样就能够实现咱们要的成果了 点击睡觉前面的按钮实现需要。 办法二. 其实思路是一样的,都是反应思考,避开咱们拿到的这个index。 slice这个办法我之前的文章中细讲了很多了,不再过多赘述了,成果也是能够失常实现的。 办法三 这个办法是我长期想到的,试一试能够不,用splice去解决。 ...

June 10, 2022 · 1 min · jiezi

关于vue.js:element表单精确点击单个表格跳转事件

@cell-click点击事件 <el-table :data="records" style="width: 100%" @cell-click="txidUrl"> <el-table-column prop="burnTime" label="工夫" width="180"></el-table-column> <el-table-column prop="txid" :formatter="(row,column,cellValue,index) => {return ellipseText(cellValue);}" label="交易ID" width="180"></el-table-column> <el-table-column prop="amount" :formatter="(row,column,cellValue,index) => {return convertNum(cellValue);}" label="数量"></el-table-column></el-table> //交易ID单元格点击跳转txidUrl(row, column, cell, event){// console.log('row',row) console.log('column',column) console.log('cell',cell) console.log('event',event) if (column.label == "交易ID") { console.log(row.txExplorer)//整行的数据都在row里 window.location.href= row.txExplorer; } },

June 10, 2022 · 1 min · jiezi

关于vue.js:老生常谈的vue源码

当初这个时候在聊起vue源码,不论是vue2还是vue3都有些陈词滥调了吧。没得方法,谁让咱卷的慢呢,so 权当是个笔记吧了解Vue的设计思维 MVVM框架的三要素:数据响应式、模板引擎及其渲染 数据响应式:监听数据变动并在视图中更新模版引擎:提供形容视图的模版语法渲染:如何将模板转换为html先思考new Vue之后都做了什么(vue2)抽象的来说就做了组件实例化、初始话这么一个事 选项合并(mergeOptions)将全局注册的组件换入到new Vue的是实例中组件是实例的一些属性办法的初始化派发两个申明周期的钩子callHook(vm, 'beforeCreate')和callHook(vm, 'created')挂载initLifecycle(vm) // $parent $children 实例属性initEvent(vm) // 事件的监听initRender(vm) // 插槽 $slots $scopedSlots _c()/$createElement 生成vdomcallHook(vm, 'beforeCreate')initInjections(vm) // 注入祖辈传递下来的数据initState(vm) // 解决props/data/computed/watch/methodsinitProvide(vm) // 向后辈传递callHook(vm, 'created') new Vue class Vue { constructor(options) { // 0.保留options this.$options = options; this.$data = options.data; // 1.将data做响应式解决 new Observer(this.$data); // 2.为$data做代理 proxy(this, "$data"); // 3.编译模板 if (options.el) { this.$mount(options.el); } } // 增加$mount $mount(el) { this.$el = document.querySelector(el); // 1.申明updateComponent const updateComponent = () => { // 渲染获取视图构造 const el = this.$options.render.call(this); // 后果追加 const parent = this.$el.parentElement; parent.insertBefore(el, this.$el.nextSibling); parent.removeChild(this.$el); this.$el = el; }; // 2.new Watcher new Watcher(this, updateComponent); }}创立Vue时候的时候第一工夫保留的了options选项并进行了数据响应式的解决,返回的app在调用$mount进行渲染挂载其实在new Watcher和$mount()之间还有一个compile的类存在,我这里没有写,因为全写会比较复杂。 ...

June 10, 2022 · 4 min · jiezi

关于vue.js:mixin-混入

mixin 是 vue 组件复用性能的技术之一 他能够把多个组件中反复呈现的属性和办法进行封装不便屡次调用 应用 混入就是把组件屡次应用的属性和办法等内容进行封装新建一个 mixin 的文件夹用来包容混入的封装 export let demo={ methods:{ fun(){ console.log("你好!!!!!!") } }, data(){ return { } }, computed:{ }}调用全局混入 --mixin慎用可能会造成代码的净化、 import Vue from 'vue'import App from './App.vue'import router from './router'import store from './store'// 1.援用mixinimport {demo} from "./mixins"// 2.配置全局混入Vue.mixin(demo)Vue.config.productionTip = falsenew Vue({ router, store, render: h => h(App)}).$mount('#app')部分混入 --mixins <template> <div class="about"> <h1>This is an about page</h1> <!-- 3.就能够间接想怎么用就怎么用混入的内容 --> <button @click="fun()">点我调用混入的办法--{{text}}</button> </div></template><script>// 1.援用混入import {demo} from "@/mixins"export default {// 2.调用混入 mixins:[demo]}</script>Vue 生命周期的各个钩子函数 ...

June 10, 2022 · 1 min · jiezi

关于vue.js:Vue中如何解决跨域问题

跨域报错是前端开发中十分经典的一个谬误,报错如下 Access to XMLHttpRequest at '......' from origin '......' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.跨域谬误源自于浏览器的同源策略,想要解决跨域首先要晓得什么是同源策略 同源策略同源策略:驰名的安全策略,URL有三个根本组成部分:协定+域名或ip+端口,三个必须完全相同称之为同源,不同源的称之为跨域 URLURL比照http://localhost:3000/https://localhost:3000/不同源:协定不同http://localhost:3000/http://127.0.0.1:3000/不同源:域名或ip不同http://localhost:3000/http://localhost:3001/不同源:端口不同http://localhost:3000/http://localhost:3000/同源http://127.0.0.1:3000/http://127.0.0.1:3000/同源留神:同源策略不是服务器行为,而是浏览器的行为,服务器会失常响应申请,然而如果不同源会被浏览器拦挡 express服务器搭建一个express服务器用来演示跨域报错 装置express npm i expressapp.js let express = require('express') let app = express() app.listen(3000, () => { console.log('服务器已启动...') }) app.use(express.static('./views')) app.get('/getTest', (req, res) => { console.log(req.query) res.send(req.query) })views/index.html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Document</title> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <script> function getIpTest() { axios({ method: "get", url: "http://127.0.0.1:3000/getTest", params: { uid: 123 }, }).then((res) => { console.log(res.data); }); } function getDnameTest() { axios({ method: "get", url: "http://localhost:3000/getTest", params: { uid: 123 }, }).then((res) => { console.log(res.data); }); } </script> </head> <body> <button onclick="getIpTest()">getIpTest</button> <button onclick="getDnameTest()">getDnameTest</button> </body> </html>关上浏览器拜访http://127.0.0.1:3000/ ...

June 9, 2022 · 2 min · jiezi

关于vue.js:LP流动性挖矿系统开发构思详细逻辑

Uniswap 代码构造 Uniswap 智能合约代码由两个 github 我的项目组成。一个是 core,一个是 periphery。 https://github.com/Uniswap/un... https://github.com/Uniswap/un... core 偏外围逻辑,(LP 流动性挖矿零碎开发,具体对接v+hkkf5566)单个 swap 的逻辑。periphery 偏外围服务,一个个 swap 的根底上构建服务。单个 swap,两种代币造成的交易对,俗称“池子”。每个交易对有一些根本属性:reserve0/reserve1 以及 total supply。reserve0/reserve1 是交易对的两种代币的储存量。total supply 是以后流动性代币的总量。每个交易对都对应一个流动性代币(LPT-liquidity provider token)。简略的说,LPT 记录了所有流动性提供者的奉献。所有流动性代币的总和就是 total supply。Uniswap 协定的思维是 reserve0*reserve1 的乘积不变。 Periphery 逻辑 外围逻辑实现在 UniswapV2Router02.sol 中。称为 Router,因为 Periphery 实现了“路由”,反对各个 swap 之间的连贯。基本上实现了三个性能:1/add liquidity(减少流动性)2/remove liqudity(抽取流动性)3/swap(替换)。 1.add liqudity 减少流动性,就是同时提供两种代币。因为代币有可能是 ETH,针对不同状况有不同的接口。逻辑相似。 function addLiquidity( address tokenA, address tokenB, uint amountADesired, ...

June 9, 2022 · 2 min · jiezi

关于vue.js:vue中在浏览器重新刷新页面吸顶效果失效

问题:第一次加载我的项目的时候是能够失常显示吸顶成果的,然而从新刷新页面的时候就没有了 created() { this.getDestruction() this.watchScroll() window.addEventListener("scroll", this.watchScroll); }, async mounted() { await this.getMarket(); // console.log('this.turnover',this.burn) this.drawLine(); // 事件监听滚动条 }, destroyed() { // 移除事件监听 window.removeEventListener("scroll", this.watchScroll); window.removeEventListener("scroll", this.handleClick); }, methods: { watchScroll() { // 滚动的间隔 var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop; // 容器的高度 var offsetTop = document.querySelector("#headtitle_bg").offsetHeight; // 滚动的间隔如果大于了元素到顶部的间隔时,实现吸顶成果 if (scrollTop > offsetTop) { this.navBarFixed = true; } else { this.navBarFixed = false; } }, }吸顶之前吸顶成果隐没起因:获取不到#headtitle_bg节点解决办法:应用nextTick()办法,是将回调函数提早在下一次dom更新数据后调用,简略的了解是:当数据更新了,在dom中渲染后,主动执行该函数,Vue.nextTick()回调函数中的执行的应该是会对DOM进行操作。 批改后的代码 ...

June 8, 2022 · 1 min · jiezi

关于vue.js:vue-多个路由使用同一个组件页面

在我的项目中, 会有多个路由共用一个页面组件, 比方新增&编辑页面, 根本一样,只是数据结构不同而已, 这时新建路由和编辑路由,就能够应用同一个页面组件 但,存在一个问题,就是切换路由时, 路由变动了, 不会从新触发页面组件的钩子函数(只在第一次加载时调钩子函数)。这个问题是页面钩子生命周期相干, 为了解决能从新获取数据,从新加载页面。 总结了以下解决方案 办法一: 给router-view 里增加 key 惟一管制 //在父组件加载路由的中央,减少key<router-view :key="$route.fullPath"></router-view>办法二: 通过监听 $route 路由的办法 //在共用的页面组件中减少路由监听事件 watch:{ '$route': function(to, from){ if(to==="/create"){ // 解决该路由下的数据 } else if(to==="/update"){ // 解决该路由下的数据 } }, },办法三: 通过减少一个两头页面 empty.vue 解决跳转 methods: { init(){ // update 和create 路由都指向同一个组件 let id = this.$route.query.id if(id){ //编辑 this.$router.replace({path:"/update", query:{id, id}}) } else{ //新增 this.$router.replace({path:"/create"}) } },}

June 8, 2022 · 1 min · jiezi

关于vue.js:为什么vue2使用vfor时不要用index作为keydiff算法

前言1.什么是 diffdiff 算法是一种通过同层的树节点进行比拟的高效算法 2.diff 具备哪些劣势比拟只会在同层级进行, 不会跨层级比拟。在 diff 比拟的过程中,循环从两边向两头比拟 diff 流程图 patchgithub: vuejs/vue@2.6.14 patch /** * 是否是 非空 */function isUndef(v: any) { return v === undefined || v === null;}/** * 是否不是 非空 */function isDef(v: any) { return v !== undefined && v !== null;}/** * * @param oldVnode * @param vnode * @param hydrating * @param removeOnly */function patch(oldVnode, vnode, hydrating, removeOnly) { // 如果 新vnode 不存在 if (isUndef(vnode)) { // 如果 老vnode 存在, if (isDef(oldVnode)) invokeDestroyHook(oldVnode); return; } let isInitialPatch = false; const insertedVnodeQueue = []; // 老vnode不存在(首次渲染) if (isUndef(oldVnode)) { isInitialPatch = true; createElm(vnode, insertedVnodeQueue); } // 更新节点阶段 else { const isRealElement = isDef(oldVnode.nodeType); // 不是实在节点,并且 新、老节点是同一节点 if (!isRealElement && sameVnode(oldVnode, vnode)) { // 进行更新节点 patchVnode(oldVnode, vnode, insertedVnodeQueue, null, null, removeOnly); } else { if (isRealElement) { // 是否是 ssr渲染 if (oldVnode.nodeType === 1 && oldVnode.hasAttribute(SSR_ATTR)) { oldVnode.removeAttribute(SSR_ATTR); hydrating = true; } // ssr渲染逻辑 if (isTrue(hydrating)) { // 混合 if (hydrate(oldVnode, vnode, insertedVnodeQueue)) { invokeInsertHook(vnode, insertedVnodeQueue, true); return oldVnode; } else if (process.env.NODE_ENV !== 'production') { warn( 'The client-side rendered virtual DOM tree is not matching ' + 'server-rendered content. This is likely caused by incorrect ' + 'HTML markup, for example nesting block-level elements inside ' + '<p>, or missing <tbody>. Bailing hydration and performing ' + 'full client-side render.' ); } } // 不是 ssr渲染或混合失败,则创立一个空节点 oldVnode = emptyNodeAt(oldVnode); } // replacing existing element const oldElm = oldVnode.elm; const parentElm = nodeOps.parentNode(oldElm); // create new node createElm( vnode, insertedVnodeQueue, // extremely rare edge case: do not insert if old element is in a // leaving transition. Only happens when combining transition + // keep-alive + HOCs. (#4590) oldElm._leaveCb ? null : parentElm, nodeOps.nextSibling(oldElm) ); // update parent placeholder node element, recursively if (isDef(vnode.parent)) { let ancestor = vnode.parent; const patchable = isPatchable(vnode); // 遍历 父节点 while (ancestor) { // 卸载老节点的所有组件 for (let i = 0; i < cbs.destroy.length; ++i) { cbs.destroy[i](ancestor); } // 替换节点 ancestor.elm = vnode.elm; if (patchable) { for (let i = 0; i < cbs.create.length; ++i) { cbs.create[i](emptyNode, ancestor); } // #6513 // invoke insert hooks that may have been merged by create hooks. // e.g. for directives that uses the "inserted" hook. const insert = ancestor.data.hook.insert; if (insert.merged) { // start at index 1 to avoid re-invoking component mounted hook for (let i = 1; i < insert.fns.length; i++) { insert.fns[i](); } } } else { registerRef(ancestor); } // 更新父节点 ancestor = ancestor.parent; } } // 如果老节点存在,则删除 if (isDef(parentElm)) { removeVnodes([oldVnode], 0, 0); } // 否则卸载 老节点 else if (isDef(oldVnode.tag)) { invokeDestroyHook(oldVnode); } } } // 注册节点 invokeInsertHook(vnode, insertedVnodeQueue, isInitialPatch); return vnode.elm;}sameVnode判断是否是同一个节点 ...

June 8, 2022 · 6 min · jiezi

关于vue.js:Vue-中-JSX-的基本用法

根本用法首先须要约定一下,应用 JSX 组件命名采纳首字母大写的驼峰命名形式,款式能够少的能够间接基于 vue-styled-components 写在同一个文件中,简单的倡议放在独自的_Styles.js_文件中,当然也能够不采纳 CSS-IN-JS 的形式,应用 Less/Sass 来写,而后在文件中 import 进来。 上面是一个通用的骨架: import styled from 'vue-styled-components'const Container = styled.div` heigth: 100%;`const Dashboard = { name: 'Dashboard', render() { return ( <Container>内容</Container> ) }}export default Dashboard插值在 JSX 中应用单个括号来绑定文本插值 <span>Message: {this.messsage}</span><!-- 相似于v-html --><div domPropsInnerHTML={this.dangerHtml}/><!-- v-model --><el-input v-model={this.vm.name} />在 jsx 中不须要把 v-model 分成事件绑定和赋值二局部离开来写,因为有相应的 babel 插件来专门解决。 款式在 JSX 中能够间接应用 class="xx" 来指定款式类,内联款式能够间接写成 style="xxx" <div class="btn btn-default" style="font-size: 12px;">Button</div><!-- 动静指定 --><div class={`btn btn-${this.isDefault ? 'default' : ''}`}></div><div class={{'btn-default': this.isDefault, 'btn-primary': this.isPrimary}}></div><div style={{color: 'red', fontSize: '14px'}}></div>遍历在 JSX 中没有 v-for 和 v-if 等指令的存在,这些全副须要采纳 Js 的形式来实现 ...

June 8, 2022 · 4 min · jiezi

关于vue.js:vue项目在IE11下报错的解决方案

文章不易,请关注公众号 毛毛虫的小小蜡笔,多多反对,谢谢 问题我的项目可能会用IE关上,所以在本人电脑上关上IE,发现是IE11,原来这是windows 10的标配。而后在IE11下关上发现,竟然报错了。下图是域名拜访,只是配置了host。 剖析看起来貌似是DNS问题,但我曾经配了host。 在网络中看到申请没收回去,难道是网络问题? 自我感觉,这个起因能够先不折腾,感觉不是这个问题。 详情 请查看:毛毛虫的小小蜡笔

June 8, 2022 · 1 min · jiezi

关于vue.js:PHP开发者福音支持CRUD代码生成且前后分离的tp6Vue3后台管理系统开源啦

题目仿佛是个伪命题,反对代码生成,但又前后端拆散??其实不然,明天咱们要介绍的这款后盾管理系统,将web代码目录放在了tp的根目录内,代码生成能够:同时生成后端和前端代码,生成好的web代码间接就能够放到指定地位,而后通过后盾进行npm build,而web目录内蕴含:洁净(不含后端代码)、残缺(所有前端代码文件均在此内) 的前端代码文件,所以说这款后盾管理系统,的确是前后拆散的。 等等,你说在后盾进行npm build?是的,这款后盾零碎内置WEB终端,以实现一些现实中的性能,应用正确的状况下,您不再须要执行npm install和npm build等其余相干命令。 而后,终于,咱们能够请出明天的配角:✨✨BuildAdmin✨✨ 一款企业级极速后盾零碎。 [Gitee仓库 | GitHub仓库 | 文档] 介绍我的项目是基于Thinkphp6、Vue3、TypeScript、Vite、Pinia、Element Plus等的后盾管理系统,同时提供web和server端,vue-router-next,i18n(国际化)等vue3全家桶,而后根本的页面自适应,无需受权即可收费商用。 为什么抉择它?一、顶级技术栈下面说的我的项目技术栈中,没有一个不是最新且风行的技术栈,抉择TP6:因为tp只有6,抉择Vue3:因为Vue只有3,另外,咱们的Vue3应用了Setup、状态治理应用Pinia等等,均是新而风行还稳固。 二、性能完备 CRUD代码生成一行命令即可生成数据表的CRUD代码(大气且实用的表格,多达22种表单组件反对,受权限管制的编辑和删除等-同时主动生成增删改查权限节点)从而节俭大量工夫。 通过框架自带的test_build表,在调试模式下,只执行了一行命令:php think crud -t test_build,后盾间接多了一个知识库治理性能,框架主动生成了该数据表的后盾菜单,点开里边就是对应数据表的表格、减少/编辑表单、删除、公共搜寻等等,同时:生成的减少/编辑表单是依据字段名、字段正文等来建设表单元素和语言包的;test_build表就是设计的知识库表,只是表名为test_build而已。 自带终端家喻户晓,vue开发少不了npm,而npm就少不了要执行命令。 框架内置了一个WEB终端以实现一些现实中的性能,应用正确的状况下,您不再须要执行npm install和npm build等其余相干命令。 如本文结尾的演示图,执行了一次测试命令,这条命令首先是切换到了一个测试目录,该目录下有一个package.json文件,而后测试命令会install所有的包,来检测命令是否能够失常运行,并反馈执行状态。 值得一提的是,这个终端,反对多种包管理器:npm、cnpm、pnpm、yarn、ni都是反对的。 高颜值首先是后盾自适应PC、平板、手机等多种场景的反对,轻松应答各种需要。 其次本文结尾的演示图大小无限,如果你关上演示站,你间接就会发现,这个后盾,它长得不一样!最显著的中央是:它并没有强行填满屏幕的每一个缝,所有的性能版块,都像是悬浮在屏幕上的,同时又将屏幕空间及其正当的利用了。 图片上没有体现进去的,双击表单项能够间接编辑该行,回车间接保留表单,这点很好使,但同类框架也只是局部有此性能,而此框架的作者,把:在多行文本输入框中,应用Ctrl+回车来保留表单,也实现了,另外笔者看到的还有加载表格表单时的loading地位大小正当,表单保留按钮、甚至表格中的开关,也都有loading态。 润物无声提供字段级数据批改记录和批改比照;删除数据则主动对立回收,随时回滚和还原,平安且无感。 老规矩,间接看图吧 你能够看到,配置好要回收那些数据之后(不是指定数据ID,而是指定控制器、数据表等),数据被删就主动到回收站里边去了,能够一键还原或者是查看被删数据。 而敏感字段这个在理论业务中也比拟实用,管理员对一些敏感字段进行批改操作后,这里提供了一个Ctrl+Z,不得不说,这位大佬的想法,的确清奇,我就问还有那个后盾提供这种细粒度的批改反悔性能。 权限验证BuildAdmin实现了十分弱小的路由与权限模块。 路由与权限可在后盾可视化增删改查WEB端路由主动注册WEB端按钮级鉴权有限子级菜单(权限节点)前后两端双鉴权更多待您自行摸索 收费凋谢稳固零碎收费开源,且无需受权即可商业应用,并将继续批改bug和迭代版本。\最要害的是,官网并未打算做pro、plus、x等免费版本。主框架永恒收费开源。 还有自适应、文档欠缺、内置大量性能等等,请自行摸索... 装置应用提供了欠缺的文档,对于相熟ThinkPHP和Vue的用户,有疾速上手疏导,对于新人,别离提供了Windows下、Linux下、MacBook下的从零开始疏导。 对于演示站 账户:admin,明码:123456(演示站数据无奈批改,请下载源码装置体验全副性能)Gitee仓库GitHub仓库文档:wonderful-code.gitee.io 我的项目预览

June 7, 2022 · 1 min · jiezi

关于vue.js:vuerouter源码四createRouter源码解析

前言【vue-router源码】系列文章将带你从0开始理解vue-router的具体实现。该系列文章源码参考vue-router v4.0.15。源码地址:https://github.com/vuejs/router浏览该文章的前提是你最好理解vue-router的根本应用,如果你没有应用过的话,可通过vue-router官网学习下。 该篇文章将带你剖析createRouter的实现。 应用const routerHistory = createWebHistory()export const router = createRouter({ history: routerHistory, strict: true, routes: [ { path: '/home', redirect: '/' }, { path: '/', components: { default: Home, other: component }, props: { default: to => ({ waited: to.meta.waitedFor }) }, }, { path: '/nested', alias: '/anidado', component: Nested, name: 'Nested', children: [ { path: 'nested', alias: 'a', name: 'NestedNested', component: Nested, children: [ { name: 'NestedNestedNested', path: 'nested', component: Nested, }, ], }, { path: 'other', alias: 'otherAlias', component: Nested, name: 'NestedOther', }, { path: 'also-as-absolute', alias: '/absolute', name: 'absolute-child', component: Nested, }, ], }, ], async scrollBehavior(to, from, savedPosition) { await scrollWaiter.wait() if (savedPosition) { return savedPosition } else { if (to.matched.every((record, i) => from.matched[i] !== record)) return { left: 0, top: 0 } } return false },})createRouter在剖析createRouter之前,先来看下它的参数类型: ...

June 7, 2022 · 2 min · jiezi

关于vue.js:Vue初学

Vue筹备工作应用npm装置vue脚手架 npm i -g @vue/cli装置完之后在cmd中查看vue版本 vue -V 启动vue图形化项目管理界面 vue uivue创立我的项目是在这个图形化界面里创立 在图形界面启动我的项目 应用局域网(比方行里网络无奈在ui里下载)可能无奈在UI界面中装置依赖和插件,能够在同一个文件中再开一个终端,应用npm install bootstrap来手动装置依赖和插件 启动一个已存在的我的项目应用npm run dev。可能会报错没有装置某些依赖包,装置即可 书写Vue组件<style>属性关键字scoped 如果呈现报错 ERROR in ./node_modules/bootstrap/dist/js/bootstrap.js 11:90-115Module not found: Error: Can't resolve '@popperjs/core'则依据日志提醒,须要补充装置依赖,应用npm install @popperjs/core装置即可。 编写一个NavBar组件当前, NavBar本人要在<script>里写上name:NavBar,阐明该组件是叫<NavBar>挂载在App。<script>里写上import NavBar from ./components/navBar,export default里写上name:app,components:{NavBar};<templates>里写上<NavBar/>页面View组件写完当前,能够写路由router 所有的页面组件和NavBar组件一样,都是 <template></template><script></script><style></style>书写路由写路由在/router/index.js外面写;路由写完之后,能够写链接跳转,个别是在<a>标签中的href属性写,不过这种渲染形式是后端渲染,要进行前端渲染要应用<router-link>标签,只有改了这个标签就会发现变成前端渲染 <router-link class='navbar-home' :to="{name:'home'}"> //这里的name:'home'就是后面\router\index.js外面书写的路由中的name总结:在写路由的时候,尽量让每一个路由的name和component保持一致 { path:'/home', name:'HomeView', component:'HomeView', //这里起名须要应用两个单词,否则前面会报错(multi-words)}bootstrap罕用contaier.fluid 更偏两边布局 card零碎常做页面内容布局,范畴最大,蕴含grid grid零碎常做材料卡片 img属性,图片自适应类:class="img-fluid" Element-ui罕用引进element-ui成果步骤: 我的项目装置npm install element-uimain.js中引入Vue组件特地属性标签<slot>:当抽离公共局部后,然而又有自定义不同的内容,就会应用这个标签 <Content> 首页<Content/>=========================================// Content组件在定义的时候就会在内层多一个<slot><div class='container-fluid'> <div class='home'> <div class='card'> <slot></slot> </div> </div></div>书写每一个页面中的Content内容三个子组件之间要进行数据交互,就须要将数据寄存在独特的父组件的setup中。 setup是写在export外面的,上面是setup里: ref定义变量,能够应用.value从新赋值;效率低reactive定义对象,不可从新赋值;效率高setup(){ const user = reactive({ id:1, username:'mysql', useCount:123, is_use:false, }); return { user, } }须要返回下面的对象user,否则报错 ...

June 6, 2022 · 1 min · jiezi

关于vue.js:vuerouter源码二createWebHistorycreateWebHashHistory等源码解析

前言【vue-router源码】系列文章将带你从0开始理解vue-router的具体实现。该系列文章源码参考vue-router v4.0.15。源码地址:https://github.com/vuejs/router浏览该文章的前提是你最好理解vue-router的根本应用,如果你没有应用过的话,可通过vue-router官网学习下。 在vue-router 4.x中创立router时,须要应用createWebHistory、createWebHashHistory、createMemoryHistory中的一个创立一个history,这篇文章将就这三个函数进行解析。 应用import { createWebHistory, createRouter } from 'vue-router'const routerHistory = createWebHistory()const router = createRouter({ history: routerHistory, routes: [ ... ]})createWebHistorycreateWebHistory源码所处地位:src/history/html5.ts。首先来看createWebHistory的参数,函数能够承受一个base字符串可选参数,该参数提供了一个根底门路。在createWebHistory中首先会调用normalizeBase函数对传入的base进行标准化。 base = normalizeBase(base)来看下base标准化的过程: export function normalizeBase(base?: string): string { if (!base) { // 浏览其环境下尝试获取base标签的href属性 if (isBrowser) { const baseEl = document.querySelector('base') base = (baseEl && baseEl.getAttribute('href')) || '/' // 去除htttp(s)://xxx/,如https://example.com/folder/ --> /folder/ base = base.replace(/^\w+:\/\/[^\/]+/, '') } else { base = '/' } } // 确保base的前导/ if (base[0] !== '/' && base[0] !== '#') base = '/' + base return removeTrailingSlash(base)}如果没有配置base的话,在浏览器环境下会尝试获取<base>标签的href属性作为base,如果没有<base>标签或<base>标签的href属性没有值,base取/,而后又对base进行了reaplce(/^\w+:\/\/[^\/]+/, '')操作,该操作是去除base的http(s)://xxx局部(如果base是https://example.com/floder/child,base最终会变成/floder/child);非浏览器环境下,base间接取/。在最初会将base的开端/去除,而后返回base,这样做的目标是后续咱们能够通过base + fullPath的模式建设一个href。 ...

June 5, 2022 · 6 min · jiezi

关于vue.js:前端开发vue技术栈程序员的vs-code插件分享

工欲善其事,必先利其器,想要达成高效的开发指标,怎么能短少了适合的编辑器插件呢。通过近期开发的几个我的项目,我养成了本人的开发习惯,这里就分享一些好用的vs code插件给大家。 第一款,Auto Rename Tag,这款插件能够在你扭转标签名称的时候主动重命名对称的标签。第二款,Chinese (Simplified) (简体中文) Language Pack for Visual Studio Code,名字尽管长,但其实是一个vs code汉化插件,对于英文苦手来说本地化的界面可能更好的上手。第三款,code settings sync,这款插件能够通过gitee同步咱们的vscode配置,实用于那些常常在多台电脑之间切换应用或者常常重装系统的敌人,具体的配置办法能够参考 ,这里不做赘述。第四款,ESLint,是一款赫赫有名的代码规范性检测插件,可能给你的代码规范性保驾护航,还能够依照我的项目外面.eslintrc.js的配置来自定义检测形式。第五款,Live Server,相似于open in browser,能够将你的我的项目右键用浏览器关上,与open in browser不同的是,它是在本地启用一个服务器来运行你的我的项目,因而在你保留时能够实时预览,十分不便,毛病是敞开vs code之后网页也会生效,因为它是随着vs code外面的终端一起运行的。第六款,One Dark Pro,本篇介绍中惟一一款非功能性插件,它是用来丑化编辑器外观的,应用前正文文本是有点儿晃眼的绿色,装上这款插件后正文文本变成了容易疏忽的浅灰色,各种标签和变量也有各自的色彩,不容易混同,同时它还集成了Material Icon Theme的性能,左侧文件列表中的不同文件也有了不同的图标,而这一款插件也有三种不同的对比度模式,装置插件后在插件的详情页面点击“设置色彩主题”即可抉择。第七款,Prettier ESLint,这款插件能够依照ESLint的标准格式化代码,应用时须要在设置中编辑settings.json的eslint.options我的项目,具体的设置阐明稍后会在文末给出。第八款,Settings Sync,与后面的code settings sync类似,欠缺了了vs code本身的同步性能,这款插件应用微软账户或者github账户来同步,因其同步应用的服务器地址不在国内,比拟适宜重度github用户来应用,具体的教程能够看这里 Settings Sync 应用教程 ,教程中有一点没提到的是生成tokens的时候记得把默认的30days改成no expriation。第九款,Vetur ,能够用来提醒vue代码的高亮,同样相似的插件还有Vue 3 Snippets ,能够对vue2和vue3的代码进行主动补全,VueHelper ,能够将vue编写的代码给出提醒,敌人们能够自行抉择,我本人是把三款插件全副都装置了,享受三倍的高兴~ 最初,大家有什么比拟得心应手的插件也能够分享在评论区,文中有表述谬误或者有疑难的也能够提出来,不吝赐教。附:自己Prettier ESLint设置代码如下 { "update.enableWindowsBackgroundUpdates": false, "update.mode": "none", "window.zoomLevel": 2, "workbench.colorTheme": "One Dark Pro", "sync.gist": "58510748d9d691bd67101073cf3e1064", "editor.formatOnSave": true, "diffEditor.ignoreTrimWhitespace": true, "javascript.format.enable": false, "typescript.format.enable": false, "vetur.format.enable": false, "eslint.enable": true, "eslint.run": "onType", "eslint.options": { "extensions": [ ".js", ".vue", ".jsx", ".tsx" ] }, "editor.codeActionsOnSave": { "source.fixAll.eslint": true }}应用办法为点击编辑器左下角齿轮按钮,抉择“设置”,点击右上角“关上设置(json)”图标,备份好本人的设置代码之后,将以上内容粘贴进settings.json设置文件即可。 ...

June 5, 2022 · 1 min · jiezi

关于vue.js:通俗易懂讲解并手写一个vue数据双向绑定案例

问题形容面试中,面试官除了问基础知识以外,还喜爱问一些框架原理。比方:你对vue的数据双向绑定mvvm是如何了解的?网上的局部贴子可能写的有点形象,不便于疾速浏览了解。本篇文章就应用通俗易懂的简略形式,来解说并实现一个简略的vue数据双向绑定原理demo,心愿对大家有肯定的帮忙 先温习基本知识为了便于大家更好的了解下文数据双向绑定的代码,咱们最好先温习一下旧常识,如果基础知识扎实的道友,能够间接跳过这一段。 DOM.children属性返回DOM元素有哪些元素子节点代码: <body> <div class="divClass"> <span>孙悟空</span> <h4>猪八戒</h4> <input type="text" value="沙和尚"> </div> <script> let divBox = document.querySelector('.divClass') console.log('元素节点', divBox); console.log('元素节点的子节点伪数组', divBox.children); </script></body>示例图: 留神辨别:DOM.childNodes失去所有的节点,比方元素节点、文本节点、正文节点;而,DOM.children只失去所有的元素节点。二者返回的都是一个伪数组,但伪数组有length长度,代表有多少个节点,且能够循环遍历,遍历的每一项都是一个dom元素标签!不过伪数组不能应用数组的办法DOM.hasAttribute(key)/getAttribute(key)判断元素标签是否有key属性以及拜访对应value值代码: <body> <h3 class="styleCss" like="coding" v-bind="fire in the hole">穿梭前线</h3> <script> let h3 = document.querySelector('h3') console.log(h3.hasAttribute('v-hello')); // 看看此标签有没有加上v-hello这个属性,没的,故打印:false console.log(h3.hasAttribute('like')); // 看看此标签有没有加上like这个属性,有,故打印:true console.log(h3.getAttribute('like')); // 拜访此标签上加上的这个v-bind属性值是啥,打印:coding console.log(h3.hasAttribute('v-bind')); // 看看此标签有没有加上v-bind这个属性,,有的,故打印:true console.log(h3.getAttribute('v-bind')); // 拜访此标签上加上的这个v-bind属性值是啥,打印:fire in the hole console.log(h3.attributes); // 能够看到所有的在标签上绑定的属性名和属性值(key="value"),是一个伪数组 </script></body>示例图: 这两个api能够用来看标签上是否绑定了vue的指令,以及看看vue指令值是啥,以便于咱们去与data中的相应数据做对应DOM.innerHTML与DOM.innerText的区别二者均能够批改dom的文本内容。innerHTML是合乎W3C规范的属性,所以是支流应用的dom的api。而innerText尽管兼容性要好一些,不过支流还是innerHTML 代码: <body> <h3>西游记</h3> <button>更改dom内容</button> <script> let h3 = document.querySelector('h3') let btn = document.querySelector('button') btn.onclick = () => { h3.innerHTML = h3.innerHTML + '6' } </script></body>示例图: ...

June 5, 2022 · 4 min · jiezi

关于vue.js:配置文件npmrc优先级之在CICD工作流中私有NPM仓库使用

.npmrc是npm运行时配置文件,简略点说.npmrc能够设置package.json中依赖包的装置起源既从哪里下载依赖包,也能够配置token秘钥不便从公有的NPM仓库拉取安装包;npm、cnpm、pnpm、yarn都是在干一件事用起来没啥大区别,据说当初最好用的就是pnpm,上面的操作中都能够用pnpm代替npm,前提须要装置了pnpm;在上线部署的CI/CD中配置的话,没有必要用pnpm,pnpm实用于本地开发;什么是CI/CD呢?其实就是流水线容器化部署,主动拉取代码主动打包主动部署这一套;pnpm装置# 全局装置pnpm,都说它好用就装上间接用呗npm install -g pnpm配置文件.npmrc优先级电脑系统中可能会存在多个.npmrc文件,在咱们装置依赖包时,npm会依照如下程序读取配置文件,也就是优先级; 我的项目配置文件: /project/.npmrc用户配置文件:~/.npmrc全局配置文件:/etc/npmrc配置.npmrc.npmrc文件外面以key=value的格局进行配置;1、国内镜像源,在国内用国内的源速度飞起; 中国镜像站搜寻地址:https://npmmirror.com/registry地址:https://registry.npmmirror.com2、应用公有仓库,阿里云效“制品仓库”收费提供公有NPM治理(如果应用其它公有操作根本一样); 应用公有仓库是起因大部分是有一些业务上的封装,从公司平安角度思考不能应用公共仓库托管,应用了公有仓库不会影响原来公共源的拉取应用,公有仓库提供方(阿里云效)都给解决好了,咱们也不必管;如果应用了公有仓库,然而没有配置好凭证,npm install 就会报错;#拜访链接,能够依据操作步骤提醒操作https://packages.aliyun.com/npm/npm-registry/guide#设置镜像源,相当于在`~/.npmrc`文件中配置了镜像源,上面截图第一行npm config set registry=https://packages.aliyun.com/*******/npm/npm-registry/#登陆npm仓库并设置凭证npm login#输出阿里云效提供的用户名、明码和邮箱后,相当在`~/.npmrc`减少了公有拜访令牌,上面截图第二行`_authToken`前面的值就是令牌token请妥善保存//??????/:_authToken=0000-0000000-0000-0000在CI/CD工作流中应用公有包公有仓库配置完后,零碎家目录下会创立好.npmrc配置文件“~/.npmrc”,然而如果是在CI/CD中应用配置文件最好是放在我的项目录下,我的项目目录下的配置文件优先级也最高;# `请留神:这波操作相当于把你的秘钥token裸露在了我的项目目录下,是存在安全隐患的`# 复制一下就好,就是把创立好的配置文件复制到本人的我的项目目录下cp ~/.npmrc /project/爱护您的令牌你的令牌可能有权读取专用包、代表你公布新包或更改用户或包设置;不要将令牌增加到版本控制中或以不平安的形式存储令牌;将其存储在明码管理器、云提供商的平安存储或 CI/CD 提供商的平安存储中;# 编辑`.npmrc`文件,将`_authToken=`前面token用环境变量代替//???????/:_authToken=${NPM_TOKEN}# 应用`export`能够申明环境变量export NPM_TOKEN=0000-0000000-0000-0000# 理论开发是,每次都export一下也不事实,所以须要一劳永逸,写在`.zshrc`、`.bash_profile`echo export NPM_TOKEN=0000-0000000-0000-0000 >> ~/.zshrcCI/CD中的配置划重点:集体基本上等于收费应用,还有服务器资源赠送,收费的羊毛撸起来!网址:https://code-galaxy.net 基于Galaxy的流水线配置如下,如果应用的是其它CI/CD工具,基本上相似;Galaxy学习老本靠近于0;1、git-clone,克隆代码;2、depend-install,依赖装置; npm install -g pnpm --registry=https://registry.npmmirror.com \&& node -v \&& npm -v \&& pnpm -v \&& export NPM_TOKEN=0000-0000000-0000-0000 \&& pnpm install \&& pnpm run build:dev3、dockerfile-generator,生成Dockerfile;4、build-push-image,生成能够部署的镜像;

June 4, 2022 · 1 min · jiezi

关于vue.js:Vue2中虚拟DOM和Snabbdom

Vue2中的虚构DOM实现革新了了第三方库snabbdomSnabbdom 是一个虚构 DOM 库,专一提供简略、模块性的体验,以及弱小的性能和性能。应用起来也很简略package.json { "name": "parcel-test", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "dev": "parcel index.html --open", "build": "parcel build index.html" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "parcel-bundler": "^1.12.5" }, "dependencies": { "snabbdom": "^2.1.0" }}index.html <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Snabbdom-demo</title></head><body> <div id="app"></div> <!-- <script src="./src/01-test.js"></script> --> <script src="./src/02-test.js"></script></body></html>01-test.js中测试了单个元素的替换 import {init} from 'snabbdom/build/package/init'; // parcel这里要导入全门路,不然会报错import {h} from 'snabbdom/build/package/h'const patch = init([])// 第一个参数:标签+选择器// 第二个参数:如果是字符串就是标签中的文本内容let vnode = h('div#container.cls','hello world')let app = document.querySelector('#app')// 第一个参数:旧的vnode,能够是DOM元素// 第二个参数:新的vnode// 返回新的vnode// 比照两个vnode,比拟差别,更新到DOMlet oldVnode = patch(app,vnode)vnode = h('div#container.another','snabbdom test')patch(oldVnode,vnode)02-test.js中测试了多个标签的替换,还有异步更新和清空 ...

June 3, 2022 · 8 min · jiezi

关于vue.js:vue2element修改主题

参考链接:https://blog.csdn.net/sinat_36728518/article/details/113310494 后续优化总结

June 2, 2022 · 1 min · jiezi

关于vue.js:解决前端项目Cannot-read-properties-of-null-拉取项目安装依赖出现错误

首先拉取一个我的项目时npm i 却呈现以下问题 解决方案一(这个计划作者用了不行,而后就放弃了应用npm) 解决步骤: ①输出指令:npm cache clear --force ②接着重新安装依赖:npm i ③最初运行我的项目:npm run serve 解决方案二(可能是node版本过高,与我的项目之间不适配,而后应用cnpm,淘宝镜像源) 解决步骤: ①先卸载本人的node,重新安装致低版本 找到控制面板,在控制面板里卸载很洁净 ②到node官网找老版本,以往的版本 | Node.js 点击下载,默认装置。详情装置步骤(默认就行):Node.js 装置配置 | 菜鸟教程 ③进入全局cmd,配置cnpm 装置:命令提示符执行 npm install cnpm -g --registry=https://registry.npm.taobao.org测试是否胜利装置 cnpm -vnpm设置国内镜像 npm config set registry https://registry.npm.taobao.org④最初应用cnpm i进行装置依赖 ⑤用cnpm run serve进行我的项目运行 胜利!

June 2, 2022 · 1 min · jiezi

关于vue.js:Vue3的设计目标做了哪些优化

易用性:API简化;例如vue2中的v-model和sync修饰符,在vue3中对立用v-model,无需辨别两者不同;例如用于渲染函数外部生成VNode的h函数,h(type,props,children),其中的props不再须要思考辨别属性、特效、事件等,框架替咱们判断

June 1, 2022 · 1 min · jiezi

关于vue.js:vue使用之属性透传

属性透传与实传 实传:prop指定传递的属性; 透传:未指定prop传递的属性传递给子组件嵌套组件透传实现: 以二次封装ui组件场景为例 应用的api: $attrs, $listeners, inheritAttrs, 渲染函数 // 父组件<MyButton name="测试透传" type="error" :disabled="false" @click="clickBtn" />// 子组件const MyButton = { // 将未被props指定的属性(不包含style,class)和不含 .native 修饰符的事件监听器绑定到子组件Button上 template: `<div class="box"> <Button v-bind:type="type" v-bind="$attrs" v-on="$listeners" /> </div>`, components: { Button, }, inheritAttrs: false, // 禁止未被props指定的属性利用到组件根元素上 props: { type: { type: String, default: 'primary', }, }, created() { console.log(this.$attrs); // {name: '测试透传', disabled: false} console.log(this.$listeners); // {click: f} },};// ui组件Button, 间接应用如下<Button type="primary" name="测试文本" icon="xxx" disabled @click="xxx" />.native绑定事件到子组件根元素$listeners可用于将事件监听器指向到具体的某个子元素,应用更灵便将原生事件绑定到组件 引申应用:动静组件透传实现在下面案例的根底上实现动静生成表单内容 // template<div v-for="(config, index) in configArr" :key="config.type + index"> <!-- 动静组件,依据配置中的 Type 来决定渲染的是 Input 还是 Select --> <component :is="config.type" :configProps="config.props"></component></div>// configArr[{ type: 'Input', props: { placeholder: '我是默认值', clearable: true }}, { type: 'Button', props: { type: 'default' }}]// 注册新的组件, 应用渲染函数以代替动静组件// 应用渲染函数解构props,获取attribute绑定const CompFormItem = { components: { Input, Select }, name: 'FormItem', props: { config: { required: true } }, render (h) { // 第一个参数就是配置中的 type,也就是咱们的组件名称 return h(`${this.config.type}`, { props: { ...this.config.props || {} }, attrs: { ...this.config.props || {} } }) }}// 应用组件<FormItem :config="config"></FormItem>-----对于vue3.x的变更----- ...

May 31, 2022 · 1 min · jiezi

关于vue.js:vue2子组件中定义的data为什么必须是一个function

是什么需要:当初咱们须要在一个组件中定义一个name变量,并且把这个变量显示在界面上,代码: <template> <div> {{ name }} </div></template><script>export default { data() { return { name: 'syz' } }}</script> 那么问题来了,为什么组件中的data须要是一个函数呢,能够将data申明为一个对象吗,这样不是更间接吗?代码: <template> <div> {{ name }} </div></template><script>export default { data: { name: 'syz' }}</script> 如果是下面这种写法,不出意外的话,在vs code data处将会呈现红线报错 data property in component must be a function,提醒咱们data必须是一个function。 为什么好,重点来了,为什么呢?起因就是:通过函数返回数据对象,保障了每个组件实例都有一个惟一的数据正本,防止了组件间数据相互影响。 先上论断:每个子组件注册后会被解决成一个VueComponent实例,相似上面的MyVueComponent(...), data属性会挂在他的原型链下面 当子组件中的data是一个Object时,代码: function MyVueComponent(){ }MyVueComponent.prototype.data = { name:'jack', age:22,}const componentA = new MyVueComponent();const componentB = new MyVueComponent();componentA.data.age=55;console.log(componentA.data.age,componentB.data.age) // 55,55能够看到,当componentA.data.age赋值为55时,componentB.data.age也被更改为55了 当子组件的data是一个function时,代码: function MyVueComponent(){ this.data = this.data()}MyVueComponent.prototype.data = function() { return { age:22 }}const componentA = new MyVueComponent();const componentB = new MyVueComponent();componentA.data.age=55;console.log(componentA.data.age,componentB.data.age) // 55,22能够看到,componentA.data.age更改后,并不会影响到componentB.data.age的值,也就是咱们下面说的,防止了组件间数据相互影响 ...

May 31, 2022 · 3 min · jiezi

关于vue.js:腾讯地图api根据路线画自定义箭头

我遇到的状况:1、应用腾讯地图画出门路,并在地图上示意方向(也就是箭头指向)我查了很多的材料,并没有具体的论断,我依照api给的办法,我自定义做出的成果vue+element+腾讯地图API,(仅供参考)效果图如下: 思路1、首先看是否跟我应用的办法申明Map统一的办法,腾讯地图的JavaScript API GL的api(如有不同,能够看逻辑,逻辑是一样的,然而须要本人去专研下代码)https://lbs.qq.com/webApi/jav...2、如果看到这里,那我先讲下逻辑,我之前思考过计划:(1)地图自带的线段带的箭头指向(跟理论需要不符) ,而且,箭头不能大于具体宽度,这样咱们没方法扩大,果然放弃了(心愿腾讯地图api,这里能够改善下) 这时示例地址:https://lbs.qq.com/webDemoCen...这是api地址:https://lbs.qq.com/webApi/jav... (2)自定义DOM覆盖物(DOMOverlay)这是百度搜寻最多的计划,然而我看过,能够做到,申明img构造(img就是箭头的图片),依照img旋转不同的角度所失去的,然而会呈现一种bug,就是不会随着地图缩放而进行变动,这就很恼火了,所以我就没思考(测试必定给我提bug)(3)这种目前我应用的一种,依据两点的坐标,判断角度、拿到箭头的三角坐标给画两条线,联合成箭头形态,(说白点:就是跟画线一样,画进去的箭头)(4)依据画多边形,进行绘制,然而原理都是一样的,先找到箭头的三角坐标,之后进行解决,须要看具体的需要,(如果是箭头是笼罩有色彩的,那就先拿到坐标,进行多边形绘制,成果也能实现)。重点:拿到箭头的三个角的坐标!!!(5)其余的计划,大同小异,都是依据需要,联合坐标,进行绘制。 上面我就具体讲下第三种1、申明map以及polylineLayer(后面是地图,前面是画线),点位的申明,我就不做粘贴的,会一点都应该会撒点 <div class="echarts_heating" id="map"></div> //htmlvar map = new TMap.Map(document.getElementById("map"), { zoom: 11, //设置地图缩放级别 center: center, //设置地图中心点坐标 mapStyleId: "style1", //个性化款式默认style disableDefaultUI: true, showControl: false, baseMap: { type: "vector", features: ["base", "building3d", "point"], // 暗藏矢量文字可依据需要去配置 }, // mapStyleId: "style1", //设置款式ID,本例中的key绑定的style1为经典地图款式 //(若应用未绑定的款式或有效ID,则会提醒谬误,并用地图默认款式显示) });画线polylineLayer的申明以及线段的格调 var polylineLayer = new TMap.MultiPolyline({ map, // 绘制到指标地图 // 折线款式定义 styles: { style_blue: new TMap.PolylineStyle({ color: "#F15E59", // 线填充色 width: 3, // 折线宽度 lineCap: "round", // 线端头形式 }), style_dash: new TMap.PolylineStyle({ color: "#F15E59", // 线填充色 width: 3, // 折线宽度 lineCap: "butt", // 线端头形式 dashArray: [6, 5], // 虚线展现形式 }), }, geometries: [], });在vue的methods中 ...

May 31, 2022 · 2 min · jiezi

关于vue.js:模拟Vue响应式原理

当你把一个一般的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并应用 Object.defineProperty 把这些 property 全副转为 getter/setter。 数据劫持vue2中数据劫持应用了Object.defineProperty来实现Object.defineProperty(obj, prop, descriptor) 参数obj要定义属性的对象。prop要定义或批改的属性的名称或 Symbol 。descriptor要定义或批改的属性描述符。返回值被传递给函数的对象。 模仿vue中的data选项 // 模仿 Vue 中的 data 选项 let data = { msg: 'hello' } // 模仿 Vue 的实例 let vm = {} // 数据劫持:当拜访或者设置 vm 中的成员的时候,做一些干涉操作 Object.defineProperty(vm, 'msg', { // 可枚举(可遍历) enumerable: true, // 可配置(能够应用 delete 删除,能够通过 defineProperty 从新定义) configurable: true, // 当获取值的时候执行 get () { console.log('get: ', data.msg) return data.msg }, // 当设置值的时候执行 set (newValue) { console.log('set: ', newValue) if (newValue === data.msg) { return } data.msg = newValue // 数据更改,更新 DOM 的值 document.querySelector('#app').textContent = data.msg } }) // 测试 vm.msg = 'Hello World' console.log(vm.msg)当data对象中有多个属性时,此时须要遍历vm,把每一个属性都转换成vm中的getter和setter ...

May 30, 2022 · 5 min · jiezi

关于vue.js:最好用的-6-款-Vue-实时消息提示通知MessageNotification组件推荐与测评

本文完整版:《最好用的 6 款 Vue 实时音讯提醒告诉(Message/Notification)组件举荐与测评》 Vue 音讯提醒告诉组件(Message / Notification)是咱们日常开发中常常应用的组件,它可用作与用户交互的反馈提醒,信息提交胜利、谬误、操作正告等场景应用。原生 JavaScript  提供了 alert、prompt、confirm 等办法,这三个办法的不反对定制化,应用场景重大受限,特地是 alert 在浏览器外弹窗,体验十分蹩脚。因而要想给用户提供良好的应用体验,咱们须要封装一个定制化较好的 Vue 音讯提醒组件,这种组件看似简略,但也存在十分多深坑要小心,例如遮罩层、隐没工夫、点击事件的冒泡解决等。 我本人在开发和钻研 Message / Notification 性能组件时,发现其实 Github 上有十分多开源的制作精良,应用场景定位清晰的第三方音讯提醒组件库可用,社区成熟,代码简洁,间接援用即可,齐全没必要本人写,本文给大家举荐 6 款我用过的开源音讯提醒库,各有劣势,可按需自取。 如果你正在搭建后盾管理工具,又不想解决前端问题,举荐应用卡拉云 ,卡拉云是新一代低代码开发工具,可一键接入常见数据库及 API ,无需懂前端,仅需拖拽即可疾速搭建属于你本人的后盾管理工具,一周工作量缩减至一天,详见本文文末。 接下来我来介绍一下我用过且感觉不错的 6 款常见的 Vue Message / Notification 组件,大家可依据本人实现需求自取。 vue-notification - 专一实时音讯提醒 各类款式随便批改 你想要的它都有SweetAlert2 - 反对 Vue 3 实时音讯提醒、全功能、性能包罗万象vue-toasted - 极简风,代码简洁,自定义轻便,轻量级音讯提醒组件vue-toastification - 带有按钮和 loading 进度条的音讯弹窗组件,给用户更多交互vue-notifications - 超轻量级,适宜只需提醒组件根底性能的开发者vue-toast-notification - 超轻量级,多种提醒类型,可定义地位、持续时间,列队等属性,反对 Vue 3Vue-notification - 专一实时音讯提醒 各类款式随便批改 你想要的它都有 vue-notification 是简洁高效的音讯提醒组件库,惯例的胜利、谬误、正告款式随便筛选,它应用 Velocity 动效库作为它的动画反对,代码简洁,能够依据需要调整动画。更不用说惯例的色彩、字体、字号、弹出地位等细节,更是随便批改。 SweetAlert2 - 反对 Vue 3 实时音讯提醒、全功能、性能包罗万象 ...

May 30, 2022 · 1 min · jiezi

关于vue.js:vue2huskyeslintprettiercommitlint

本文介绍vue2增加git校验1、npx husky install 生成.husky的文件夹2、在.husky文件夹下创立文件pre-commit 内容如下:#!/bin/sh. "$(dirname "$0")/_/husky.sh"//--allow-empty 解决格式化prettier文件没变的问题npx lint-staged --allow-empty3、命令行提交 装置提交内容标准第一步:npm i -D commitizen 第二步:npx commitizen init cz-conventional-changelog --save-dev --save-exact 实现后: // package.json+ "config": {+ "commitizen": {+ "path": "./node_modules/cz-conventional-changelog"+ }+ }第三步(提交命令应用):npx cz或者:应用 yarn commit 手动提交(vscode)第一步:npm i @commitlint/config-conventional @commitlint/cli -D第二步:创立配置文件 // commitlint.config.jsmodule.exports = { extends: ['@commitlint/config-conventional']}//第三步:应用husky生成commit-msg(win10留神不要用空格生成文件后改回来)npx husky add .husky/commit-msg "npx --no-install commitlint --edit $1" 配置lint-stagedyarn add lint-staged -D //package.json "lint-staged": { "src/**": [ "prettier --config .prettierrc.js --write", "eslint --ext .js,.jsx,.ts,.tsx,.vue --no-error-on-unmatched-pattern --quiet --fix" ] },

May 30, 2022 · 1 min · jiezi

关于vue.js:推荐几个精简后台管理系统前端可快速进行开发

本文章举荐几款曾经精简化的后盾管理系统,前端下载模板可间接进行疾速开发。 应用的UI框架有以下:1. elementUI 2.13.x2. antd-Design 1.7.83. iview 3.2.xvue-antd-admin 精简版后盾管理系统vue-cli 3.xantd-design 1.7.8 vue-element-admin 精简版后盾管理系统vue-cli 3.xelement-ui 2.13.x vue-iview-admin 精简版后盾管理系统vue-cli 3.xiview 3.2.x

May 30, 2022 · 1 min · jiezi

关于vue.js:VueRouter模拟实现

Vue-Router hash模式 URL中#号前面的内容作为门路地址监听hashchange事件依据以后路与地址找到对应的组件从新渲染history模式通过history.pushState()办法扭转地址栏监听popstate事件依据以后路由地址找到对应组件从新渲染根本应用 // 1. 注册路由插件Vue.use(VueRouter)// 2. 创立 router 对象const router = new VueRouter({ routes:[ {nmae:'home',path:'/',component:homeComponent} ]})const vm = new Vue({ // 3. 注册 router 对象 router, render: h => h(App)}).$mount('#app')第一步实现install办法第二步实现构造函数,构造函数中须要初始化options,data,routeMap三个属性,data为响应式对象第三步,实现createRouteMap办法,把构造函数中传入options中的routes结构成键值对存储到routeMap中,键为路由地址,值为对于组件。第四步,实现initComponents办法第五步,运行时版本vue不反对template模板,手动实现一个render函数第六步,实现initEvent()办法 /* eslint-disable indent */let _Vueexport default class VueRouter { // 先实现install办法 // 1,判断以后插件是否曾经装置 static install (Vue) { if (VueRouter.install.installed) { return } VueRouter.install.installed = true // 2,把Vue构造函数记录到全局变量 _Vue = Vue // 3,把创立Vue实例传入的router对象注入到Vue实例上 // 混入 _Vue.mixin({ beforeCreate () { if (this.$options.router) { // 只需执行一次,并且是vue实例才执行,组件选项中没有router属性 _Vue.prototype.$router = this.$options.router // this.$options.router.init() // 调用初始化两个办法 } } }) } // 第二步实现构造函数 constructor (options) { this.options = options this.routeMap = {} // 解析options存储的routes,键是路由地址,值是组件 this.data = _Vue.observable({ current: '/' }) this.init() } // 第三步实现createROuteMap createRouteMap () { // 遍历所有路由规定,把路由规定解析成键值对的模式 存储到routeMap中 this.options.routes.forEach(route => { this.routeMap[route.path] = route.component }) } init () { this.createRouteMap() this.initComponents(_Vue) this.initEvent() } initComponents (Vue) { // 实现一个router-link组件 Vue.component('router-link', { props: { to: String }, // template: '<a :href="to"><slot></slot></a>' 运行时版本vue不反对template模板 render (h) { return h('a', { attrs: { href: this.to }, on: { click: this.clickHandler // 阻止点击的默认行为 } }, [this.$slots.default]) }, methods: { clickHandler (e) { history.pushState({}, '', this.to) // 扭转以后路由地址 this.$router.data.current = this.to e.preventDefault() } } }) const self = this Vue.component('router-view', { render (h) { const component = self.routeMap[self.data.current] return h(component) // 转化component为虚构dom } }) } initEvent () { // 注册popstate事件 window.addEventListener('popstate', () => { // this代表组件实例 this.data.current = window.location.pathname }) }}

May 28, 2022 · 2 min · jiezi

关于vue.js:Vue-之-nextTick-原理

一、异步更新队列可能你还没有留神到,Vue 在更新 DOM 时是异步执行的。只有侦听到数据变动,Vue 将开启一个队列,并缓冲在同一事件循环中产生的所有数据变更。如果同一个 Watcher 被屡次触发,只会被推入到队列中一次。这种在缓冲时去除反复数据对于防止不必要的计算和 DOM 操作是十分重要的。而后,在下一个的事件循环“tick”中,Vue 刷新队列并执行理论 (已去重的) 工作。 Vue 在外部对异步队列尝试应用原生的 Promise.then、MutationObserver 和 setImmediate,如果执行环境不反对,则会采纳 setTimeout(fn, 0) 代替。 例如,当你设置 vm.someData = 'new value',该组件不会立刻从新渲染。当刷新队列时,组件会在下一个事件循环 “tick” 中更新。少数状况咱们不须要关怀这个过程,然而如果你想基于更新后的 DOM 状态来做点什么,这就可能会有些辣手。 尽管 Vue.js 通常激励开发人员应用“数据驱动”的形式思考,防止间接接触 DOM,然而有时咱们必须要这么做。为了在数据变动之后期待 Vue 实现更新 DOM,能够在数据变动之后立刻应用 Vue.nextTick(callback)。这样回调函数将在 DOM 更新实现后被调用。例如: <div id="example">{{message}}</div>var vm = new Vue({ el: '#example', data: { message: '123' }});vm.message = 'new message'; // 更改数据vm.$el.textContent === 'new message'; // falseVue.nextTick(function () { vm.$el.textContent === 'new message'; // true});在组件内应用 vm.$nextTick() 实例办法特地不便,因为它不须要全局 Vue,并且回调函数中的 this 将主动绑定到以后的 Vue 实例上: ...

May 28, 2022 · 4 min · jiezi

关于vue.js:vfor中动态校验elform表单项代码示例

问题形容在我的项目开发中,咱们常常会遇到表单保留的性能,在表单保留前,经常须要做表单必填项的校验,校验通过当前才去发申请保留表单数据。然而,这个表单如果是动静的,即:能够新增雷同的表单。比方这个表单有输入框和下拉框须要校验,点击增加表格按钮,再新增一个雷同的表单,同样新的这个表单对应的输入框和下拉框也须要校验。本文记录一下对应代码写法思路,咱们先看一下效果图: 效果图 代码思路表单的主数据是要写成对象模式 :model="ruleForm" 不过既然是要动静的,必定是要循环呢,所以,能够写成这样:ruleForm: { // 动静循环项数组 formItemArr: [ { name: "", gender: "", }, ], },点击增加表格的时候,就能够间接push对应项就行啦,即,这样:// 增加一个表格 addForm() { let itemObj = { name: "", gender: "", }; this.ruleForm.formItemArr.push(itemObj); },重点来喽,因为是循环的,所以prop也要变成动静的了,要拼接上index,就变成依据索引去找对应的校验项了,即为::prop="'formItemArr.' + index + '.name'" ,这样的话,就变成了:prop="formItemArr.0.name"、prop="formItemArr.1.name"、prop="formItemArr.2.name" ... 这样的话,就能够关照到每一项中的每一个绑定的值了,校验就不会漏掉校验规定写成内联就能够触发校验函数this.$refs["ruleForm"].validate((val) => {})了<el-form-item label="姓名" :prop="'formItemArr.' + index + '.name'" :rules="{ required: true, message: '请填写', trigger: 'blur', }" > ......残缺代码演示的话,大家间接复制粘贴即可 <template> <div class="box"> <el-button @click="addForm" size="mini" type="primary" plain >增加表格</el-button > <el-button @click="saveForm" size="mini" type="primary" plain >保留表格</el-button > <br /> <br /> <el-form :model="ruleForm" ref="ruleForm" label-width="100px" class="formform" > <div class="formformItemClass" v-for="(item, index) in ruleForm.formItemArr" :key="index" > <el-form-item label="姓名" :prop="'formItemArr.' + index + '.name'" :rules="{ required: true, message: '请填写', trigger: 'blur', }" > <el-input size="mini" v-model.trim="item.name" placeholder="请填写" style="width: 200px" ></el-input> </el-form-item> <el-form-item label="性别" :prop="'formItemArr.' + index + '.gender'" :rules="{ required: true, message: '请抉择', trigger: 'change', }" > <el-select clearable size="mini" v-model="item.gender" placeholder="请抉择" > <el-option label="男" value="男"></el-option> <el-option label="女" value="女"></el-option> </el-select> </el-form-item> </div> </el-form> </div></template><script>export default { data() { return { ruleForm: { // 动静循环项数组 formItemArr: [ { name: "", gender: "", }, ], }, }; }, methods: { // 增加一个表格 addForm() { let itemObj = { name: "", gender: "", }; this.ruleForm.formItemArr.push(itemObj); }, // 保留表格 saveForm() { this.$refs["ruleForm"].validate((val) => { if (val) { console.log("符合要求,保留胜利", this.ruleForm); } else { console.log("error submit!!"); return false; } }); }, },};</script><style lang="less" scoped>.box { width: 100%; height: 100%; box-sizing: border-box; padding: 24px; .formform { width: 360px; .formformItemClass { padding-top: 24px; border: 2px dashed #ccc; margin-bottom: 18px; } }}</style>好忘性不如烂笔头,记录一下吧 ^_^

May 28, 2022 · 2 min · jiezi

关于vue.js:vue3封装一个符合思维简单实用的弹出层

前言在平时开发中,弹出层算是一个最罕用的组件了,尤其是后盾的表单页,详情页,用户端的各种确认都很适宜应用弹出层组件展现,然而个别组件库提供给咱们的个别还是组件的模式,或者是一个简略的服务。 组件模式的弹出层,在我看来应该是组件库提供给咱们二次封装用的,如果间接其实很不合乎直觉 写在页面构造里,然而却不是在页面构造中展现,放在那个地位都不适合只能放在最下边一个页面如果只有一个弹出层还好保护,多几个先不说放在那里,光保护弹出层的展现暗藏变量都是件头大的事件弹出层两头展现的如果是一个表单或者一个业务很重的页面,逻辑就会跟页面混在一起不好保护,如果抽离成组件,在后盾这种全是表格表单的时候,都抽离成组件太过麻烦那么有没有更合乎思维的形式应用弹窗呢,嘿嘿还真有,那就是服务创立弹出层 服务式弹出层等等!如果是服务创立弹出层每个ui组件库根本都提供了,为什么还要封装呢?因为组件库提供的服务个别都是用于简略的确认弹窗,如果是更重的表单弹窗就难以用组件库提供的服务创立了,咱们以ant-design-vue的modal为例子看看。 <template> <a-button @click="showConfirm">Confirm</a-button></template><script lang="ts">import { ExclamationCircleOutlined } from '@ant-design/icons-vue';import { createVNode, defineComponent } from 'vue';import { Modal } from 'ant-design-vue';export default defineComponent({ setup() { const showConfirm = () => { Modal.confirm({ title: 'Do you want to delete these items?', icon: createVNode(ExclamationCircleOutlined), content: 'When clicked the OK button, this dialog will be closed after 1 second', onOk() { return new Promise((resolve, reject) => { setTimeout(Math.random() > 0.5 ? resolve : reject, 1000); }).catch(() => console.log('Oops errors!')); }, // eslint-disable-next-line @typescript-eslint/no-empty-function onCancel() {}, }); }; return { showConfirm, }; }, }); </script>能够看到modal提供了属性content,在文档里咱们能够看到他的类型是能够传vue组件,然而这样写是有弊病的,咱们无奈在content中的组件敞开modal,想要在子组件敞开Modal须要把Modal自身传递给子组件,而后触发destroy();。 ...

May 27, 2022 · 3 min · jiezi

关于vue.js:Vue3和Vue2的不同及替代方案TypeScript篇

路由篇router/index.ts同ES6的router/index.js写法雷同 import { createRouter, createWebHashHistory } from "vue-router"import Home from '../views/Home.vue'const routes = [ { path: '/', name: 'Home', component: Home }]const router = createRouter({ history: createWebHashHistory(), routes})export default router但main.ts中不同 import { createApp } from 'vue'import App from './App.vue'import router from './router/index' // ES6中是import router from './router'import ElementPlus from 'element-plus'import 'element-plus/dist/index.css'const app = createApp(App)app.use(router).use(ElementPlus).mount('#app')

May 27, 2022 · 1 min · jiezi

关于vue.js:Vue3-相关笔记

记录 Vue3 应用过程中的问题和解决方案main全局属性能够通过 appconfig.globalProperties 绑定vue3 import { createApp } from 'vue'createApp(App).config.globalProperties.$yourFunc = () => {//...}vue2 import Vue from 'vue';Vue.prototype.$yourFunc = () => {//...};setupgetcurrentinstancesetup 中能够通过 getCurrentInstance().proxy 获取相似 Vue2 中 this 的援用组合式api中的模板援用<template> 中对子组件的 ref="comp1" 援用,在 setup 中能够申明同名变量获取 const comp1 = ref(null)defineExposescript setup 组件中须要被动应用 defineExpose({...}) 裸露想让内部通过 ref 援用应用的组件内属性(变量,办法...)$children$children 实例 property 已从 Vue 3.0 中移除,不再反对。

May 26, 2022 · 1 min · jiezi

关于vue.js:ModStart支持webp图片格式更加现代化

2022 年 05 月 25 日 ModStartCMS 公布 v4.0.0 版本,反对webp图片格式,更加现代化 与PNG图片相比,WebP的无损图片往往要再小上25%。而跟JPEG图片相比,则要小25%到34%。此外,该格局还反对透明度,动静图片等,跟GIF格局相比,大小更是可能缩小64%。

May 26, 2022 · 1 min · jiezi

关于vue.js:vue实现修改nodemodules文件夹源码重新npm-i-无需再手动修改源码

以批改 jsencrypt 加解密插件源码 为例: package.json "dependencies": { "jsencrypt": "^3.2.1"}装置jsencrypt 后,找到 jsencrypt 在node_modules文件夹里的源文件,批改你须要改变的代码npm i patch-package --save-dev //装置 patch-package 插件npx patch-package jsencrypt // 运行后会在我的项目根目录下的patches目录中创立一个名为jsencrypt+3.2.1.patch 的文件。将该patch文件提交后,即可在之后利用该补丁了。package.json"scripts": { "postinstall": "patch-package" //执行 npm install 命令时,会主动为依赖包打补丁了}提交代码

May 26, 2022 · 1 min · jiezi

关于vue.js:Vuex和全局事件总线的区别

咱们晓得通过全局事件总线的办法同样也可能实现任意组件间的通信,并且是依靠于Vue的个性联合一些技巧实现的,并不需要第三方的反对,那么和全局事件总线相比Vuex和全局事件总线$bus的区别在哪里呢?咱们上面来探讨一下: 总线和Vuex的共同点组件能找到它们的原理一模一样Vuex状态治理是利用Store仓库进行治理,而事件总线是通过$bus绑定($on)和触发($emit)事件实现的。他们都应用了Vue 数据代理的这个重要的一个内置关系:VueComponent.prototype.__proto__ === Vue.prototype 咱们来看看应用总线和应用状态治理的时候调用的的API就晓得了 /*--------事件总线-----------*/// 事件总线绑定事件this.$bus.$on('handleAdd',handleAdd)// 事件总线触发事件this.$bus.$emit('handleAdd',this.count) /*--------状态治理-----------*/// 获取状态this.$store.state.count// 批改状态this.$store.dispatch('increment',this.count)this.$store.commit('INCREMENT',this.count)咱们能够看到调用他们的形式都是再组件中应用this获取到他们,这里的this就是指向以后的实例化组件(VueComponent),于是咱们就能够通过VueComponent.prototype.__proto__ === Vue.prototype这个内置关系晓得数据最终是透过原型链找到的$bus/store,所以不论是Vuex还是总线,想要让全局可能获取到$bus/store他们的原理是一样的,那就是将他们创立在Vue的原型对象上。 const vm = new Vue({ render: h => h(App), // 创立总线 beforeCreate() { Vue.prototype.$bus = this }, // 创立状态治理仓库 store,}).$mount('#app')咱们能够看看Vue.use(Vuex)他到底帮咱们做了什么 // Vuex提供了install属性,通过Vue.use(Vuex)来注册。const install = function (Vue) { Vue.mixin({ beforeCreate() { if (this.$options.store) { Vue.prototype.$store = this.$options.store } } })}原理一模一样!! 总线和Vuex的优缺点是否应用第三方插件事件总线不是三方库原来就有,而状态治理是一个弱小且配套的第三方库。 事件总线不是三方库原来就有 章节结尾时说过,全局事件总线是依靠于Vue的个性联合一些技巧实现的,并不需要第三方的反对。他是依附在Vue实例对象上的办法实现事件的绑定($on)、触发($emit)、解绑($off) 咱们对总线的比喻经常就是公交车(bus[他有总线的意思]),或者是来实现组件间任意通信的工具人。它能够是组件的实例化对象(VueComponent)也能够是Vue实例自身(VM)【罕用】,当$bus是Vue实例自身时就会在原型链上呈现一个闭环就是$bus = Vue实例化对象。总之,全局事件总线是依附Vue元编程的个性,通过经验总结造成的产物,没有应用到第三方插件(音讯订阅和公布、状态治理都是三方库)。 状态治理是三方库 说到三方库,咱们都说这个库可能活下来被大家fork的个别就是niubility的我的项目,他们个别都有着优雅、弱小等等这些标签。状态治理就是这其中的一个。 状态治理作为三方库是合乎Vue对渐进式框架这个定位的产物。咱们用不必状态治理次要是看有没有必要杀猪用牛刀了。咱们看看源码就晓得为什么是牛刀了。 /** * Extends interfaces in Vue.js */import Vue, { ComponentOptions } from "vue";import { Store } from "./index";declare module "vue/types/options" { interface ComponentOptions<V extends Vue> { store?: Store<any>; }}declare module "vue/types/vue" { interface Vue { $store: Store<any>; }}咱们不须要读懂源码,只须要明确他是将vue引入了,在实现上咱们能够看到 ...

May 25, 2022 · 1 min · jiezi

关于vue.js:VUE一个渐进式的JavaScript框架

我的博客 渐进式?Vue.js(读音 /vju/,相似于 view) 是一套构建用户界面的渐进式框架。这句话你可能并不生疏,但你未必真正读懂了它。 咱们留神到这句话中有一个被作者高亮的词语—渐进式框架,其实明确了这个词语的意思,也便读懂了这句话,从而也就了解了Vue的核心理念。 那么渐进式框架到底是什么意思呢? 什么是框架,什么是库? 为了应答以上问题,开发人员从新梳理了代码的组织构造,把JS代码划分为三个板块,数据(M)、视图(V)、 逻辑管制(*)。 数据板块只含有数据内容,视图板块只负责更改款式,逻辑管制负责分割视图板块和数据板块和相应的逻辑,如下图所示。 这样代码构造组织的益处是不言而喻的,当需要产生变动时,只须要改变相应的板块即可。还是拿上文中提到的记录图片点击次数的需要为例,这是从新组织后的代码 demo,能够看到这次代码变得清晰易懂,而且你本人也能够去构想再减少某些需要,来看看须要改变代码的水平。 要留神的是,框架与咱们的库概念是不一样的。 框架(Framework) ,库(Library,简写Lib)在网上看到一个十分形象的举例: 如果咱们要买一台电脑,框架为咱们提供了曾经装好的电脑,咱们只有买回来就能用,但前提是你必须把整个电脑要买回来。另外,咱们还必须依据框架设定的应用规定来应用电脑。尽管这样用户可能轻松许多,但会导致很多人用一样的电脑,或你想自定义某个部件将须要批改这个框架。 而库就如本人组装的电脑。库为咱们提供了很多部件,咱们须要本人组装,如果某个部件库未提供,咱们也能够本人做。 也就是说,库是涣散的,但自由支配度高。框架是封装的,什么都帮你定义好了,然而自由度就必定低了。 图上的形容十分好,我就间接截图下来了。 渐进式所谓渐进式,你能够了解为: 就是一开始不须要你齐全把握它的全副性能个性,能够后续逐渐减少性能。没有多做职责之外的事件即:VUE不强求你一次性承受并应用它的全副性能个性 有趣味去深刻了解一下的话,能够看看这: (vue) => {渐进式} 什么是渐进式前端开发框架?

May 25, 2022 · 1 min · jiezi

关于vue.js:vuevue实现年份范围选择器yearrangepicker

之前看到有人须要一个年份范畴选择器,因为element-ui里没有提供<el-date-picker type="yearange">的类似性能,故本人写了一个简略的《年份范畴选择器》。上面是组件代码,其中有用到moment这个js日期工夫库,不须要的能够应用new Date()进行解决。 <template> <div class="picker-year"> <el-form ref="year-range-picker" :model="formData" :rules="rules"> <el-row> <el-col :span="11"> <el-form-item prop="yearStart"> <el-date-picker class="picker-first" v-model="formData.yearStart" value-format="yyyy" @change="val=>onDateChange(0,val)" :picker-options="pickerOptionsStart" :placeholder="startPlaceholder" type="year"> </el-date-picker> </el-form-item> </el-col> <el-col class="line" :span="2">-</el-col> <el-col :span="11"> <el-form-item prop="yearEnd"> <el-date-picker class="picker-second" v-model="formData.yearEnd" value-format="yyyy" @change="val=>onDateChange(1,val)" :picker-options="pickerOptionsEnd" :placeholder="endPlaceholder" type="year"> </el-date-picker> </el-form-item> </el-col> </el-row> </el-form> </div></template><script>import moment from 'moment'export default { name: "YearRangePicker", data() { return { formData: { yearStart: '', yearEnd: '', }, rules: { yearStart: [ {required: true, message: '请抉择开始年份', trigger: 'change'} ], yearEnd: [ {required: true, message: '请抉择完结年份', trigger: 'change'} ], }, pickerOptionsStart: { disabledDate(date) { return false }, }, pickerOptionsEnd: { disabledDate(date) { return false }, } } }, watch: { value: { handler(newVal, oldValue) { if (newVal) { this.yearStart = newVal[0] this.yearEnd = newVal[1] } }, immediate: true }, }, props: { value: { type: Array, default: [] }, startPlaceholder: { type: String, default: '' }, endPlaceholder: { type: String, default: '' } }, methods: { onDateChange(index, value) { this.pickerOptionsStart = { disabledDate: (date) => { return (moment(date) > moment().year(this.yearEnd)) }, } this.pickerOptionsEnd = { disabledDate: (date) => { return moment(date) <= moment().year(this.yearStart) }, } if (!value) { this.rules = { yearStart: [ {required: false, message: '请抉择开始年份', trigger: 'change'} ], yearEnd: [ {required: false, message: '请抉择完结年份', trigger: 'change'} ], } this.formData = { yearStart: '', yearEnd: '' } } else { this.rules = { yearStart: [ {required: true, message: '请抉择开始年份', trigger: 'change'} ], yearEnd: [ {required: true, message: '请抉择完结年份', trigger: 'change'} ], } } this.$refs["year-range-picker"].validate((valid) => { if (valid) { console.log('校验后果', index, value, [this.formData.yearStart, this.formData.yearEnd]) this.$emit('change', [this.formData.yearStart, this.formData.yearEnd]) this.$emit('input', [this.formData.yearStart, this.formData.yearEnd]) } else { console.log('error submit!!'); return false; } }); } },}</script><style scoped>.picker-year { display: flex; flex-direction: row; align-items: center; justify-content: flex-start; width: 100%;}.picker-first { width: 100%;}.line { text-align: center;}.picker-second { width: 100%;}</style>以下是在页面中调用的DEMO。 ...

May 25, 2022 · 2 min · jiezi

关于vue.js:Vuejs-监听属性

监听属性本章节,咱们将为大家介绍 Vue.js 监听属性 watch,咱们能够通过 watch 来响应数据的变动。 以下实例通过应用 watch 实现计数器: 实例<div id = "app"> <p style = "font-size:25px;">计数器: {{ counter }}</p> <button @click = "counter++" style = "font-size:25px;">点我</button></div><script type = "text/javascript">var vm = new Vue({ el: '#app', data: { counter: 1 }});vm.$watch('counter', function(nval, oval) { alert('计数器值的变动 :' + oval + ' 变为 ' + nval + '!');});</script>尝试一下 »以下实例进行千米与米之间的换算: 实例<div id = "computed_props"> 千米 : <input type = "text" v-model = "kilometers"> 米 : <input type = "text" v-model = "meters"></div><p id="info"></p><script type = "text/javascript"> var vm = new Vue({ el: '#computed_props', data: { kilometers : 0, meters:0 }, methods: { }, computed :{ }, watch : { kilometers:function(val) { this.kilometers = val; this.meters = this.kilometers * 1000 }, meters : function (val) { this.kilometers = val/ 1000; this.meters = val; } } }); // $watch 是一个实例办法 vm.$watch('kilometers', function (newValue, oldValue) { // 这个回调将在 vm.kilometers 扭转后调用 document.getElementById ("info").innerHTML = "批改前值为: " + oldValue + ",批改后值为: " + newValue;})</script>

May 17, 2022 · 1 min · jiezi

关于vue.js:Quickadmin基于ThinkPhp6VueElementUI后台管理框架

简介QuickAdmin 是一款基于ThinkPHP 6.x,ElementUI&&Vue 2.x前后端拆散后盾治理框架,通过框架自带的在线代码生成器,能够轻松的实现后盾治理的curd(增删改查),界面好看、开箱即用,领有丰盛的扩大组件和模板页面,适宜各类中后盾利用,无需(或大量)写代码!帮忙解决 PHP 前后端拆散我的项目 70%的反复工作,让开发更多关注业务逻辑。 内置功能模块角色组治理管理员治理菜单治理系统配置日志治理附件治理表单案例Online 代码生成插件市场相干文档开发文档:http://doc.quickadmin.icuQuickAdmin 官网:https://www.quickadmin.icu在线演示:http://demo.quickadmin.icu零碎演示截图 在线体验http://demo.quickadmin.icuuser: adminpwd:123456

May 17, 2022 · 1 min · jiezi

关于vue.js:vue3x页面功能拆分方式

vue3.x绝对比vue2.x次要的利用区别在于setup的应用,这个也是vue3.x的特色,所有的性能都得通过vue钩子引入应用,因为 setup 语法糖环境是不反对 this 的,这种开发方式有点回到原始的感觉,针对小我的项目还好,但如果页面模块性能简单,如果都放到一个文件里重叠,不仅会造成可读性差,而且工夫长了难以保护,所以这就须要进行按性能拆分了,形式同vue2.x一样,一个是依照组件拆分,一个是混入解决,还有就是通过vuex或api拆散性能 一、 组件能够把一些新增/编辑、配置、日志及公共操作等写到组件里,而后引入应用,组件拆分是次要的缩小页面代码量的解决形式,也是vue举荐的形式 PS:组件拆分的方向,一是公共组件,在我的项目其余模块也能应用到,二是页面级公有组件二、混入混入的场景次要是针对不须要模块且利用性能点过多,像这种能够通过混入的形式,把一些性能点拆分进去,引入应用,示例: mixins/instuctLog.ts: export default function() { const a = 123 function foo() { console.log('foo') } return { a, foo }}页面: <script lang="ts" setup>import instructLogMixin from './mixins/instructLog'const { a, foo } = instructLogMixin()</script>三、api把页面模块中的一些api申请放到api目录里引入应用 四、vuex按页面模块划分,把一些页面配置、枚举数据及数据扭转多组件响应更新的逻辑放到vuex中解决 更多前端常识,请关注小程序,不定期有惊喜!

May 17, 2022 · 1 min · jiezi

关于vue.js:ElectronVue3TypeScriptVite桌面应用程序项目初始化

初始化vite我的项目yarn create vite todolist --template vue-ts cd todolistyarnyarn dev浏览器拜访3000端口 装置Electronyarn add -D electron electron-builder rimraf vite-plugin-electron electron-devtools-installer如果感觉装置慢,能够改为淘宝镜像,或者根目录增加.yarnrc文件 registry "https://registry.npm.taobao.org/"electron_mirror "https://npm.taobao.org/mirrors/electron/"electron_builder_binaries_mirror "http://npm.taobao.org/mirrors/electron-builder-binaries/"插件阐明electron-builder:打包工具 rimraf:疾速删除文件或目录工具 vite-plugin-electron:vite 联合 electron 的库,对于这个插件能够参见 Vite 与 Electron 无缝连接 electron-devtools-installer:electron 开发工具 vite-plugin-electron 插件是将 vite 和 electron 联合在一起的,能够让咱们十分不便的联合 electron 和 vue,须要做一些指定的配置。 初始化electron我的项目新建目录文件electron-main/index.ts主过程目录和文件、electron-preload/index.ts预加载目录和文件 // electron-main/index.tsimport { app, BrowserWindow } from 'electron';import path from 'path';const createWindow = () => { const win = new BrowserWindow({ webPreferences: { contextIsolation: false, nodeIntegration: true, preload: path.join(__dirname, '../electron-preload/index.js'), }, }); if (app.isPackaged) { win.loadFile(path.join(__dirname, '../index.html')); } else { // Use ['ENV_NAME'] avoid vite:define plugin const url = `http://${process.env['VITE_DEV_SERVER_HOST']}:${process.env['VITE_DEV_SERVER_PORT']}`; win.loadURL(url); }};app.whenReady().then(() => { createWindow(); app.on('activate', () => { // On macOS it's common to re-create a window in the app when the // dock icon is clicked and there are no other windows open. if (BrowserWindow.getAllWindows().length === 0) createWindow(); });});app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit(); }});须要留神引入的预加载文件应该是打包后的 js 文件,门路和 ts 文件门路雷同,只有类型改为 js 即可。 ...

May 16, 2022 · 2 min · jiezi

关于vue.js:VUEX属性详解

在工作中应用 VUEX 进行状态治理,共享数据是十分不便的,要留神的是 vuex 的数据是存储在浏览器的内存中的,如果F5刷新了页面那之前申请的内存就会被开释,从新加载 js 脚本,这样一来咱们之前存在 vuex 中的数据就没了。如果咱们的一些重要的数据,例如 token 等,想要长时间的寄存,能够寄存在 localStorage/cookes 中。vuex 总共有 5 个属性供咱们进行数据管理,具体如下: state: 是vuex中存放数据的最小也是最根本的单元,vuex的数据源。惯例页面对于state中的数据最好只读取不要进行间接的批改,如果须要批改 state 中的属性值,能够通过官网举荐的 mutations 进行批改,具体用法请往下看。 state:{ name: '一蓑烟雨任平生', count: 10 } //应用办法 this.$store.state.namemutations: 相当于是 vuex 中的 methods,能够定义各种办法来进行对数据的解决,引入的第一个参数个别是 state 对象,第二个参数能够是通过函数传递过去进行操作的数据,在惯例页面中触发 mutations 须要应用 commit 办法,罕用$store.commit('your evevt',data),在 actions 中触发 mutations 中的办法能够在 actions 的办法中传入一个 context 对象,通过 context 来操作 mutations 中的办法,具体用法请往下看。 mutations:{ changeName(state, val){ state.name = val } } //应用办法 this.$store.commit('changeName', '张嘀嗒')actions: actions 和 mutations 一样,都是用于存储办法的属性,然而 actions 是用来存储有异步行为的办法的,咱们对于接口的申请就能够存在 actions 中,要留神的是,咱们仍旧不要间接批改 state 中的数据,如果波及到对 state 中数据进行批改的操作,还是通过 mutations 中的办法作为媒介来更改 state 中的数据,能够在 actions 的办法中承受一个参数 context 放在第一个地位,而后通过 context.commit('mutations Event',val) 的模式触发 mutations 中的办法实现对 state 中的数据的批改。 ...

May 16, 2022 · 2 min · jiezi

关于vue.js:vuejs中的默认插槽具名插槽作用域插槽三者的比较

前言Vue中的插槽是一个十分弱小的性能,在复用组件模块的时候,针对类似的构造,领有不通的内容时,应用插槽就十分不便,肯定水平上能够缩小在模板中应用大量的逻辑判断,管制显示不通的内容 同时,也能够让代码组织构造更加清晰,尽管应用上是简略了,然而插槽有些不是很好了解,不是很直观 它是让父组件能够向子组件指定地位处插入一html构造,自在灵便,也是组件间的一种通信形式 模式上有,默认插槽,具名插槽还有作用域插槽 大家在应用element-ui表格的时候,尽管都晓得怎么用,表头,以及内容模板的渲染,就应用了插槽,然而往往是很迷糊的 因为被形象了的 明天就一起来学习下,学完之后,在看element-ui表格的时候,心愿能给你带来一些启发,下次再次应用时,了解更上一层楼 视频解说-见b站-默认插槽视频解说-见b站-具名插槽视频解说-见b站-作用域插槽默认插槽官网文档里介绍到:Vue 实现了一套内容散发的 API,这套 API 的设计灵感源自 Web Components 标准草案,将 <slot> 元素作为承载散发内容的进口 这句话不是很好了解,换句话说,也就是,<slot>能够充当元素标签的占位符,能够代替在父组件援用的组件内的html标签内容 以如下示例所示 在App组件中引入SlotBase.vue组件 <template> <div id="app"> <SlotBase :lists="lists"> <p>默认内容</p> </SlotBase> </div></template><script>import SlotBase from "./components/SlotBase.vue"export default { name: 'App', components: { SlotBase }, data() { return { lists: [ { id: "001", title: "直播卖酒" }, { id: "002", title: "直播打赏" }, { id: "003", title: "直播炫富" } ] } }}</script><style>#app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px;}</style>而在编写SlotBase.vue组件中,引入slot标签,如下所示 ...

May 16, 2022 · 3 min · jiezi

关于vue.js:nuxtjs快速上手nuxt2

nuxtjs疾速上手(nuxt2) 提醒:本篇文章是博主观看b站up主前端aka老师视频学习整顿的文章视频指路:《CMS全栈我的项目》系列九:Nuxt+ElementUInuxtjs官网(nuxt2):NuxtJS 前言提醒:本篇文章为nuxt2: 本篇文章能够带你疾速搭建一个简略的Nuxt.js我的项目,Nuxt.js 是基于 Vue.js 的通用利用框架,Nuxt.js 预设了利用 Vue.js 开发 服务端渲染(SSR) 的利用所须要的各种配置,文章简要叙述 Nuxt.js 的根底性能,能够疾速上手Nuxt! 提醒:以下是本篇文章正文内容,上面案例可供参考 一、疾速生成nuxt我的项目运行 create-nuxt-app 确保装置了 npx (npx 在 NPM 版本 5.2.0 默认装置了):npx create-nuxt-app <我的项目名>或者用 yarn :yarn create nuxt-app <我的项目名> 二、nuxtjs配置IP与端口开发中常常会遇到端口被占用或者指定IP的状况。咱们须要在根目录下的 package.json 里对 config 项进行配置。比方当初咱们想把IP配置成 127.0.0.1 ,端口设置 8080。 { ..., "config": { "nuxt": { "host": "127.0.0.1", "port": "8080" } //或者 "nuxt": { "host": "0.0.0.0", "port": "80" } }} 三、在nuxt中应用less装置 less 和 指定版本的 less-loader npm install less less-loader@7.0.0 --save-dev全局款式文件在 static 目录中创立 base.less 文件,用来写全局款式。而后关上 nuxt.config.js 并找到 css: ...

May 16, 2022 · 3 min · jiezi

关于vue.js:在Vuex中使用websocket协议

在Vuex中应用websocket协定 提醒:这篇文章问ws协定的,在vuex中的应用,大家看好题目哦 前言博主这边最近的公司做的都是物联网的我的项目,波及到要和机器的COM口数据进行对接,后盾的话咱们公司是用的java,实时发送ws协定这边来承受,所以钻研了一下这个ws协定的应用,实测管用! 提醒:以下是本篇文章正文内容,上面案例可供参考 一、store仓库中store/index.js代码如下示例import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)export default new Vuex.Store({ state: { //推送音讯 data: {} }, getters: { }, mutations: { //websocket初始化 initWebsocket(state, itemId, userId) { const wsUrl = 'ws://192.168.1.156:80/ws' const ws = new WebSocket(wsUrl) //建设连贯 ws.onopen = function() { /* * 连贯胜利 * */ console.log('通信开始') // 发送心跳避免ws协定主动断联 setInterval(() => { state.webSocket.send(1) }, 1000 * 60) } //接管服务端音讯 ws.onmessage = function(e) { /* * 收到音讯时回调函数 * */ // console.log('收到的数据:', e.data) let data = JSON.parse(e.data) state.data = e.data console.log(data) } ws.onerror = function() { /* * 通信异样 * */ console.log('通信异样') } ws.close = function() { /* * 敞开连贯时回调函数 * */ console.log('连贯已断开') } } }, actions: {}, modules: {}})二、vue中调用App.vue中代码如下(示例):created() { //初始化websocket this.initSocket()},methods: { //websocket初始化 initSocket(itemId, userId) { this.$store.commit('initWebsocket', itemId, userId) } }

May 16, 2022 · 1 min · jiezi

关于vue.js:VScode快速生成vue3代码模板

VScode疾速生成vue3代码模板提醒:以下是本篇文章正文内容,上面案例可供参考 一、如何创立模板首先在VScode编辑器中关上,【文件】–>【首选项】–>【用户片段】–>【新代码片段】–> 取名vue.json 确定把下列代码放进去 { // Place your snippets for vue here. Each snippet is defined under a snippet name and has a prefix, body and // description. The prefix is what is used to trigger the snippet and the body will be expanded and inserted. Possible variables are: // $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. Placeholders with the // same ids are connected. // Example: // "Print to console": { // "prefix": "log", // "body": [ // "console.log('$1');", // "$2" // ], // "description": "Log output to console" // } "Print to console": { "prefix": "vue3", "body": [ "<template>", " <div $1></div>", "</template>", "", "<script setup>", "import { ref, reactive, toRefs, onBeforeMount, onMounted, watchEffect, computed } from 'vue';", "import { useStore } from 'vuex';", "import { useRoute, useRouter } from 'vue-router';", "/**", "* 仓库", "*/", "const store = useStore();", "/**", "* 路由对象", "*/", "const route = useRoute();", "/**", "* 路由实例", "*/", "const router = useRouter();", "//console.log('1-开始创立组件-setup')", "/**", "* 数据局部", "*/", "const data = reactive({})", "onBeforeMount(() => {", " //console.log('2.组件挂载页面之前执行----onBeforeMount')", "})", "onMounted(() => {", " //console.log('3.-组件挂载到页面之后执行-------onMounted')", "})", "watchEffect(()=>{", "})", "// 应用toRefs解构", "// let { } = { ...toRefs(data) } ", "defineExpose({", " ...toRefs(data)", "})", "", "</script>", "<style scoped lang='less'>", "</style>" ], "description": "Log output to console" }}二、如何应用模板新建vue页面,在文章中输出vue3后,点击回车即可

May 16, 2022 · 2 min · jiezi

关于vue.js:Vue32-setup语法糖总结

Vue3.2 setup语法糖总结前言 提醒:Vue3.2 版本开始能力应用语法糖!在 Vue3.0 中变量必须 return 进去,template中能力应用;而在 Vue3.2 中只须要在 script 标签上加上 setup 属性,无需 return,template 便可间接应用,十分的香啊! 提醒:以下是本篇文章正文内容,上面案例可供参考 一、如何应用setup语法糖只需在 script 标签上写上setup 代码如下(示例):<template></template><script setup></script><style scoped lang="less"></style>二、data数据的应用因为 setup 不需写 return,所以间接申明数据即可 代码如下(示例):<script setup> import { ref, reactive, toRefs, } from 'vue' const data = reactive({ patternVisible: false, debugVisible: false, aboutExeVisible: false, }) const content = ref('content') //应用toRefs解构 const { patternVisible, debugVisible, aboutExeVisible } = toRefs(data)</script>三、method办法的应用代码如下(示例):<template > <button @click="onClickHelp">零碎帮忙</button></template><script setup>import {reactive} from 'vue'const data = reactive({ aboutExeVisible: false,})// 点击帮忙const onClickHelp = () => { console.log(`零碎帮忙`) data.aboutExeVisible = true}</script>四、watchEffect的应用代码如下(示例):<script setup>import { ref, watchEffect,} from 'vue'let sum = ref(0)watchEffect(()=>{ const x1 = sum.value console.log('watchEffect所指定的回调执行了')})</script>五、watch的应用代码如下(示例):<script setup> import { reactive, watch, } from 'vue' //数据 let sum = ref(0) let msg = ref('你好啊') let person = reactive({ name:'张三', age:18, job:{ j1:{ salary:20 } } }) // 两种监听格局 watch([sum,msg],(newValue,oldValue)=>{ console.log('sum或msg变了',newValue,oldValue) },{immediate:true}) watch(()=>person.job,(newValue,oldValue)=>{ console.log('person的job变动了',newValue,oldValue) },{deep:true}) </script>六、computed计算属性的应用computed计算属性有两种写法(简写和思考读写的残缺写法) ...

May 16, 2022 · 3 min · jiezi

关于vue.js:Vue-修改组件中的样式

**有时候咱们须要批改组件的款式,明晓得对应的 class 或 标签 后批改其款式始终不失效,这里列举了两个办法解决:(局部代码省略)** 页面1: <template> <div id="app"> <News></News> <!--组件--> </div></template><style lang="css" scoped> .News /deep/ .name{ // 第一种写法 color:red; } .News >>> .name{ // 第二种写法 color:red; }</style>页面2:组件页面 <div class="News"> <div class="name">Name</div></div>

May 16, 2022 · 1 min · jiezi

关于vue.js:vue中使用高德地图amap步骤流程代码案例

问题形容开发中,有时候会遇到我的项目中须要搭配地图定位性能。 最常见最简略的就是公司的门户官网中,要有一个地图位置性能,因为须要让用户看到咱们公司在哪里,不便分割咱们。当然也有可视化须要、或者停车场定位性能须要,或者其余。 本文简述一下vue我的项目中应用高德地图,做一个定位的性能。咱们先看一下效果图 效果图 代码思路第一步,装置vue-amap插件cnpm i vue-amap --save 第二步,main.js文件中注册应用插件import Vue from 'vue'import App from './App.vue'// 其余插件应用配置// ......// 高德地图配置import VueAMap from "vue-amap"; // 引入插件Vue.use(VueAMap); // 应用插件VueAMap.initAMapApiLoader({ // 初始化插件 key: "baface8ee2ca22a7b9b66a4a6c1c1cd1", // 高德key,本人官网申请即可,这里是我申请的 plugin: ["AMap.Geocoder"], // 插件汇合,这里只有一个定位性能,所以就只放一个AMap.Geocoder uiVersion: "1.0.11", // 不加会报错,加上吧 v: "1.4.15", // 不加也不会影响,棘手加上吧});new Vue({ render: h => h(App), router}).$mount('#app')上述高德key大家最好本人去官网申请,而后最好应用本人的哈。这里为了演示,我贴出本人申请的。不过文末会简述如何申请高德key,毕竟大家做地图相干,还是要应用本人的哈。咱们先持续往下浏览第三步,绘制地图演示的话,间接复制粘贴即可,代码中已写了相干正文便于大家浏览 <template> <div class="box"> <!-- 地图组件 --> <el-amap vid="amapContainer" :zoom="zoom" :events="events" class="amapClass" ></el-amap> </div></template><script>// 引入地图加载实例办法import { lazyAMapApiLoaderInstance } from "vue-amap";export default { name: "gaode_ditu_amap", data() { return { map: null, // 地图实例存储变量 zoom: 13, // 地图缩放比例。zoom值越小,越宏观、越大,越宏观。大家能够更改zoom值看看成果 events: {}, // 地图事件 // 下方为上海虹桥火车站的经纬度坐标,我从网上搜寻,大家能够更改这个坐标看看成果 x: 121.320205, y: 31.193935, }; }, mounted() { // 插件加载胜利当前去绘制地图 lazyAMapApiLoaderInstance.load().then(() => { // 指定地图容器,并做相应的配置 this.map = new AMap.Map("amapContainer", { center: new AMap.LngLat(this.x, this.y), // 地图中心点的经纬度地位配置 zoom: this.zoom, // 地图缩放比例配置 }); // 标记的配置 var marker = new AMap.Marker({ map: this.map, // 应用此地图实例 icon: "https://webapi.amap.com/theme/v1.3/markers/n/mark_b.png", // 标记定位的小图标 position: [this.x, this.y], // 标记定位的小图标经纬度地位(个别标记定位的地位和地图中心点的地位要保持一致) }); // 应用相干配置 marker.setMap(this.map); }); },};</script><style scoped>.box { width: 100%; height: 100%; box-sizing: border-box; padding: 60px; background-color: #ced;}/* 指定地图的宽高 */.amapClass { width: 640px; height: 400px;}</style>申请高德地图key第一步,高德官网注册官网地址: https://lbs.amap.com/ ...

May 15, 2022 · 1 min · jiezi

关于vue.js:浅谈-SAP-UI5-框架对一些其他前端框架比如-Vue-的支持

咱们都晓得 Fiori 代表 SAP 新一代 UI 的界面风格,而 UI5 是 Fiori UX(User Experience,用户体验)的具体实现技术。从下图这则新闻 可能看出,SAP 决定将 Fiori 同具体 UI 实现技术解耦, 是出于什么思考呢? 家喻户晓,前端技术倒退的速度是十分快的,新理念,新名词,新工具层出不穷,很多前端开发程序猿常常悲叹"学不过去了",那么,如果只绑定于某一种具体的 UI 实现技术,Fiori UX 会不足足够的灵活性,很难充分利用业界最新技术来更好地为终端用户服务。 同时,这一行动也充分体现了 SAP 的确在聆听本人生态圈里开发人员的呼声,通过这种解耦容许 SAP 开发人员依据理论我的项目须要,灵便抉择最佳 UI 框架来开发 Fiori 利用。 Fiori UX 同底层 UI 实现框架解耦的要害就在于 SAP Fiori Fundamentals, 一个轻量级的展示层实现。从技术层面上说,SAP Fiori Fundamentals 不是一种新的 UI 技术或者框架,而是一系列 stylesheets 和 HTML 标签的汇合,以此来让 SAP 生态圈里的 UI 开发人员用其喜爱的 UI 框架,比方 Angular,React,Vue 等进行开发,同时主动保障开发出的利用仍具备 Fiori 的格调和用户体验。 SAP Fundamentals 是一个应用 HTML 和 CSS 的轻量级表示层,借助 Fundamentals 的样式表和 HTML 标签库,开发人员能够在任何基于 Web 的技术中构建统一的 SAP 应用程序。 ...

May 15, 2022 · 2 min · jiezi

关于vue.js:如何优雅地覆盖组件库样式

大家好,我是年年!组件库的款式笼罩不掉,这应该是很多前端在工作中遇到过的问题。明天从理论案例登程剖析起因,最初会给出在React和Vue我的项目中的最优解。 本文首发在我的公众号,订阅获取我的最新文章! 本文会讲清: React中CSS Module的原理是什么?:global是做什么的?Vue中Scoped的原理是什么?深度作用选择器是什么?先不讲概念,间接从需要登程:我应用了Antd组件库来展现一个日历。 当初我想将以后日期下面的蓝色边框变成紫色。 公众号后盾回复「101」获取React版本的在线地址,回复「102」获取Vue版本的在线地址能够试试你能不能实现。 不论是React还是Vue,整个Calendar是被封装起来的,咱们没有方法在组件外简略加上style/class改变外部的款式。 import { Calendar } from 'antd';...<div className="myWrapper"> <Calendar class="custom"/></div>定位要笼罩的款式首先用开发者工具定位对应的款式:.ant-picker-calendar-date-today,这就是咱们要批改的中央。 .ant-picker-calendar-full .ant-picker-panel .ant-picker-calendar-date-today { border-color: #1890ff; }相熟webpack的人应该晓得,引入的CSS文件最终都会被style-loader解决。简略来说,它的作用就是把CSS文件打包,放在style标签内,最初塞进HTML中作为一个外部样式表。不论是组件库的款式还是咱们写的自定义款式都是这样解决的。咱们要把组件库的款式先于自定义款式引入,这样自定义款式能力有更高的优先级。 批改源文件间接改选件库的CSS源码是最简略粗犷的办法。关上你我的项目的node_modules文件夹,一层层点开,找到对应款式文件,依照需要批改即可。 集体我的项目这样解决的确可行,然而团队单干时,同步他人本地的node_modules就比拟麻烦,只能算一个60合成法。 全局CSS文件之前提到,把本人写的的CSS文件放在组件库的款式前面,能够保障自定义有更高优先级。只有重写同名的款式,实践上就能实现笼罩组了。 但这样解决会发现并不起作用: /* src/demo.css */.ant-picker-calendar-date-today { border-color: purple; /* 笼罩为紫色 */}// src/Demo.js// 组件库的款式import 'ant-design-vue/dist/antd.css'; // 自定义款式import './demo.css'import { Calendar } from 'antd';...<div className="myWrapper"> <Calendar /></div>...因为这里还波及CSS组合选择器的优先级。 根底的优先级应该不必赘述:!important>内联款式>ID选择器>类选择器>标签选择器。(!important这种hack会导致我的项目不好保护,不提倡应用) 在这个根底上还有五种组合选择器要对优先级分数做累计,以类选择器为例: 后辈选择器(空格):.A .B抉择.A元素后的所有.B元素,子元素选择器(大于号):.A>.B抉择.A元素的间接后辈中的.B元素相邻兄弟选择器(加号):.A+.B抉择.A元素后紧邻的第一个兄弟.B元素后续兄弟选择器(~号):.A~.B抉择.A元素后所有的兄弟.B元素交加选择器(连在一起):.A.B抉择本身同时领有.A和.B两个属性的元素下面几个规定看着很简单,其实用的多的就是第一个后辈选择器,记住它就行。Antd组件库用的就是它: .ant-picker-calendar-full .ant-picker-panel .ant-picker-calendar-date-today { border-color: #1890ff; }如果说一个类选择器优先级分数是10分,那三个造成的后辈选择器就是30分。 而自定义的款式只有10分,所以即便放在更前面引入,也不能胜利笼罩。 .ant-picker-calendar-date-today { border-color: purple; // 笼罩为紫色}须要残缺重写整个选择器能力实现想要的成果。 这里补充一点,同样也是组合选择器,但并集选择器(逗号)优先级不累计:.A, .B抉择.A或者.B元素(能够是逗号+空格)款式隔离CSS Module和Scoped下面咱们引入自定义的全局CSS文件,实现了款式的笼罩,然而这种解法只能给80分。因为在理论工作中,我的项目Owner通常不容许应用全局CSS,这会造成款式净化:你定义了一个款式my_button,团队其他人凑巧也命名为my_button,这就造成款式抵触。 ...

May 13, 2022 · 1 min · jiezi

关于vue.js:vue源码watcher阅读记录

1.首先从computed钻研开始 function initComputed (vm: Component, computed: Object) { // 首先应用连等形式,申明watchers,并给vue实例上增加_computedWatchers属性,二者指向同一对象,用来记录所有的computed const watchers = vm._computedWatchers = Object.create(null) // 判断是否是服务端渲染 const isSSR = isServerRendering() for (const key in computed) { const userDef = computed[key] // computed两种申明形式函数、对象:{get,set} const getter = typeof userDef === 'function' ? userDef : userDef.get if (!isSSR) { // create internal watcher for the computed property. // 给每一个computed创立Watcher实例,并增加到watchers,vm._computedWatchers也会增加 watchers[key] = new Watcher( vm, getter || noop, noop, computedWatcherOptions ) } // 判断vm上是否已存在雷同属性名,存在报错,不存在代理到vm上,以便this.xxx调用 if (!(key in vm)) { defineComputed(vm, key, userDef) } else if (process.env.NODE_ENV !== 'production') { if (key in vm.$data) { warn(`The computed property "${key}" is already defined in data.`, vm) } else if (vm.$options.props && key in vm.$options.props) { warn(`The computed property "${key}" is already defined as a prop.`, vm) } else if (vm.$options.methods && key in vm.$options.methods) { warn(`The computed property "${key}" is already defined as a method.`, vm) } } }}2.defineComputed 1) 首先看下noop函数是什么? ...

May 13, 2022 · 2 min · jiezi

关于vue.js:如何发布一个公共的-vue-组件到-npm

如何公布一个公共的 vue 组件到 npm参考文章:https://www.freecodecamp.org/news/how-to-create-and-publish-a-vue-component-library/介绍一下如何将一个写好的组件公布到公共的 npm 上,能够让其像其它插件一样下载应用。一、全局装置工具 vue-sfc-rollupnpm i -g vue-sfc-rollup公布一个 vue 组件,须要配置不少货色,并要合乎公布 vue 组件的内容格局,这个过程能够通过 vue-sfc-rollup 这个工具来实现,它简化了须要公布 vue 组件的过程,好让你只须要关注组件的实现。 二、应用 vue-sfc-rollup 初始化我的项目在你须要创立这个 vue 组件的文件夹中执行初始化操作,而后就会进入初始化过程,这个过程跟新建一个 vue 我的项目差不多。 sfc-init1. 这个组件用于哪个版本 v2 还是 v3 2. 是一个组件库还是只是一个独自的组件 3. 输出这个我的项目名 4. 这个组件名是定义组件名,默认跟我的项目名统一,也能够本人定义名字 5. 这个组件应用 js 还是 ts 编写 6. 输出盛放组件文件的目录地位,默认在我的项目根目录如果是单组件我的项目,放在根目录也不妨 7. 自此,这个组件我的项目就初始化实现了我的项目目录如下: 三、实现组件的性能不要被下面的目录构造吓到,你不须要了解每个目录的作用,把这个当成一个一般的 vue 我的项目就能够,在你定义的组件文件中实现你的代码逻辑。 你能够依据本人须要增加 scss 反对什么的。比方我的 kyle-password-pad 组件中就用到了 scss ,所以我装置了 scss 反对,并增加了本人罕用的一些通用办法库和 scss 变量库。再提醒一遍,这我的项目就只是一个一般的 vue 我的项目,放心大胆的写就能够了。 1. 装置我的项目依赖先装置依赖,用 npm 或 yarn 都能够,我喜爱用 yarn ...

May 13, 2022 · 1 min · jiezi

关于vue.js:Vue-仔细说一说vue的插槽语法02

插槽简写,作用域插槽。 插槽的简写 (# vue 2.6.0新增)v-slot: --> # 就和 v-bind: 简写为 : 以及 v-on: 简写为 @ 一样,v-slot: 也领有本人的简写符号 # 留神:v-slot:要和旧语法做辨别// ↓ 上面是伪代码v-slot: === :slot !== v-slot: ( v-slot: 和 :slot 都是旧语法) 作用域插槽 (vue 2.6.0有更新)留神slot-scope是旧语法,曾经废除,理解但不要学习,防止混同。 让应用处的html可能拜访散发处的信息很有必要,因而呈现了作用域插槽。在散发处将须要传递的信息利用属性名+属性值的形式卸载<slot>标签上,应用处就能够以通过一个slotProps对象来拜访传递的信息。(个别会配合解构语法间接解构对应的key,举荐应用解构语法) ↓ Panel.vue <template id='panel'> <div class="panel"> <div class="title"> <slot name='s1' msg="散发处的信息" index="1"></slot> </div> </div></template>// ↓ 最根底的应用 <div id="app"> <Panel> <template v-slot:s1="obj"> <span>信息: {{ obj.msg }} </span> <span>序号: {{ obj.index }} </span> </template> </Panel></div>// ↓ 理论我的项目中个别这么写 (插槽的简写# ,属性解构) <div id="app"> <Panel> <template #s1="{msg, index}"> <span>信息: {{ msg }} </span> <span>序号: {{ index }} </span> </template> </Panel></div>再进一步,vue 2.6.0之后反对动静插槽名 ...

May 13, 2022 · 1 min · jiezi

关于vue.js:vue-项目使用高德地图

新版本的高德倡议应用平安key 首先在publit/index.html页面外面引入高德js,引入后整个我的项目能够应用高德 <script type="text/javascript"> window._AMapSecurityConfig = { securityJsCode:'平安秘钥', // } </script> <script type="text/javascript" src="https://webapi.amap.com/maps?v=2.0&key=一般key"></script> vue 文件中应用: container 为地图的容器,必须设置宽高 if (window.AMap) { this.map = new window.AMap.Map(document.querySelector('#container'), { // mapStyle: "amap://styles/darkblue", //设置地图容器id viewMode: "3D", //是否为3D地图模式 zoom: 11, //初始化地图级别 center: [114.300923, 30.575807], //初始化地图中心点地位 }); }},加载一些地图的工具 this.map.plugin( [ "AMap.HawkEye", "AMap.MapType", "AMap.Scale", "AMap.ToolBar", "AMap.MouseTool", ], () => { //加载工具条 var tool = new AMap.ToolBar({ position: "LT", }); this.map.addControl(new AMap.HawkEye()); this.map.addControl(new AMap.MapType()); this.map.addControl(new AMap.Scale()); this.map.addControl(tool); });这样地图就进去了,有地图后开发性能,比方在地图上画区域 减少点击的dom <div class="input-card" style="width: 200px"> <!-- <button class="btn" @click="drawPolyline" style="margin-bottom: 5px"> 绘制线段 </button> --> <button class="btn" @click="drawPolygon" style="margin-bottom: 5px"> 绘制多边形 </button> <!-- <button class="btn" @click="drawRectangle" style="margin-bottom: 5px"> 绘制矩形 </button> --> <!-- <button class="btn" @click="drawCircle" style="margin-bottom: 5px"> 绘制圆形 </button> --> <button class="btn" @click="drawClose" style="margin-bottom: 5px"> 革除 </button></div>减少点击工夫 ...

May 12, 2022 · 2 min · jiezi

关于vue.js:VueCliSpringBoot项目搭建依赖引入配置信息一

一、Vue Cli搭建一、须要装置node.js、VueCli二、window+R cmd 三、vue ui(可视化工具)1、创立VueCli 2、选取创立的门路 3、配置信息 4、抉择本人须要的默认配置,创立我的项目 二、引入axios、element ui1、main.jsimport Vue from 'vue'import App from './App.vue'import router from './router'import ElementUI from 'element-ui' //引入element uiimport 'element-ui/lib/theme-chalk/index.css'; //引入element ui 款式import axios from 'axios' //引入axios//设置全局Vue.prototype.$axios = axios //应用element uiVue.use(ElementUI) //阻止显示生产模式的音讯Vue.config.productionTip = false //axios切换生产环境和开发环境接口地址 this.$axios.get(/selectAll)axios.defaults.baseURL = 'http://0.0.0.0:1313'; new Vue({ router, render: h => h(App)}).$mount('#app')2、package.json serve:启动形式 npm run servebuild:打包形式 npm run build3、vue.config.js没有能够本人创立(与package.json同级) module.exports = {//敞开eslint验证 lintOnSave: false, devServer:{//设置端口号 port:1314,//解决 Vue 我的项目 invalid host header 问题disableHostCheck:true报错 disableHostCheck: true, }}

May 12, 2022 · 1 min · jiezi

关于vue.js:vue-自从使用了组件工作量减去了一半

常识付费应用 script 标签引入 Vue.js。在我的项目中也能够应用组件,实现一些公共业务。以 H5 登录弹窗为例,对在常识付费中应用组件进行阐明。 登录弹窗会在多个业务场景下应用,如果在每个业务场景下反复一套登录弹窗,会使得代码冗余,且前期保护较为繁琐。此时,咱们能够将登陆业务的代码剥离进去,在须要对其应用的中央进行引入即可。这样做不仅精简代码,而且在前期保护时也更加容易,不用再为新的性能需要,在多处进行代码改变。 在以后我的项目下,有两种剥离形式。一种形式是将登录业务代码写在独立的 JavaScript 文件中,其中的 DOM 片段须要进行字符串拼接;另一种形式是应用插件,将写有 DOM 片段的 HTML 文件、JavaScript 文件、CSS 文件进行组合。 拼接字符串形式:在晚期我的项目中,应用的就是这种形式。 如上图所示,图中的模板内容应用字符串拼接而成。这种形式拼接字符串一旦超多,会显得代码很乱,且易出错。 组合形式:我的项目应用 RequireJS 进行模块化开发,所以咱们能够应用 text.js 和 css.js 插件,引入 HTML 和 CSS。 如上图所示,咱们将登录组件的 HTML、CSS 和 JavaScript 文件放在 base_login 文件夹下。 如上图所示,base_login 文件夹下的文件。 如上图所示,这是 index.html 中的内容。 如上图所示,这是 index.css 中的内容。 如上图所示,这是 index.js 中的内容,其中引入 index.html 和 index.css 文件。 如上图所示,在页面中应用登录组件,先引入,再应用。 如上图所示,这是组件的应用。 源码附件曾经打包好上传到百度云了,大家自行下载即可~ 链接: https://pan.baidu.com/s/14G-b...提取码: yu27百度云链接不稳固,随时可能会生效,大家放松保留哈。 如果百度云链接生效了的话,请留言通知我,我看到后会及时更新~ 开源地址码云地址:http://github.crmeb.net/u/defu Github 地址:http://github.crmeb.net/u/defu ...

May 11, 2022 · 1 min · jiezi

关于vue.js:ReactVue2和Vue3在原理等内容上的异同

一,在diff算法上的异同相同点:1.虚构DOM在比拟时只比拟同一层级节点,复杂度都为 O(n),升高了算法复杂度。2.都应用key比拟是否是雷同节点,都是为了尽可能的复用节点。3.都是操作虚构DOM,最小化操作实在DOM,进步性能(其实虚构DOM的劣势 并不是在于它操作DOM快)。4.都是不要用 index作为 key。 不同点:1.diff算法遍历节点方向:React的是仅向右挪动,Vue2的是双端向两头挪动,Vue3的是在Vue2的根底上减少最长递增子序列的算法优化。 2.diff算法比拟变量:vue保护四个变量: oldStartIdx => 旧头索引oldEndIdx => 旧尾索引newStartIdx => 新头索引newEndIdx => 新尾索引两边方向同时比拟,由新的地位来获取实在DOM;如果老的先走完,就增加;如果新的先走完,就删除react保护三个变量: 1.nextIndex => 遍历nextChildren时候的index,每遍历一个元素加1 (遍历新节点)2.lastPlacedIndex => 上一次从prevChildren中取出来元素时,这个元素在prevChildren中的index(新节点对应)3.oldIndex => 元素在数组中的地位(旧节点对应的地位)节点挪动前提是:oldIndex < lastPlacedIndex 挪动的准则:首个节点(指的是新节点)不执行挪动操作(除非它要被移除),以该节点为原点,其它节点都去寻找本人的新地位;将原来的元素往右移,通过lastIndex来管制。在lastIndex右边的,就往lastIndex左边挪动;在lastIndex左边的,就不须要动。 nextIndex : 往右遍历,逐步+1oldIndex:依据nextIndex在旧结点中寻找对应的元素,如果能找到比拟oldIndex和lastPlacedIndex,否则增加lastPlacedIndex:能够了解为是一个比拟指引,当产生挪动的时候lastPlacedIndex值放弃上一次比拟值,不做挪动应用oldIndex值oldIndex = 4 > lastPlacedIndex 不做操作,且 lastPlacedIndex = oldIndex = 4oldIndex = 0 < lastPlacedIndex 挪动, lastPlacedIndex放弃不变 3.diff算法比对形式:React只比拟节点类型和key,Vue比拟节点类型和key,还有属性

May 10, 2022 · 1 min · jiezi

关于vue.js:面试官如何自己手写一个mini的vuex3

介绍说来惭愧,这对于喜爱摸鱼的程序员来说,vue3都公布这么久了,当初才开始浏览vuex3源码,当初分享一下集体对这次学习的总结,写的不好请大家轻喷。 地址源码地址:vuejs/vuex@3.6.2 myGithub:2460392754/mini-vuex3 我的项目构造src├── core│ ├── helpers.ts│ ├── index.ts│ └── store.ts├── types│ └── index.ts├── utils│ ├── index.ts│ ├── isModuleType.ts│ ├── reactive.ts│ └── register.ts└── index.ts实现1 根本1.1 注册应用class的static属性进行创立一个名为install的静态方法, 用于Vue.use注册插件。 插件注册时把以后环境的vue对象援用保留下来,确保我的项目和插件应用的是同一个援用对象。因为须要利用我的项目中的data性能来辅助state和getters值更新后触发视图更新。 github: mini-vuex3/src/core/store.ts#L6-L23 import type { VueConstructor } from 'vue';// 保留以后vue援用, 确保和我的项目应用雷同的援用let _vue: VueConstructor;export class store { /** * 插件注册 * @param vue */ static install(vue: VueConstructor) { _vue = vue; } // do something...}1.2 实例化通过class的构造函数进行初始化。 (Tips: registerState和registerGetters会在前面的实例属性里讲到) github: mini-vuex3/src/core/store.ts#L40-L59 import type Vue from 'vue';import type { StoreOpts } from '../types';// 保留以后vue援用, 确保和我的项目应用雷同的援用let _vue: VueConstructor;export class store { private _vm: Vue = null; private _mutations = null; private _actions = null; private _modules = null; getters = null; constructor(opts: StoreOpts) { // 增加 原型属性,指向以后store实例化后的对象 _vue.prototype.$store = this; // _state对象 响应式解决, 须要告诉我的项目视图更新 this._vm = new _vue({ data() { return { _state: registerState(opts), }; }, }); this.getters = registerGetters(this.state, opts || {}); this._mutations = opts.mutations || {}; this._actions = opts.actions || {}; this._modules = opts.modules || {}; registerModules(this._mutations, this._actions, this._modules); }}registerModules ...

May 10, 2022 · 6 min · jiezi

关于vue.js:vue组件的一点探索和思考

文章不易,请关注公众号 毛毛虫的小小蜡笔,多多反对,谢谢 起源和问题在增加主机和批改明码的弹窗中,都有雷同的“测试连通及硬件检测”的性能。 如下截图所示: 目前的实现形式是,别离在两个弹窗中各自写的代码。 那是否抽出来做一个专用的组件呢? 因为测试连通的按钮,点击后执行的代码的确比拟多,大略40行。 尽管能够简略抽出来作为mixin,但如果别的页面也要用呢? 想着还是组件复用度和通用性比拟高,所以就想抽出来做一个专用组件。 代码如下所示: // html<el-form-item> <el-button class="test" @click="handleClickTestConnectivity" :disabled="testing" :loading="testing">测试连通及硬件检测</el-button> <div v-show="isTestConnectivity" class="tested"> <img :src="checkSvg" class="xuanze" /> 连贯胜利!该主机CPU{{ testConnectivityInfo.cores }}核,内存{{ testConnectivityInfo.memory }}G,硬盘{{ testConnectivityInfo.totalSpace }}G </div> <div v-show="isTestConnectivityFailed" class="testfail">{{ testConnectivityInfo }}</div> </el-form-item> // jshandleClickTestConnectivity() { const params = { hostIp: this.form.hostIp, sshPort: this.form.sshPort, sshAccount: this.form.sshAccount, sshPasswd: this.form.sshPasswd } this.$refs.form.validate(async (valid) => { // 校验通过并且以后没有在测试的工作 if (valid && !this.testing) { this.testing = true this.resetCheck() try { const res = await hostService.testConnectivity(params) if (res.code === 0) { this.isTestConnectivity = true this.testConnectivityInfo = res.data } } catch (e) { if (e.data.code === -1) { this.isTestConnectivityFailed = true this.testConnectivityInfo = e.data.message } else { let mes = e.data.message if (!mes) { mes = '服务器外部谬误' } Notification.error({ title: '申请失败', message: mes, position: 'bottom-right' }) } } finally { this.testing = false } } })}剖析问题1因为须要点击button才发申请,发申请的代码在子组件外面,但参数(form表单)却在父组件那边。 ...

May 9, 2022 · 1 min · jiezi

关于vue.js:Vue注册的全局组件配置对象保存的位置

背景有时候你想给Vue一些组件库新增一些补丁性能或者批改性能,这些库如果像ElementUI一样有裸露到全局的api,还容易运行时篡改,如果没有裸露到全局上但有注册成全局组件,然而你又不想去库的源代码,怎么办呢?其实咱们能够在运行时动静去篡改或者新增一些性能,这个时候咱们须要拜访这些组件的配置对象 Vue2.x版本在Vue.options.components中Vue 3.X版本在Vue.createApp这个api返回的对象的_context.components中// 例如Vue.createApp({})._context.components

May 9, 2022 · 1 min · jiezi

关于vue.js:vue3APIwatch

watch官网概念 graph LRA[watch] -->B[作用]A[watch] -->C[特点]A[watch]--> D[与watchEffect的共享行为]B-->B1(侦听单个数据源)B-->B2(侦听多个数据源)C--> |1|C1(懈怠执行回调函数)C1--> C12(只有被监听的数据源扭转时才会触发回调)C--> |2|C2(明确了侦听器触发的条件和机会)C2--> C21(触发条件:被监听的数据源)C2--> C22(触发机会:被监听的数据源产生扭转)C--> |3|C3(可拜访被监听数据源发生变化前后的值)第一个参数:指定的数据源第二个参数:指定数据源发生变化时的回调let color = ref('red'); // 定义一个数据源setTimeout(() => { color.value = 'blue'; // 扭转数据源}, 1000);写法一// watch(// () => color.value,// (newValue, oldValue) => {// console.log('newValue:', newValue);// console.log('oldValue:', oldValue);// }// );写法二watch(color, (newValue, oldValue) => { console.log('newValue:', newValue); console.log('oldValue:', oldValue);});// 上述打印后果:newValue: blueoldValue: red

May 8, 2022 · 1 min · jiezi

关于vue.js:vue3APIwatchEffect

watchEffect 函数官网介绍watchEffect graph LRA[watchEffect函数] -->B[概念]B-->B1(watchEffect是什么?)A-->C[次要特点]C-->|1|C1(立刻执行)C1-->C11(谁立刻执行?)C-->|2|C2(响应式追踪依赖)C-->|3|C3(进行侦听)C3-->C31(怎么进行?)C3-->C32(在什么时候进行?) C-->|4|C4(革除副作用) C-->|5|C5(附加options) C5-->C51(选项值 pre) C51-->C511(有什么影响?) C5-->C52(选项值 post) C52-->C521(有什么影响?) C-->|6|C6(侦听调试) C6-->C61(onTrack)C6-->C62(onTrigger)watchEffect 概念watchEffect是一个函数,它承受一个立刻执行函数,同时响应式追踪其依赖,并在其依赖变更时从新运行该函数。官网概念 watchEffect 特点一 立刻执行watchEffect 的回调函数会 立刻执行组件初始化时立刻执行二 响应式追踪依赖(数据)如下代码: 每一次age的值发生变化时,都会被watchEffect所收集,并且 watchEffect 的回调函数会立刻执行。let age = ref(5); setTimeout(() => { age.value = 6;}, 1000); setTimeout(() => { age.value = 7;}, 2000); watchEffect(() => { console.log('age的值', age.value);});// 顺次打印出 5 6 7三 进行侦听watchEffect 在组件卸载时主动进行watchEffect 能够显示的调用返回值实现:进行侦听let age = ref(5);setTimeout(() => { age.value = 6;}, 1000);setTimeout(() => { stopHandler(); // 进行侦听}, 1500);/* 因为在1500ms时显示的进行了侦听, 故不会监测到该值的变动,然而(该值实际上被更新了,只是watchEffect没有持续侦听而已) */setTimeout(() => { age.value = 7;}, 2000);let stopHandler = watchEffect(() => { console.log('age的值', age.value);});// 打印后果: 5 6四 革除副作用依据官网文档介绍,革除副作用触发条件: ...

May 8, 2022 · 1 min · jiezi

关于vue.js:Vue-仔细说一说vue的插槽语法01

插槽语法有版本新旧,倡议大家看新版本的语法,不要看旧的语法,防止在语法的新旧上有混同。以下注释局部代码都应用新版语法进行演示。 首先是匿名插槽(Default slot)和具名插槽(Named slots)。 这里补充我来定义两个名词,不便后文阐明。1、散发处 - 散发处留空,期待内容填入。2、应用处 - 在应用处搁置text / html,应用处的内容会填充到散发处。 匿名插槽(Default slot) 若只须要一个散发处,这个时候能够用匿名插槽。匿名插槽,就是默认插槽,应用处的内容都会搁置在这个默认插槽的地位。 那么能够间接在模板内(Panel.vue中)增加一个<slot></slot>标签( <slot>标签是散发的入口)。↓ Panel.vue <template id='panel'> <div class="panel"> <div class="title"> 题目 </div> <div class="content"> <slot></slot> (匿名插槽,散发处) </div> <div class="footer"> 更多信息 </div> </div></template>这样即可。 应用时,在组件标签内( <Panel> ..这里.. </Panel> )中间接输出须要插入的内容。 <div id="app"> <Panel> hello slot (这里是应用处) </Panel></div>hello slot就会呈现在下面散发处的地位。留神:<slot> 标签在html中不存在。 具名插槽(Named slots) 如果有多个散发处(要留出多个地位来搁置内容),这时就要辨别各个散发处的名称(给插槽加个名字),这时候就须要具名插槽了。 具体做法是能够在模板内(Panel.vue中)退出solt标签  并给它一个name属性。↓ Panel.vue <template id='panel'> <div class="panel"> <div class="title"> <slot name='s1'></slot> </div> <div class="content"> <slot name='s2'></slot> </div> <div class="footer"> <slot name='s3'>我是默认值</slot> // 散发处的默认值 </div> </div></template>应用时,在组件标签内( <Panel> </Panel> ) 中须要应用插槽的标签上加上slot属性。slot属性所在的标签能够是<div> <template> 等,这个标签用什么没有要求。slot属性的值,要和散发处<slot>标签的name属性对应的值雷同 ("s1", "s2", "s3"),这里是散发处的标识,让vue晓得上面的内容要搁置在哪个散发处的地位。 ...

May 6, 2022 · 1 min · jiezi

关于vue.js:前端-一键换色-的几种方案

当初越来越多的网站都提供了更换主题性能,如ElementUI,既是为了投合用户需要,或是为了凸显本人特点,因而提供了个性化定制性能。 最近刚好做了这个性能,次要通过以下几种形式实现: CSS款式笼罩 外围通过切换CSS选择器得形式实现主题款式的切换: 1.在组件中保留不变的款式,将须要变动的款式进行抽离 2.提供多种款式,给不同的主题定义一个对应的CSS选择器3.依据不同主题设置不同的款式 实现 上面通过vuex存储和管制全局的主色彩,其代码如下: 在template模板中通过vuex中的主题设置对应类名,如头部代码如下: 上面theme.css中通过 .light 和 .dark 两个类选择器来辨别亮堂主题和光明主题,并且当时筹备了它们对应的款式,如下: 毛病 1.多种主题款式都要引入,导致代码量增大2.款式不易治理3.查找款式简单4.开发效率低5.拓展性差… 实现多套CSS款式 外围 实现多套CSS主题款式,依据用户切换操作,通过 link 标签动静加载不同的主题款式,次要解决了多个主题色被编译到一个文件中导致单个文件过大。 实现 css局部间接拆分成 light.css 和 dark.css 两个文件: 设置主题局部的 setTheme.js 代码如下: 毛病 1.须要反复CV多份款式文件进行独自批改2.没有独自提取出可变的款式局部3.须要提前晓得打包后的文件门路,否则可能导致主题款式引入谬误… CSS变量实现外围 通过body.style.setProperty(key, value) 动静批改 body 上的CSS变量,使得页面上的其它局部能够利用最新的CSS变量对应的款式。 实现 theme.css 中负责定义全局CSS变量,代码如下: 通过var() 在组件中利用对应CSS变量,比方在头部中的应用: 实现了后面的内容之后,当初别离给 light 和 dark 主题增加图片 最初 以上就是目前理解到得一些更换主题得计划,全副基于CSS去实现的,不过晓得了原理就能够联合less 和 sass 进行更好的实现。如果有更好的计划,欢送分享! 如果你感觉这篇文章对你有点用的话,麻烦请给咱们的开源我的项目点点star:http://github.crmeb.net/u/defu不胜感激 ! 收费获取源码地址:http://www.crmeb.com PHP学习手册:https://doc.crmeb.com 技术交换论坛:https://q.crmeb.com

May 6, 2022 · 1 min · jiezi

关于vue.js:vue3使用elementplus中的自定义指令-clickOutside解决点击外部自动收起的需求

解决点击红色框框里面局部主动收起的需要 vue3.0中应用ClickOutside 1、从elemtn-plus中导入ClickOutside指令 import { ClickOutside as vClickOutside } from 'element-plus' 2、从元素上绑定对应的指令 v-click-outside= "onClickOutside" 3、onClickOutside绑定对应的办法 vue2.01、导入指令 import { ClickOutside } from 'element-plus' 2、映射该指令 directives:{ ClickOutside} 3、在元素上绑定该指令 v-clickOutside="handleClickOutside" 4、在函数中调用该办法 function handleClickOutside(){}

May 5, 2022 · 1 min · jiezi

关于vue.js:Vuejs-3x-中跨层级组件如何传递数据

provide/inject 根本用法在 Vue.js 中,跨层级组件如果想要传递数据,咱们能够间接应用 props 来将先人组件的数据传递给子孙组件: 注:上图来自 Vue.js 官网:Prop Drilling。如上图所示,两头组件 <Footer> 可能基本不须要这部分 props,但为了 <DeepChiild> 能拜访这些 props,<Footer> 还是须要定义这些 props,并将其传递上来。 有人说咱们能够应用 $attrs/$listeners,但仍然还要通过两头层级,而应用 Vuex 又过于麻烦,Event Bus 又很容易导致逻辑扩散,呈现问题后难以定位。 那么,有没有其余办法能够实现间接从先人组件传递数据给子孙组件呢?答案就是 provide/inject。 先人组件: // Root.vue<script setup>import { provide } from 'vue'provide('msg' /* 注入的键名 */ , 'Vue.js' /* 值 */)</script>子孙组件: // DeepChild.vue<script setup>import { inject } from 'vue' const msg = inject('msg' /* 注入的键名 */, 'World' /* 默认值 */)</script>具体用法详见:Provide / Inject。 当初,问题解决了: 注:上图来自 Vue.js 官网:Prop Drilling。provide 实现原理这么神奇的货色,到底是如何实现的呢? ...

May 5, 2022 · 2 min · jiezi

关于vue.js:虚拟列表组件

<script>export default { name: "VirtualList", props: { templateRender: Function,list: { type: Array, default: () => [],},remainList: { type: Array, default: () => [],},itemHeight: { type: Number, default: 34,},wrapHeight: { type: Number, default: 262,},group: { type: Number, default: 1,},}, data() { return { pointer: 0, translateY: 0,};}, watch: { remainList: { handler(v) { this.translateY = v.length * this.itemHeight; let scrollTop = this.$refs["virtual-list-wrapper"]?.scrollTop; if (scrollTop !== undefined) { this.handleScroll({ srcElement: { scrollTop, }, }); } }, immediate: true,},}, computed: { ...

May 4, 2022 · 2 min · jiezi

关于vue.js:Vue3生命周期

vue3 生命周期钩子官网文档 上面总结下几个罕用的生命周期钩子执行程序 一 单个组件生命周期钩子执行程序 <template> <div>{{num}}</div></template><script setup lang="ts">import { ref, watchEffect, onBeforeMount, onMounted, onBeforeUpdate,onUpdated, onBeforeUnmount,onUnmounted} from 'vue';//--------------------------------let num = ref(1);setTimeout(() => { num.value += 1;}, 500);//--------------------------------watchEffect( () => { let b = num.value; console.log('welcom组件--watchEffect'); }, { // flush: 'post' flush: 'pre' // 默认此配置 });//--------------------------------onBeforeMount(() => {});onMounted(() => {});onBeforeUpdate(() => {});onUpdated(() => {});onBeforeUnmount(() => {});onUnmounted(() => {});</script>二 父子组件生命周期钩子执行程序

May 3, 2022 · 1 min · jiezi