关于vue.js:从零搭建webpack

webpackwebpack_ 是一个古代 JavaScript 应用程序的_动态模块打包器(module bundler)_。当 webpack 解决应用程序时,它会递归地构建一个_依赖关系图(dependency graph)_,其中蕴含应用程序须要的每个模块,而后将所有这些模块打包成一个或多个 _bundle_。 一.装置webpacknpm init -y初始化我的项目npm i webpack@4.43.0 webpack-cli@3.3.12 webpack-dev-server@3.11.0 -D这里我指定了版本号 因为他们三个是须要相互依赖的,版本不对启动时会报错 二.配置的前置条件 一.新建build文件夹build webpack.base.js //兼容开发环境和生产环境的配置webpack.prod.js //生产环境的配置webpack.dev.js //开发环境的配置二.在根目录新建src文件夹src index//主入口文件,相当于vue中的main.js三.配置package.json新增scripts配置 "scripts": { "dev": "webpack-dev-server --env=dev --config build/webpack.base.js", "build": "webpack --env=prod --config build/webpack.base.js"}dev的配置 webpack-dev-server:应用下面咱们装置的webpack-dev-server插件帮咱们本人起一个服务--env是前面用来辨别环境的标识--config build/webpack.base.js:是运行此命令时启动该文件prod的配置 webpack:打包命令前面两个与dev的配置雷同三.配置进口入口及依据执行的命令合并webpack.base.js let dev = require('./webpack.dev');//引入开发环境配置let prod = require('./webpack.prod');//引入生产环境配置let {resolve} = require('path');//应用path.resolve将门路解析成绝对路径let {merge} = require('webpack-merge');//执行npm i webpack-merge -D装置合并文件的插件module.exports = (env) => {//env为下面设置的--env=xxx let isDev = env === 'dev' ? true : false;//判断如果是开发环境则返回true否则返回false let base = {//配置兼容开发和生产 entry: resolve(__dirname, '../src/index.js'),//入口文件 output: {//进口文件 filename: 'bundle.js',//生成的js文件名 path: resolve(__dirname, '../dist')//生成在哪个目录下 } } isDev ? merge(base, dev) : merge(base, prod);//依照传进来的参数进行合并}webpack.dev.js ...

December 7, 2020 · 2 min · jiezi

关于vue.js:翻译-JavaScript-Everywhere第18章-带Electron的桌面应用程序

翻译 | 《JavaScript Everywhere》第18章 带Electron的桌面应用程序 写在最后面大家好呀,我是毛小悠,是一位前端开发工程师。正在翻译一本英文技术书籍。 为了进步大家的浏览体验,对语句的构造和内容略有调整。如果发现本文中有存在瑕疵的中央,或者你有任何意见或者倡议,能够在评论区留言,或者加我的微信:code_maomao,欢送互相沟通交流学习。 (゚∀゚)..:*☆哎哟不错哦 第18章 带Electron的桌面应用程序我第一次接触集体计算机是在一个充斥Apple II机器的学校实验室中进行的。 每周一次,我和我的同学被老师带进教室,给了一些软盘,并给出了无关如何加载应用程序(通常是Oregon Trail)的粗略阐明。在这些课程上,除了记得本人发愣之外,我对其余事件记不清了。自1980年代中期以来,集体计算机曾经走了很长一段路,然而咱们依然须要依附桌面应用程序来执行许多工作。 通常,我可能会拜访电子邮件客户端、文本编辑器、聊天客户端、电子表格软件、音乐流服务以及其余多个桌面应用程序。个别,这些应用程序具备与Web应用程序等效的性能,然而桌面应用程序的便利性和集成性能够为用户带来很多益处。然而,多年来,创立这些应用程序的能力始终十分不足。值得庆幸的是,明天,咱们可能应用网络技术来构建性能全面的桌面应用程序,而且学习曲线很小。 咱们正在构建什么在接下来的几章中,咱们将为Notedly的社交笔记应用程序构建一个桌面客户端。咱们的指标是应用JavaScript和Web技术来开发桌面应用程序,用户能够下载并装置在计算机上。目前,该应用程序将是一个简略的实现,它将咱们的Web应用程序包装在桌面应用程序shell中。以这种形式开发咱们的应用程序将使咱们可能疾速将桌面应用程序发送给感兴趣的用户,同时为咱们提供了当前为桌面用户引入自定义应用程序的灵活性。 咱们将如何构建它要构建咱们的应用程序,咱们将应用Electron,它是一个凋谢源代码的框架,用于应用Web技术构建跨平台的桌面应用程序。它能够利用Node.js和Chrome的根底浏览器引擎Chromium来工作。 这意味着作为开发人员,咱们能够应用浏览器、Node.js和特定于操作系统的性能,而这些性能通常在Web环境中不可用。Electron最后是由GitHub为Atom文本编辑器开发的,但尔后始终用作大小应用程序的平台,包含Slack,VS Code,Discord和WordPress Desktop。 入门在开始开发之前,咱们须要将我的项目启动程序文件复制到咱们的电脑上。 我的项目的源代码蕴含了开发应用程序所需的所有脚本和对第三方库的援用。 要将代码克隆到咱们的本地计算机,请关上终端,切换到保留我的项目的目录,而后git clone我的项目存储库。如果你曾经钻研过API和Web章节,则可能曾经创立了一个 notedly目录来放弃我的项目代码的有条理: $ cd Projects$ # type the `mkdir notedly` command if you don't yet have a notedly directory$ cd notedly$ git clone git@github.com:javascripteverywhere/desktop.git$ cd desktop$ npm install装置第三方依赖项通过制作本书的入门代码的正本,并在目录中运行npm install,你无需为任何第三方依赖项再次运行npm install。 该代码的构造如下: /src这是你随书一起进行开发的目录。 /solutions该目录蕴含每章的解决方案。如果你卡住了,这些能够供你参考。 /final该目录蕴含最终的工作我的项目。 创立我的项目目录并装置依赖项之后,咱们就能够开始开发了。 咱们的第一个电子应用程序将咱们的代码存储库克隆到咱们的电脑后,让咱们开发咱们的第一个Electron应用程序。如果你在src目录中查找,则会看到其中有一些文件。index.html文件蕴含了HTML标记。目前,该文件将用作Electron的“渲染器过程”,这意味着它将是咱们Electron应用程序显示为窗口的网页。 <!DOCTYPE html><html><head><meta charset="UTF-8"><title>Notedly Desktop</title></head><body><h1>Hello World!</h1></body></html>咱们将在index.js文件中设置咱们的Electron应用程序。在咱们的应用程序中,该文件将蕴含Electron所谓的“主过程”,它定义了应用程序shell。次要过程通过在Electron中创立一个BrowserWindow实例来工作,该实例用作应用程序shell。 index.js与main.js在咱们的案例利用中的其余局部都是用的index.js命名,然而通常在软件开发中命名main.js来命名“主程序”。让咱们设置次要过程以显示蕴含HTML页面的浏览器窗口。首先,导入Electron的应用程序,而后写src/index.js中的browserWindow性能: const { app, BrowserWindow } = require('electron');当初,咱们能够定义应用程序的browserWindow并定义应用程序将加载的文件。在src/index.js中,增加以下内容: ...

December 6, 2020 · 2 min · jiezi

关于vue.js:Vuejs中的keepalive组件

<keep-alive></keep-alive>,个别用来包裹动静组件,能够使被蕴含的租组件保留状态,防止被从新渲染。 当在组件之间来回切换到时候,它会缓存不流动的组件实例,而不是执行组件的申明周期的destroyed钩子函数销毁组件。 keep-alive有两个属性,exclude和include,蕴含或者不蕴含该组件,而后对其进行相应的缓存操作。 当组件在<keep-alive></keep-alive>中被切换时,有activated和deactivated两个生命周期钩子函数被对应的执行。 比方说:当咱们想要下次回到这个页面的时候,还是让其放弃来到时候的状态,如下拉的高度就是一个能够被保留的状态。咱们就能够调用其两个钩子函数,对滚动的高度进行记录和缓存,确保下次回来时,还是在以后的高度。在来到的时候,在deactivated中保留间隔视口顶部的高度;在回来的时候,在activated中,让其通过短暂的提早之后(大略50ms),还是在来到时记录的那个地位的高度。

December 5, 2020 · 1 min · jiezi

关于vue.js:Vue源码研究

写在后面最近新部门的 React 我的项目要做多环境部署,参考了一下之前部门做的 Vue 我的项目,顺便把 vue-cli-service 的源码看了一下。看源码的时候还去看了下 Vue 源码,感觉挺有意思的,打算好好钻研下,这里继续更新自己的心得体会~ vue-cli-service多环境首先在 package.json 外面 script 上面增加如下内容: "scripts": { "serve": "vue-cli-service serve", "serve:staging": "vue-cli-service serve --mode staging", "serve:prod": "vue-cli-service serve --mode production", "lint": "vue-cli-service lint", "format": "vue-cli-service lint --formatter", "inspect": "vue-cli-service inspect", "build": "vue-cli-service build", "build:staging": "vue-cli-service build --mode staging", "build:prod": "vue-cli-service build --mode production"},vue-cli-service 源码在 node_modules/@vue/cli-service/bin/vue-cli-service.js 目录下 vue-cli-service.js 在第 14 行加载了 ../lib/Service.js 模块,这个模块在 151 行加载了 serve.js 模块 serve.js 在 node_modules/@vue/cli-service/lib/commands/serve.js 目录下 ...

December 4, 2020 · 1 min · jiezi

关于vue.js:Vuejs中的vfor为什么要用key

在之前的vue中v-for不绑定key不会报错,当初的vue中在编写的过程中如果不绑定key是会报错的。(当然这个起因并不足以压服我不加key) v-for个别用在列表的渲染,渲染的时候会默认恪守就地复用策略。 就地复用策略:当在进行列表渲染的时候,vue会间接对已有的标签进行复用,不会整个的将所以的标签全副删除和创立,只会从新渲染数据,而后再创立新的元素直到数据渲染完为止。key属性能够用来晋升v-for渲染DOM的效率。key属性必须是惟一不变的值(惟一标识),防止数据凌乱的状况的呈现。 加了key之后,vue能够辨认每组节点。如果节点之间内容统一,只是程序发生变化,那么就没有必要进行减少删除操作了,而是间接进行程序的更改即可。大大晋升效率。 这里我倡议应用id,如果没有id的情乱下应用index(下标),然而尽量不要用index,因为如果有元素被删除,就会导致index变动,从而会导致数据的凌乱。

December 4, 2020 · 1 min · jiezi

关于vue.js:Vue的computed可以修改自身的值吗

我的项目中有一个输入框的值content须要同时依赖四个变量data1, data2, data3, data4, 同时还要实现双向绑定。 <textarea rows="4" v-model="content" placeholder="形容"/>一开始我把content的赋值写在办法中,然而随着逻辑的减少,四个变量扭转时都要为content赋值,代码就变得很反复。 于是我试着把content写在computed中,发现在输入框中输入框中批改值时,界面上能够变动,然而用vue dev tools能够看到,this.content的值并没有发生变化。Vue官网文档指出,计算属性是基于它们的响应式依赖进行缓存的。只在相干响应式依赖产生扭转时它们才会从新求值。 然而computed中的值咱们能够给它一个setter属性。本认为设置setter就能够间接扭转原变量了,后果并没有扭转,官网文档给出的setter也都是扭转其余变量的值。 最初想了一个变通的办法,我在data中申明了另一个content1,当输入框发生变化时,会触发计算属性的setter,从而扭转content1的值。 残缺代码如下: <textarea rows="4" v-model="content" placeholder="形容"/> data() { return { data1: '', data2: '', data3: '', data4: '', content1: '' } }, computed: { content: { get: function() { let val = `${this.data1}${this.data2}${this.data3}${this.data4}` this.content1 = val return val }, set: function(v) { this.content1 = v return v } } },

December 4, 2020 · 1 min · jiezi

关于vue.js:用vue一分钟快速实现一个可视化编辑器流程图拓扑图web组态SCADA

视频教程: https://www.bilibili.com/vide... 装置topology-vue $ npm install topology-vue# OR$ yarn add topology-vue应用组件1. 导入组件Typescript应用形式 https://github.com/le5le-com/... <template> <div class="home"> <topology /> </div></template><script lang="ts">import { Component, Vue } from 'vue-property-decorator';import topology from 'topology-vue';import 'topology-vue/topology-vue.css';@Component({ components: { topology, },})export default class Home extends Vue {}</script><style lang="scss">.home { height: calc(100vh - 80px);}</style>JavaScript应用形式 https://github.com/le5le-com/... <template> <div class="home"> <!-- 应用topology组件 --> <topology /> </div></template><script>// 导入topology-vue组件import topology from "topology-vue";// 须要导入topology-vue.cssimport "topology-vue/topology-vue.css";export default { name: "Home", components: { topology, },};</script><style lang="scss">.home { height: 100vh;}</style>2. 加载相干字体文件<!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"> <link rel="icon" href="<%= BASE_URL %>favicon.ico"> <!-- 通用字体图标 --> <link href="//at.alicdn.com/t/font_2030495_pwo1zu1ka1.css" rel="stylesheet" /> <!-- 通用根底图形库 --> <link href="//at.alicdn.com/t/font_1331132_qhyav2o6mp.css" rel="stylesheet"/> <title><%= htmlWebpackPlugin.options.title %></title> </head> <body> <noscript> <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> </noscript> <div id="app"></div> <!-- built files will be auto injected --> <!-- 须要用到的工具js --> <script src="http://topology.le5le.com/js/canvas2svg.js"></script> <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> <script src="https://cdn.bootcss.com/jszip/3.2.2/jszip.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/echarts/4.8.0/echarts.min.js"></script> </body></html>3. 加载相干js文件<!-- 须要用到的工具js --><script src="http://topology.le5le.com/js/canvas2svg.js"></script><script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script><script src="https://cdn.bootcss.com/jszip/3.2.2/jszip.min.js"></script><script src="https://cdn.bootcdn.net/ajax/libs/echarts/4.8.0/echarts.min.js"></script>页面成果 ...

December 4, 2020 · 1 min · jiezi

关于vue.js:vue30调试工具vuedevtools在chrome不显示

官网文档强制开启办法vue-devtools// Before you create appVue.config.devtools = process.env.NODE_ENV === 'development'// After you create appwindow.__VUE_DEVTOOLS_GLOBAL_HOOK__.Vue = app.constructor// then had to add in ./store.js as well.Vue.config.devtools = process.env.NODE_ENV === 'development'这个办法应该还是vue2.0的办法 vue3.0 vue-devtoolsimport { createApp } from 'vue'import App from './App.vue'const app = createApp(App)// 分环境解决if (process.env.NODE_ENV === 'development') { if ('__VUE_DEVTOOLS_GLOBAL_HOOK__' in window) { // 这里__VUE_DEVTOOLS_GLOBAL_HOOK__.Vue赋值一个createApp实例 window.__VUE_DEVTOOLS_GLOBAL_HOOK__.Vue = app } app.config.devtools = true}app.mount('#app')这个形式与vue2.0的vue-devtools会不兼容,控制台会报错,临时敞开2.0的vue-devtools就能够调试工具显示后能够正文调这段代码,不然调试工具会多出一个vue实例 if (process.env.NODE_ENV === 'development') { // if ('__VUE_DEVTOOLS_GLOBAL_HOOK__' in window) { // window.__VUE_DEVTOOLS_GLOBAL_HOOK__.Vue = app // } app.config.devtools = true}

December 4, 2020 · 1 min · jiezi

关于vue.js:vue-使用canvas画圆弧进度条

话不多说先上效果图,合乎需要再往下看:这是参考有赞商城做的一个小性能。间接贴办法,到时候间接调用办法传值就好。 html: <canvas id="circle" class="circle-item" width="240px" height="240px"></canvas>script: mounted() { this.toCanvas("circle", 70); //第一个是id,第二个百分比(圆弧达到地位)}, toCanvas(id, progress) { //canvas进度条 var canvas = document.getElementById(id); var ctx = canvas.getContext("2d"); var percent = progress; //最终百分比 var circleX = canvas.width / 2; //核心x坐标 var circleY = canvas.height / 2; //核心y坐标 var radius = 90; //圆环半径 var lineWidth = 14; //圆形线条的宽度 //两头的字 var fontSize = 25; ctx.font = fontSize + "px April"; ctx.textAlign = "center"; ctx.fillStyle = "#000"; ctx.fillText(parseFloat(percent).toFixed(0), circleX, circleY); fontSize = 12; ctx.font = fontSize + "px April"; ctx.fillStyle = "#999"; ctx.fillText("我的成长值", circleX, circleY - 40); ctx.fillStyle = "#999"; ctx.fillText("还差20积分降级会员", circleX, circleY + 40); //画圆 function circle(cx, cy, r) { ctx.beginPath(); //ctx.moveTo(cx + r, cy); ctx.lineWidth = lineWidth; ctx.strokeStyle = "#fff"; ctx.arc(cx, cy, r, (Math.PI * 2) / 3, (Math.PI * 1) / 3); ctx.stroke(); } // 画弧线 function sector(cx, cy, r, startAngle, endAngle) { ctx.beginPath(); //ctx.moveTo(cx, cy + r); // 从圆形底部开始画 ctx.lineWidth = lineWidth; // // 渐变色 - 可自定义 // var linGrad = ctx.createLinearGradient( // circleX - radius - lineWidth, // circleY, // circleX + radius + lineWidth, // circleY // ); // linGrad.addColorStop(0.0, "#06a8f3"); // //linGrad.addColorStop(0.5, '#9bc4eb'); // linGrad.addColorStop(1.0, "#00f8bb"); ctx.strokeStyle = "red"; //圆弧两端的款式 ctx.lineCap = "round"; //圆弧 ctx.arc( cx, cy, r, (Math.PI * 2) / 3, (Math.PI * 2) / 3 + (endAngle / 100) * ((Math.PI * 5) / 3), false ); ctx.stroke(); } // 圆形 circle(circleX, circleY, radius); //圆弧 sector(circleX, circleY, radius, (Math.PI * 2) / 3, percent); },心愿能帮忙你,持续致力加油鸭!! ...

December 4, 2020 · 2 min · jiezi

关于vue.js:2020-年我与技术面试那些事儿

前言2020年,是个不平庸的一年,因为疫情的蔓延打乱了我的全盘打算。但在工作中,实现了指标我的项目、攻克了技术难关、学习了新的技术,也感激平台! 首先上来就是给一个思维导图分享: 思维导图微信Web开发者工具小程序开发环境,相干工具小程序组件小程序/小游戏开发接口开发接口凋谢能力小程序媒体原生能力小程序原生能力小程序设施原生能力小程序设施原生能力小程序界面/图形原生能力小程序界面/图形原生能力小程序界面/图形原生能力 说说我做为前端开发工程师为啥学习云开发呢?因为云开发(Tencent CloudBase,TCB)是云端一体化的后端云服务 ,采纳 serverless 架构,免去了挪动利用构建中繁琐的服务器搭建和运维。同时云开发提供的动态托管、命令行工具(CLI)、Flutter SDK 等能力极大的升高了利用开发的门槛。应用云开发能够疾速构建残缺的小程序/小游戏、H5、Web、挪动 App 等利用。 对于小程序开发,大家对其生命周期函数大都小白都是蒙蒙的,所以我讲一下:小程序注册实现后,加载页面,触发onLoad办法。页面载入后触发onShow办法,显示页面。首先显示页面,会触发onReady办法,渲染页面元素和款式,一个页面只调用一次。当小程序后盾运行或跳转到其余页面时,触发onHide办法。当小程序有后盾进入到前台运行或从新进入页面时,触发onShow办法。当应用重定向办法wx.redirectTo(OBJECT)或敞开当前页返回上一页wx.navigateBack(),触发onUnload。 在开始小程序开发之前,须要注册小程序账号、私有云账号,购买云服务器、域名、申请SSL证书,还须要相干的配置,SSH连贯服务器、装置NodeJS、装置Nginx、装置MySQL、装置MySQL、导入SSL证书、测试Nginx、域名备案,才能够进行开发。 上面针对前端工程师的知识点开展介绍:务必把握HTML(标签,属性,语义化)等。务必把握CSS(文档流,盒模型,浮动,定位,继承,浏览器兼容性)等。务必把握HTML5(新增的标签属性,以及外围JavaScript API)等。务必把握CSS3(新增的属性,媒体查问,布局,动画)等。务必把握Bootstrap(款式,组件)等。务必把握JavaScript(ECMAScript核心技术,DOM相干技术,前端常见算法)等。务必把握jQuery等相干技术。务必把握挪动端相干问题。务必把握开发兼容浏览器代码等问题。务必把握面向对象等问题,如(面向对象编程中的类,继承等)。务必把握Ajax与JSON等。务必把握HTTP和HTTPS等。务必把握Node.js(开发服务器端开发)等。务必把握EMAScript5 和 EMAScript6 ,设计模式(工作中)等。务必把握Vue.js(框架,插件),Angular(框架,插件),React(框架,插件)等。务必把握游戏开发相干问题,网络安全相干问题,性能优化相干问题,模块化开发相干问题,CSS预编译相干问题,混合开发相干问题,前端工程化问题(前端工程化工具 WebPack,gulp)等。务必把握版本管理工具(Git,SVN),测试相干问题。针对公司面试官,会针对某一个问题,对面试者提出问题(若简历里没有对我的项目作出具体介绍即会开展对技术知识点的解答) 上面技术总结HTML:标签要闭合,英文要小写,不要嵌套凌乱,用标签语义化来进步搜寻的概率,应用外链式的CSS和JS。(使构造,款式,行为拆散,内容可能被更多的设施拜访,代码简洁,开发组件化,代码易保护,可复用等)。2.HTML是一种基于web网页的设计语言;XHTML是一种基于XML,语法严格,规范的设计语言。(不同:XHTML元素必须正确嵌套,元素必须敞开,标签必须小写,必须有根元素;HTML没有限度) 3.严格模式是 浏览器依照 web规范去解析页面的办法;混淆模式是一种向后兼容的解析办法。 (触发严格模式或者规范模式,就是在HTML标签前申明正确的DTD;触发混淆模式能够在HTML文档开始时不申明DTD,或者在DOCTYPE前退出XML申明) 4.动态网页是没有数据交互的网页(没有数据库参加,没有服务器数据的加载)。如动态网页只有(HTML+CSS+JavaScript);动静网页是有后盾数据参加的网页。(有动画的网页就是动静网页是谬误的认知) 5.DOCTYPE申明位于文档中的最后面,位于html标签前,通知浏览器的解析器用什么文档类型标准来解析这个文档。DOCTYPE不存在或格局不正确都会导致文档以混淆模式来出现。 严格模式下以浏览器反对的 最高规范来运行的,在混淆模式中,以向后兼容的形式来显示。 6.HTML语义化让页面的内容变得 结构化,便于浏览器解析和搜索引擎解析,进步代码的可保护度和可重用性。 7.锚点的应用形式: id="" name="" <a href="#dadaqianduan">dadaqianduan</a>8.构造标签: <header>用于定义文档的页眉<nav>用于定义页面的导航链接局部。<section>用于定义文档中的节,示意文档中一个具体的组成部分。<article>用于定义独立于文档其余局部的内容。<footer>用于定义某区域的脚注信息。<aside>用于定义页面的一些额定组成部分。<a href="mailo:2xxx@qq.com><a href="javascript:void(0);">超级链接用于创立一般超级链接,下载链接,电子邮件链接,分割咱们链接,空链接,锚点跳转,特定的代码性能。9.IE的内核Trident;Firefox的内核(Gecko,Chrome,Safari(Webkit)... 10.div为网站布局的盒子标签,之前应用table布局会让网站加载慢,布局层级不清晰。 11.img标签上的title是为提供题目信息,当光标悬浮在标签上后显示的信息,而alt是当图片不能失常显示时,图片的替换文案。 12.上面空元素有: <br> <hr> <img> <input> <link> <meta>13.src示意起源地址(示意引入),href示意超文本援用。 14.在新窗口关上链接的形式: target=_blank15.HTML是网页内容的载体;CSS是网页内容的体现;JavaScript是用来实现网页上的特效和交互。 16.应用iframe,能够解决加载迟缓的第三方内容,能够实现平安沙箱,能够并行加载脚本。然而应用iframe会阻塞主页面的Onload事件。iframe的内容即便是空的,加载它也是须要工夫的,iframe元素是没有语义的。 17.面试问考你对语义化的了解。 首先就是失落款式的时候,也可能让页面呈现出清晰的构造;有助于SEO进行抓取更多无效的音讯,语义化更具备可读性。 上面技术总结CSS:1.css 根本选择器有:类选择器,属性选择器,ID选择器。CSS选择器的权重分 4 个等级,其中 !important 关键字优先级最高。 能够用0.0.0.0来示意 4 个等级: 内联款式的优先级为: 1.0.0.0 ID选择器的优先级为: 0.1.0.0 类属性选择器,属性选择器,伪类的优先级为:0.0.1.0 元素选择器,伪元素选择器的优先级为 0.0.0.1 通配符组合应用的时候,相应的层级权重也会减少 ...

December 4, 2020 · 1 min · jiezi

关于vue.js:面试官Vue组件间通信方式都有哪些

一、组件间通信的概念开始之前,咱们把组件间通信这个词进行拆分 组件通信都晓得组件是vue最弱小的性能之一,vue中每一个.vue咱们都能够视之为一个组件 通信指的是发送者通过某种媒体以某种格局来传递信息到收信者以达到某个目标。狭义上,任何信息的交通都是通信 组件间通信即指组件(.vue)通过某种形式来传递信息以达到某个目标 举个栗子 咱们在应用UI框架中的table组件,可能会往table组件中传入某些数据,这个实质就造成了组件之间的通信 二、组件间通信解决了什么在现代,人们通过驿站、飞鸽传书、战火报警、符号、语言、眼神、触碰等形式进行信息传递,到了明天,随着科技程度的飞速发展,通信根本齐全利用有线或无线电实现,相继呈现了有线电话、固定电话、无线电话、手机、互联网甚至视频电话等各种通信形式 从下面这段话,咱们能够看到通信的实质是信息同步,共享 回到vue中,每个组件之间的都有单独的作用域,组件间的数据是无奈共享的 但理论开发工作中咱们经常须要让组件之间共享数据,这也是组件通信的目标 要让它们相互之间能进行通信,这样能力形成一个有机的残缺零碎 二、组件间通信的分类组件间通信的分类能够分成以下 父子组件之间的通信兄弟组件之间的通信祖孙与后辈组件之间的通信非关系组件间之间的通信关系图: ## 三、组件间通信的计划 整顿vue中8种惯例的通信计划 通过 props 传递通过 $emit 触发自定义事件应用 refEventBus$parent 或 $rootattrs 与 listenersProvide 与 InjectVuex### props传递数据 实用场景:父组件传递数据给子组件子组件设置props属性,定义接管父组件传递过去的参数父组件在应用子组件标签中通过字面量来传递值Children.vue props:{ // 字符串模式 name:String // 接管的类型参数 // 对象模式 age:{ type:Number, // 接管的类型为数值 defaule:18, // 默认值为18 require:true // age属性必须传递 }}Father.vue组件 <Children name:"jack" age=18 />### $emit触发自定义事件 实用场景:子组件传递数据给父组件子组件通过$emit触发自定义事件,$emit第二个参数为传递的数值父组件绑定监听器获取到子组件传递过去的参数Chilfen.vue this.$emit('add', good)Father.vue <Children @add="cartAdd($event)" />### ref 父组件在应用子组件的时候设置ref父组件通过设置子组件ref来获取数据父组件 <Children ref="foo" />this.$refs.foo // 获取子组件实例,通过子组件实例咱们就能拿到对应的数据### EventBus ...

December 4, 2020 · 1 min · jiezi

关于vue.js:如何使用在Vuejs中轻松构建UI组件这篇文章将告诉你答案

点击获取工具>>本文将为大家介绍如何应用Kendo UI在Vue.js中构建一个气象视图UI组件,并实现与图表组件的界面。 首先让咱们一起来理解一下背景。 什么是Kendo UI?Kendo UI是一个全面的Web用户界面框架,其中蕴含JavaScript UI组件的汇合,这些JavaScript UI组件具备jQuery库以及Vue、React和Angular等更古代的库。 Kendo UI开发人员应用大量的UI小部件和数据可视化组件来构建交互式且响应迅速的高性能应用程序。 为什么抉择Kendo UI?应用Kendo UI,您能够轻松地将真正高级的UI组件增加到您抉择库的前端我的项目中,不用放心接口的要害性能,而且能够节省时间,只需关注专有性能即可。 Kendo UI附带了易于应用的集成,反对您喜爱的每个前端Web框架(例如Vue.js)。 除根本的UI组件外,Kendo UI还为您提供了高级的数据可视化UI元素,可确保您不用向我的项目中增加其余库即可解决图表,这些高级UI元素也可自定义。 你会构建什么? 您将应用Kendo UI在Vue.js中构建气象视图UI组件,将首先应用VS Code中的Kendo UI starter扩大scaffolding,而后应用Vue Router创立路由,最初应用一些Kendo UI图表组件来构建界面。 入门指南假如您曾经装置了Vue; 如果没有,请转到装置指南。当初关上您的VS Code,要做的第一件事是装置Kendo UI模板向导扩大。您能够通过转到VS Code的扩大程序标签并搜寻 “Kendo UI Template”来实现,持续下载,重新启动VS Code之后,当初能够应用它来搭建新我的项目了。 如何应用关上VSCode在Windows / Linux中按ctrl + shift + p,在Mac中按⇧⌘P关上VSCode的扩大程序启动器输出/抉择Kendo UI Template Wizard:启动并按Enter启动扩大 您能够先抉择一个项目名称和一个文件夹来开始,单击Next时,零碎会提醒您抉择要应用的前端库,Kendo UI具备Vue、Angular和React的组件元素。 下一步是抉择新我的项目中所需的页面,对于此我的项目,您能够抉择一个带有路由的图表。抉择之后,模板向导将在后盾运行Vue create命令,并为您搭建Vue应用程序。 配置既然曾经实现了应用程序的scaffolding工作,那么您必须通过运行以下命令来确保正确装置了所有依赖项: cd newappnpm install 导航到新应用程序的根目录,并在main.js文件中,确保它看起来是这样: `import Vue from 'vue'import App from './App.vue'import router from "./router";Vue.config.productionTip = falsenew Vue({render: h => h(App),router}).$mount('#app')` ...

December 3, 2020 · 3 min · jiezi

关于vue.js:夏哥事件薄-VUE-使用-vueloader-报错及解决在vue里使用scss

之前始终应用angular写我的项目,css应用的是SCSS。 起初应用VUE写CSS,写习惯 SCSS 后总感觉不不便。但因为 VUE 自身不反对 SCSS 写法,须要装置vue-loader能力在 VUE 文件及款式文件里应用 SCSS 。于是有了这次记录。 首先 官网的介绍文档 介绍 | Vue Loadervue-loader.vuejs.org npm install -D vue-loader vue-template-compiler npm install -D sass-loader node-sass 我没有 webpack.config.js 这个文件,只有三个文件 所以在 webpack.base.conf.js 内进行批改。 //base是另外两个的公共js,所以在这里批改。rules 里的代码换成这段 { test: /.sass$/, use: [ 'vue-style-loader', 'css-loader', { loader: 'sass-loader', options: { indentedSyntax: true, // sass-loader version >= 8 sassOptions: { indentedSyntax: true } } } ]}接着npm run dev 运行代码就会报 ...

December 3, 2020 · 1 min · jiezi

关于vue.js:Vue-快速入门

Vue 即 Vue.js,它是风行的前端开发框架,目前曾经倒退成为优良的前端生态。 学习 Vue 之前,须要具备:HTML, CSS, JavaScript 基础知识,最好还领有应用这些技术开发过网站的教训。如果不相熟 JavaScript,基本上无奈了解 Vue.js。所以读者敌人,请依据本人的状况,做好学习 Vue.js 的筹备工作吧。 一旦具备基础知识后,便开始搭建环境,一边应用一边学习。 毫无疑问,一边入手一边看书,是把握一门利用技能的最佳办法。 装置针对于小型我的项目,只需将 Vue.js 库用于援用到我的项目中即可。针对于大型项目,官网倡议应用 NPM 装置 Vue.js 以及配套的各种扩大工具。 援用上面是官网提供的可供援用的办法: #测试环境<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>#生产环境-指定版本<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>#原生 ES Modules 环境<script type="module"> import Vue from https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.esm.browser.js'</script>装置NPM 是 JS/Node 的一个包管理工具,Vue 配套工具利用 NPM 装置其余相干的 JS 包到本地我的项目。 上面列出从零开始的 Vue 装置过程: #装置 Node 版本管理工具 [nvm](https://github.com/nvm-sh/nvm)curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash#装置最新版 Nodenvm install node#装置原理想做到把握 Vue 的实质,须要牢牢记住如下几个要点: 虚构DOM虚构 DOM 即虚构进去的 DOM 元素,并不需要提前在 HTML 节点树中定义。而是先充沛把虚构 DOM 想做的事件“构建”进去,再挂载到实在的 HTML 构造中,这样便实现了所谓的前端的MVC化。 ...

December 2, 2020 · 2 min · jiezi

关于vue.js:vue组件注册省去import

首先咱们在vue的应用中,免不了会本人自定义组件,那么咱们每次定义好组件都会先import 进来,而后在components外面引入能力用复现以下场景 import BaseButton from './baseButton'import BaseIcon from './baseIcon'import BaseInput from './baseInput'export default { components: { BaseButton, BaseIcon, BaseInput }}<BaseInput v-model="searchText" @keydown.enter="search"/><BaseButton @click="search"> <BaseIcon name="search"/></BaseButton>咱们平时是不是都是这么写?集体感觉太麻烦了,秉持着能偷懒就偷懒的准则,咱就配置一次,再也不必import引入就间接能用多好啊,好消息,好消息!是能够实现的: 咱们须要借助一下神器webpack,应用 require.context() 办法来创立本人的(模块)上下文,从而实现主动动静require组件。这个办法须要3个参数:要搜寻的文件夹目录,是否还应该搜寻它的子目录,以及一个匹配文件的正则表达式。咱们在components文件夹增加一个叫global.js的文件,在这个文件里借助webpack动静将须要的根底组件通通打包进来。当然了要依据不同的目录构造进行不同的解决如果你是这样的目录构造 那么 global.js 就能够这么写 import Vue from 'vue'function capitalizeFirstLetter(string) { return string.charAt(0).toUpperCase() + string.slice(1)}const requireComponent = require.context( '.', false, /\.vue$/ //找到components文件夹下以.vue命名的文件)requireComponent.keys().forEach(fileName => { const componentConfig = requireComponent(fileName) const componentName = capitalizeFirstLetter( fileName.replace(/^\.\//, '').replace(/\.\w+$/, '') //因为失去的filename格局是: './dataList.vue', 所以这里咱们去掉头和尾,只保留真正的文件名 ) Vue.component(componentName, componentConfig.default || componentConfig)})如果你是以上的目录构造,以上代码就能够满足你了 ...

December 2, 2020 · 1 min · jiezi

关于vue.js:vue组件input字数限定

Vue.component('input-len-control', { template: ` <div class="input-control-wrapper"> <input type="text" v-model="input" @input="inputControl($event.target.value)" :placeholder="placeholder"> <span class="control">{{curLen}}/{{maxLen}}</span> </div> `, data() { return { curLen: 0, // 以后input值的长度 input: '' } }, // 父子组件双向绑定 model: { prop: 'inputValue', event: 'change' }, props: { maxLen: { type: Number, default: 16 }, placeholder: String, inputValue: { type: String, default: '' } }, watch: { // 初始化时携带默认值 inputValue: { handler(val) { const { returnStr, len } = getTagLen(val, this.maxLen) this.curLen = len this.input = returnStr }, immediate: true } }, mounted() { }, methods: { inputControl(val) { const { returnStr, len } = getTagLen(val) this.curLen = len this.input = returnStr this.$emit('change', returnStr) } }})function getTagLen(str, maxLen) { let reg = /^[\u4e00-\u9fa5]{0,}$/; let len = 0; let returnStr = ""; if (str === "") { return { returnStr, len } } str = str.split(''); for (let i = 0; i < str.length; i++) { if (reg.test(str[i])) { if (len >= maxLen -1) break; len += 2; } else { len++; } returnStr += str[i]; if (len >= maxLen) break; } return { returnStr, len }}根本款式 ...

December 2, 2020 · 2 min · jiezi

关于vue.js:vue项目中配置文件不打包

在开发中有一个性能,须要写一个公共配置文件且我的项目打包后能够随时更改配置文件内容,上面看代码:1.在static文件夹中新建一个文件名为projectConfig.js的文件 var projectConfig = { // projectTitToggle : 'XX零碎1' projectTitToggle : 'XX零碎2'}2.在根目录下的index.html文件中引入下面创立的配置文件 <script src="./static/projectTitle.js"></script>3.利用时可间接用projectConfig.projectTitToggle来拿到值。

December 2, 2020 · 1 min · jiezi

关于vue.js:vueelementUIeltable-数据导出Excel

1. 装置依赖//xlsx 与 file-saver依赖npm install --save xlsx file-saver`https://github.com/SheetJS/js-xlsx https://github.com/eligrey/FileSaver.js 2.在须要的组件中引入import FileSaver from 'file-saver'import XLSX from 'xlsx'3. .vue:<el-table :data="checkOrderList" border id="out-table">//表格内容</el-table><el-button type="primary" @click="exportExcel">点击导出</el-button>4.methods中引入办法exportExcel (id,title) { /* generate workbook object from table */ var wb = XLSX.utils.table_to_book(document.querySelector(#out-table)) /* get binary string as output */ var wbout = XLSX.write(wb, { bookType: 'xlsx', bookSST: true, type: 'array' }) try { FileSaver.saveAs(new Blob([wbout], { type: 'application/octet-stream' }), title+'.xlsx') } catch (e) { if (typeof console !== 'undefined') console.log(e, wbout) } return wbout}到这表格就能够导出了 ...

December 1, 2020 · 1 min · jiezi

关于vue.js:引入swiper出现not-scoped-to-the-toplevel-root-element-警告

我的项目中引入swiper运行后发现控制台呈现很多相似于上面的正告 warning in ./node_modules/swiper/css/swiper.cssModule Warning (from ./node_modules/postcss-loader/src/index.js):Warning(429:3) Custom property ignored: not scoped to the top-level :root element (.swiper-lazy-preloader-black { ... --swiper-preloader-color: ... }) @ ./node_modules/swiper/css/swiper.css 4:14-135 14:3-18:5 15:22-143 @ ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/payment/pay.vue?vue&type=script&lang=js& @ ./src/views/payment/pay.vue?vue&type=script&lang=js& @ ./src/views/payment/pay.vue @ ./src/router/payment/index.js @ ./src/router sync index\.js$ @ ./src/router/index.js @ ./src/main.js @ multi (webpack)-dev-server/client?http://10.26.155.86:8080/sockjs-node (webpack)/hot/dev-server.js ./src/main.js 从正告中能够看出跟我的项目里应用了postcss-loader有关系, 解决方案:找到我的项目 postcss.config.js文件,疏忽Custom property即可。 module.exports = { plugins: { 'postcss-cssnext': { features: { customProperties: false } }, }};

December 1, 2020 · 1 min · jiezi

关于vue.js:????????????周范围选择器它来了基于-elementui-2x-改造开发

成果先来看一下效果图 预览地址 github地址 npm地址 需要现有我的项目需要,须要用到周范畴选择器这性能,但没找到相应的组件库,故本人基于element-ui的 el-datepicker 革新开发了个。 应用 <date-week-range v-model="test" ... > </date-week-range>现状代码绝对简陋;npm包过于大;暂不反对vue 3 配置组件配置和 element-ui 中的DatePicker组件 type="daterange" 配置雷同,缩小了学习的老本。 issue and pr's welcome欢送来issue和pr哦 github地址

December 1, 2020 · 1 min · jiezi

关于vue.js:vue项目实用方法

目录阐明|-- public|-- src 我的项目开发目录 |-- api 接口目录 |-- request.js |-- api.js 接口 |-- assets 动态文件 |-- image |-- css |-- _variables.scss 全局sass变量定义文件 |-- js |-- config.js 全局js变量定义文件 |-- fieldParam.js 自定字段 |-- components 组件寄存目录 |-- i18n 国际化 |-- router router |-- meta.js route的配置文件 |-- store vuex |-- utils 自定工具 |-- views 视图目录 |-- App.vue 主入口 |-- main.js 主入口|-- package.json 依赖库|-- package-lock.json 锁定安装包的具体版本号|-- vue.config.js vue配置文件|-- .env 环境配置|-- .env.test |-- .env.production vue.config.jslet path = require('path');let packageData = require('./package.json');let CompressionPlugin = require('compression-webpack-plugin');let timestamp = new Date().getTime();let staticDeclare = ``;let needPackage = !process.env.NODE_ENV.match('development');function resolve(dir) { return path.join(__dirname, dir)}if (needPackage) { staticDeclare = `${process.env.VUE_APP_STATIC_URL}/${process.env.VUE_APP_PACKAGE_DIR}/`;}module.exports = { publicPath: staticDeclare, // 动态资源加载的门路 outputDir: `${__dirname}/dist/${process.env.NODE_ENV}/${process.env.VUE_APP_CODE.toLowerCase()}`, // 打包的dist目录文件名 // indexPath: 'index.html', // 入口文件index.html的名字 // assetsDir: 'static', // img/fonts等不会变内容的资源的文件夹 productionSourceMap: false, chainWebpack: config => { //设置别名 config.resolve.alias .set('@', resolve('src')) }, devServer: { disableHostCheck: true, // 非localhost拜访时,绕过主机查看 host: 'dev.hostname.com', open: true, //关上浏览器窗口 proxy: { '/api/service': { target: 'http://test.hostname.com:9000', // 本地跨域拜访测试环境接口 changeOrigin: true, // 是否跨域 pathRewrite: { '/api/service': '', } }, } }, //定义scss全局变量 css: { loaderOptions: { sass: { prependData: `@import "@/assets/css/_variables.scss";` }, }, extract: { // ${staticDeclare}css/ filename: `css/[name]_${packageData.version}_${timestamp}.css`, chunkFilename: `css/[name]_${packageData.version}_${timestamp}.css` }, }, configureWebpack: () => { // 打包时压缩成gzip格局 if (needPackage) { return { plugins: [new CompressionPlugin({ test: /\.js$|\.html$|\.css/, threshold: 10240, deleteOriginalAssets: false })], output: { filename: `js/[name]_${packageData.version}_${timestamp}.js`, chunkFilename: `js/[name]_${packageData.version}_${timestamp}.js` }, // 此配置须要index.html文件配合减少引入内部框架,以减小打包的大小 externals: { 'vue': 'Vue', 'vuex': 'Vuex', 'vue-router': 'VueRouter', 'axios': 'axios', 'element-ui': 'ELEMENT' }, // externals中的key是用于import,value示意的在全局中拜访到该对象,就是window.echarts } } }}index.html<!DOCTYPE html><html lang="en"><head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="Pragma" content="no-cache"> <meta http-equiv="Cache-Control" content="no-cache"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <link rel="icon" href="<%= BASE_URL %>favicon.ico"> <title>declare</title></head><body> <noscript> <strong>We're sorry but declare doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> <strong>很道歉,如果未启用JavaScript,则网站无奈失常工作。请启用它以持续浏览。</strong> </noscript> <div id="app"></div> <!-- built files will be auto injected --> <% if (!process.env.NODE_ENV.match('development')) { %> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/vuex/3.2.0/vuex.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/vue-router/3.1.3/vue-router.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.19.2/axios.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/element-ui/2.13.1/index.js"></script> <% } %></body></html>

December 1, 2020 · 2 min · jiezi

关于vue.js:Vuejs-桌面端虚拟滚动条vue美化滚动条VScroll

介绍VScroll 一款基于vue2.x构建的桌面PC端自定义模仿滚动条组件。反对自定义是否原生滚动条、自动隐藏、滚动条大小、层级及色彩等性能。领有丝滑般的原生滚动条体验! 除了垂直滚动条,同样的也反对程度滚动条。 应用起来非常简单,只需 <v-scroll></v-scroll> 即可疾速生成一个虚构的模仿滚动条。 参数配置props: { // 是否显示原生滚动条 native: Boolean, // 是否自动隐藏滚动条 autohide: Boolean, // 滚动条尺寸 size: { type: [Number, String], default: '' }, // 滚动条色彩 color: String, // 滚动条层级 zIndex: null}, 疾速开始在main.js中引入滚动条组件。 import VScroll from './components/vscroll';Vue.use(VScroll);应用组件<!-- 反对原生滚动条 --><v-scroll native> <img src="https://cn.vuejs.org/images/logo.png" /> <p>这里是自定义内容。这里是自定义内容。这里是自定义内容。</p></v-scroll> <!-- 参数配置 --><v-scroll autohide size="15" color="#00a1e0" zIndex="2021"> <img src="https://cn.vuejs.org/images/logo.png" /> <p>这里是自定义内容。这里是自定义内容。这里是自定义内容。</p></v-scroll> 编码实现vscroll自定义滚动条模板。 <template> <div class="vui__scrollbar" ref="ref__box" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave" v-resize="handleResize"> <div :class="['vscroll__wrap', {native: native}]" ref="ref__wrap" @scroll="handleScroll"> <div class="vscroll__view" v-resize="handleResize"><slot /></div> </div> <!-- //程度|垂直滚动条 --> <div :class="['vscroll__bar vertical', {ishide: !isShow}]" @mousedown="handleClickTrack($event, 0)" :style="{'width': parseInt(size)>=0 ? parseInt(size)+'px' : '', 'z-index': parseInt(zIndex)>=0 ? parseInt(zIndex) : ''}"> <div class="vscroll__thumb" ref="ref__barY" :style="{'background': color, 'height': barHeight+'px'}" @mousedown="handleDragThumb($event, 0)"></div> </div> <div :class="['vscroll__bar horizontal', {ishide: !isShow}]" @mousedown="handleClickTrack($event, 1)" :style="{'height': parseInt(size)>=0 ? parseInt(size)+'px' : '', 'z-index': parseInt(zIndex)>=0 ? parseInt(zIndex) : ''}"> <div class="vscroll__thumb" ref="ref__barX" :style="{'background': color, 'width': barWidth+'px'}" @mousedown="handleDragThumb($event, 1)"></div> </div> </div></template>/** * @Desc VueJs虚构滚动条组件VScroll * @Time andy by 2020/11/30 * @About Q:282310962 wx:xy190310 */<script> import domUtils from './utils/dom' export default { props: { // 显示原生滚动条 native: Boolean, // 自动隐藏滚动条 autohide: Boolean, // 滚动条尺寸 size: { type: [Number, String], default: '' }, // 滚动条色彩 color: String, // 滚动条层级 zIndex: null }, data() { return { barWidth: 0, // 滚动条宽度 barHeight: 0, // 滚动条高度 ratioX: 1, // 滚动条程度偏移率 ratioY: 1, // 滚动条垂直偏移率 isTaped: false, // 鼠标光标是否按住滚动条 isHover: false, // 鼠标光标是否悬停在滚动区 isShow: !this.autohide, // 是否显示滚动条 } }, mounted() { this.$ref__box = this.$refs.ref__box this.$ref__wrap = this.$refs.ref__wrap this.$ref__barY = this.$refs.ref__barY this.$ref__barX = this.$refs.ref__barX this.$nextTick(this.updated) }, // ... methods: { // 鼠标移入 handleMouseEnter() { this.isHover = true this.isShow = true this.updated() }, // 鼠标移出 handleMouseLeave() { this.isHover = false this.isShow = false }, // 拖动滚动条 handleDragThumb(e, index) { let _this = this this.isTaped = true let c = {} domUtils.isIE() ? (e.returnValue = false, e.cancelBubble = true) : (e.stopPropagation(), e.preventDefault()) document.onselectstart = () => false if(index == 0) { c.dragY = true c.clientY = e.clientY }else { c.dragX = true c.clientX = e.clientX } domUtils.on(document, 'mousemove', function(evt) { if(_this.isTaped) { if(c.dragY) { _this.$ref__wrap.scrollTop += (evt.clientY - c.clientY) * _this.ratioY _this.$ref__barY.style.transform = `translateY(${_this.$ref__wrap.scrollTop / _this.ratioY}px)` c.clientY = evt.clientY } if(c.dragX) { _this.$ref__wrap.scrollLeft += (evt.clientX - c.clientX) * _this.ratioX _this.$ref__barX.style.transform = `translateX(${_this.$ref__wrap.scrollLeft / _this.ratioX}px)` c.clientX = evt.clientX } } }) domUtils.on(document, 'mouseup', function() { _this.isTaped = false document.onmouseup = null; document.onselectstart = null }) }, // 滚动槽 handleClickTrack(e, index) { console.log(index) }, // 更新滚动 updated() { if(this.native) return // 垂直滚动条 if(this.$ref__wrap.scrollHeight > this.$ref__wrap.offsetHeight) { this.barHeight = this.$ref__box.offsetHeight **2 / this.$ref__wrap.scrollHeight this.ratioY = (this.$ref__wrap.scrollHeight - this.$ref__box.offsetHeight) / (this.$ref__box.offsetHeight - this.barHeight) this.$ref__barY.style.transform = `translateY(${this.$ref__wrap.scrollTop / this.ratioY}px)` }else { this.barHeight = 0 this.$ref__barY.style.transform = '' this.$ref__wrap.style.marginRight = '' } // 程度滚动条 ... }, handleResize() { // 更新滚动条状态 }, // ... } }</script>vue.js中如何监听DOM尺寸变动?非常简单,只需自定义一个指令用来监听滚动条区域的状态变动(宽度/高度)。 ...

December 1, 2020 · 3 min · jiezi

关于vue.js:computed-和-watch-的区别和运用的场景

computed: 是计算属性,依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值产生扭转,下一次获取 computed 的值时才会从新计算 computed 的值; watch: 更多的是「察看」的作用,相似于某些数据的监听回调 ,每当监听的数据变动时都会执行回调进行后续操作; 使用场景: 当咱们须要进行数值计算,并且依赖于其它数据时,应该应用 computed,因为能够利用 computed 的缓存个性,防止每次获取值时,都要从新计算;当咱们须要在数据变动时执行异步或开销较大的操作时,应该应用 watch,应用 watch 选项容许咱们执行异步操作 ( 拜访一个 API ),限度咱们执行该操作的频率,并在咱们失去最终后果前,设置中间状态。这些都是计算属性无奈做到的。

November 30, 2020 · 1 min · jiezi

关于vue.js:面试官说说你对双向绑定的理解

本文为面试官VUE系列 总进度:3/33 一、什么是双向绑定咱们先从单向绑定切入 单向绑定非常简单,就是把Model绑定到View,当咱们用JavaScript代码更新Model时,View就会自动更新 双向绑定就很容易联想到了,在单向绑定的根底,用户更新了View,Model的数据也主动被更新了,这种状况就是双向绑定 举个栗子 当用户填写表单时,View的状态就被更新了,如果此时能够自动更新Model的状态,那就相当于咱们把Model和View做了双向绑定 关系图如下 二、双向绑定的原理是什么咱们都晓得 Vue 是数据双向绑定的框架,双向绑定由三个重要局部形成 数据层(Model):利用的数据及业务逻辑视图层(View):利用的展现成果,各类UI组件业务逻辑层(ViewModel):框架封装的外围,它负责将数据与视图关联起来而下面的这个分层的架构计划,能够用一个专业术语进行称说:MVVM 这里的管制层的外围性能便是 “数据双向绑定” 。天然,咱们只需弄懂它是什么,便能够进一步理解数据绑定的原理 了解ViewModel它的主要职责就是: 数据变动后更新视图视图变动后更新数据当然,它还有两个次要局部组成 监听器(Observer):对所有数据的属性进行监听解析器(Compiler):对每个元素节点的指令进行扫描跟解析,依据指令模板替换数据,以及绑定相应的更新函数三、如何实现双向数据咱们还是以Vue为例,先来看看Vue中的双向绑定流程是什么的 new Vue() 首先执行初始化,对data执行响应化解决,这个过程产生Observe中同时对模板执行编译,找到其中动静绑定的数据,从data中获取并初始化视图,这个过程产生在Compile中同时定义⼀个更新函数和Watcher,未来对应数据变动时Watcher会调用更新函数因为data的某个key在⼀个视图中可能呈现屡次,所以每个key都须要⼀个管家Dep来治理多个Watcher未来data中数据⼀旦发生变化,会首先找到对应的Dep,告诉所有Watcher执行更新函数流程图如下: 实现先来一个构造函数:执行初始化,对data执行响应化解决 class Vue { constructor(options) { this.$options = options; this.$data = options.data; // 对data选项做响应式解决 observe(this.$data); // 代理data到vm上 proxy(this); // 执行编译 new Compile(options.el, this); }}对data选项执行响应化具体操作 function observe(obj) { if (typeof obj !== "object" || obj == null) { return; } new Observer(obj);}class Observer { constructor(value) { this.value = value; this.walk(value); } walk(obj) { Object.keys(obj).forEach((key) => { defineReactive(obj, key, obj[key]); }); }}编译Compile对每个元素节点的指令进行扫描跟解析,依据指令模板替换数据,以及绑定相应的更新函数 ...

November 30, 2020 · 2 min · jiezi

关于vue.js:手写一个Hexo评论系统二

接着上一篇文章《手写一个Hexo评论零碎(一)》,本篇文章次要是讲述记述评论零碎实现的一些具体的设计方案与技术细节,不便当前批改或者重构。还有我的项目的部署问题,包含域名解析,Nginx配置代理,云服务器选购的一些问题,选购服务器的坑是真的大,所以还是尽量抉择大厂,稳固一点,好用一点就不必在乎多几那块钱嘛,而且依据本人的须要买配置还是比拟划算的。 <!-- more --> 上次总共列出了如下的一些需要,依据这些需要来构想一下如何设计: 1、无需登录和验证码,间接评论即可 2、反对回复评论,且可有限递归回复 3、反对评论点赞,依照点赞排序,雷同则依照工夫排序 3、反对文章评分,显示评分人数和评分的均匀分数 4、反对本人的评论被他人回复后能够邮件告诉 5、反对评论后盾管理系统,能够设置对应属性 6、反对评论导出,且高度100%可复原数据 界面与UI设计 第一版得UI就长这样了,整体看起来格调比较简单,这也是我比拟喜爱的格调。在文章加载后评论者会取得一个随机的昵称与头像,点击昵称能够切换昵称和头像,不过都是随机的而已。而后就是三个输入框,邮箱输入框、评论内容、文章评分。所以从整体上分成了两局部,一部分是用户信息和评论框,另一部分是具体评论展现区域,只有思考分明了那么就能够开始了。 反正是做PC的Web端UI嘛,间接上ElementUI了,其实还真的挺适宜的,尤其是在展现具体评论的时候依照工夫线来展现最合适不过了,而且评分组件也很OK,挺难看的,当前有工夫再拿其余的组件库试试! 交互流程设计首先用户要一关上博客就能够取得随机头像和昵称,并且要放弃这个用户的状态,所以整体思路如下: 首先对于一个从未关上过某篇博客的页面的用户来说,在浏览器端存储的clientID必定是没有这个字段的,间接能够断定为新用户,所以去申请后盾给一个ClientID,并且调配随机的昵称和头像,把这个用户信息给落库,即便用户点击了刷新昵称和头像,然而ClientID并没有变,用户信息就这样得以保留了下来。如果浏览器曾经存在了ClientID,那么数据库外面也应该有对应的用户信息,所以就间接申请后盾拿到用户数据即可。 第二个问题,后端怎么晓得哪些评论是哪些博客的呢?其实这里应用了一个比拟简略的形式,那就是间接依据URL来判断,雷同的URL必定是同一篇博客,然而这样做也是有缺点的,就是在本地调试的时候是localhost:8080结尾,然而近程是zouchanglin.cn,这样在本地的测试数据就不会展现在正式的博客评论上。而且zouchanglin.cn和zouchanglin.gitee.io的评论并不相通,其实这是不合理的,应该把域名和残余局部URL分离出来,这样通用性才会更好,这一点当前有工夫了我会进行重构。 第三个问题,用户设置了邮箱那么怎么能力回复的时候互相告诉呢?其实对这样的Client端设计,只有在用户填写了邮箱后,进行评论或者回复的操作,都能够设置邮箱,因为这样能够从很大水平上缩小业务复杂度,只有你的邮箱呈现变更,你的下一次评论想到失去告诉的时候必定会填写新的邮箱,这样就能够间接更新整个用户的邮箱,十分不便。 数据库设计数据库应用MySQL 8.0。首先是设计客户端信息表,也就是代表了用户信息(次要包含了客户端ID、Email、昵称、创立工夫、头像、客户端OS等信息,其余字段等有须要再增加就OK): 而后是文章信息表(次要字段是文章URL、文章评论数),一条数据对应着一条博客,其中还有博客的评论总计数目,其实齐全能够拿URL做主键,然而为了当前改变不便,目前还是决定自定义生成主键比拟好一些。 而后是评论表,在这里我把评论分成了两种类型,一种是文章评论(次要字段是文章ID、comment_parent是有效字段、评论客户端ID、评论内容、点赞数、创立工夫、文章评分),也就是间接在文章上面的评论;另一种是子评论(次要字段是所在的文章评论ID、评论客户端ID、评论内容、点赞数、回复的客户端ID、创立工夫),这个就是文章评论的回复而已,当然无论是文章评论的子评论还是子评论的回复评论都被当作子评论来存储,所有分了两张表。惟一不同之处在于文章评论会存储本人是那一篇文章下的评论,而子评论会存储本人位于哪一条文章评论底下,而且会存储回复的Client是谁,所以还存储了reply_client这个字段。 后端系统设计点击此处直到后端代码仓库:https://gitee.com/zouchanglin/comment-box 后端系统还是基于SpringBoot搭建的后端服务,其实用的都是比拟常见的技术,SpringMVC、SpringDataJPA等,平时用的比拟少的就是邮件发送服务,其实应用spring-boot-starter-mail来发送邮件几乎不要太容易。须要留神的就是后端的跨域问题,须要配置一个容许跨域的配置类,然而前面部署的时候举荐应用Nginx同域部署,跨域问题也就不存在了,这是我目前最喜爱的计划。 我的项目部署问题1、云服务购买还是比拟举荐腾讯云88/年,百度云太贵、阿里云用过了。腾讯云学生及还是能够买一买的,1核2G的配置,其实齐全够用了。刚开始脑子抽搐了买个天翼云,尽管才77元/年,然而难用的要死,而且最高速度也就130K/s,这谁受得了这么慢的速度。还是宁愿多花几块钱买个好一点的呀,毕竟大厂靠谱。千万别买天翼云呀,千万别买天翼云呀,千万别买天翼云呀,重要的事件说三遍。 2、解决HTTPS问题整个代码其实都曾经写好了,就剩一个部署了,然而因为我的网站全是HTTPS的,所以评论零碎也必须是HTTPS的,否则因为浏览器的安全策略会导致评论模块无奈加载。于是乎通过域名解析了一个二级域名comment.zouchanglin.cn到服务器上,为这个二级域名申请一个证书,这样就齐全OK了。 3、Nginx部署前端我的项目打包后间接应用Nginx部署一下,顺便把HTTPS证书配置一下,这样前端我的项目就能够HTTPS拜访了,那么后端呢?不可能有https://comment.zouchanglin.cn:8080这种URL存在吧,所以还是通过Nginx很轻松的解决了这个问题,只有通过Nginx配置一个代理,100%搞定,而且彻底、一劳永逸地解决了跨域问题,并且共享域名,还利用反向代理暗藏了后端地址,比拟不便集中管理。 所以我集体还是十分举荐采纳Nginx将前后端同域部署的,Nginx真的帮了大忙! 后端我的项目application.yml配置如下,其实就是拜访门路都变成了http://127.0.0.1:8080/api/.... server: port: 8080 servlet: context-path: /api前端我的项目记得敞开History模式,而后申请的根底URL就写成了: axios.defaults.baseURL = 'https://comment.zouchanglin.cn/api/'Nginx的配置文件如下: user root;worker_processes 2;events { worker_connections 1024;}http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; gzip on; # HTTPS server server { listen 443 ssl; server_name comment.zpuchanglin.cn; # 配置证书 ssl_certificate /opt/ssl_file/cn_chain.crt; ssl_certificate_key /opt/ssl_file/cn_key.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; location / { root /root/dist; try_files $uri $uri/ /index.html; } location ^~/api/ { proxy_pass http://127.0.0.1:8080; } }}须要改良之处集思广益,大家也能够评论留言... ...

November 30, 2020 · 1 min · jiezi

关于vue.js:fedtask0305Vuejs-30-Composition-API-及-30-原理剖析

简答题1、Vue 3.0 性能晋升次要是通过哪几方面体现的?Vue 3.0 性能晋升: (1)响应式系统升级 Vue.js 2.x 中响应式零碎的外围是 Object.definePropertyVue.js 3.0 中应用 Proxy 对象重写了响应式零碎 能够监听动静新增的属性能够监听删除的属性能够监听数组的索引和 length 属性(2)编译优化 Vue.js 2.x 中通过标记动态根节点,优化 diff 过程Vue.js 3.0 中标记和晋升所有的动态节点,diff 的时候只须要比照动静节点内容 Fragments 片段,模板中能够间接放文本内容或同级标签(降级 vetur 插件)动态节点晋升到 render 函数内部,只在初始化时执行一次,再次render无需再次执行Patch flag,标记动静节点(记录节点内容、节点属性),diff时跳过动态根节点 只需关怀动静节点内容缓存事件处理函数,缩小了不必要的更新操作(3)源码体积的优化 Vue.js 3.0 中移除了一些不罕用的 API 例如:inline-template / filter 等Tree-shaking2、Vue 3.0 所采纳的 Composition Api 与 Vue 2.x 应用的 Options Api 有什么区别?Options Api 蕴含一个形容组件选项(props、data、methods 等)的对象Options Api 开发简单组件,同一个性能逻辑的代码被拆分到不同选项Composition Api 提供了一种基于函数的API,让咱们能够更灵便、更正当的组织组件的逻辑和代码构造同一性能的代码不须要拆分,有利于对代码的提取和重用3、Proxy 绝对于 Object.defineProperty 有哪些长处?Proxy 的长处: Proxy 除了有 set 和 get 监听之外,还有其余对于对象的监听回调,能够监听动静新增的属性、监听删除的属性。has deleteProperty ownKeys apply 等等Proxy 更好的反对数组对象的监督监听,能够监听数组的索引和 length 属性Proxy 是以非侵入的形式监管了对象的读写,不会批改原对象4、Vue 3.0 在编译方面有哪些优化?Vue.js 3.0 中标记和晋升所有的动态节点,diff 的时候只须要比照动静节点内容 ...

November 29, 2020 · 1 min · jiezi

关于vue.js:vuecli4创建一个项目之bashrc

用vue-cli创立一个我的项目,windows----QDD 始终都习惯了Git bash去开始整一个货色。不想win+r,再去cmd啊 然而他不论用啊,不能抉择咱们要的配置,强迫症真的好受!!! 唉,官网给了个这么滴阐明,来整一下吧 正告如果你在 Windows 上通过 minTTY 应用 Git Bash,交互提示符并不工作。你必须通过 winpty vue.cmd create hello-world 启动这个命令。不过,如果你仍想应用 vue create hello-world,则能够通过在 ~/.bashrc 文件中增加以下行来为命令增加别名。 alias vue='winpty vue.cmd' 你须要重新启动 Git Bash 终端会话以使更新后的 bashrc 文件失效。 一般来说git配置会被默认放在 C:\Users\Administrator 门路上面 进到这个门路做上面几步操作 创立一个.bashrc文件:touch ~/.bashrc关上更改内容:start ~/.bashrcalias vue='winpty vue.cmd' 这玩意儿复制进去,别忘了保留退出后重启git bash,而后运行 source ~/.bashrc再去你想要用的中央用 vue create 命令就行了,搞定阐明:bashrc文件是用户配置文环境变量的文件,每次git bash会首先运行外面的内容。每次进入git bash都会先读取.bashrc外面的内容,因而能够先将要运行的代码,放在.bashrc文件外面的。

November 28, 2020 · 1 min · jiezi

关于vue.js:vue项目性能优化方法

大略有以下几点 路由组件按需加载个别一个我的项目会有多个页面(路由),利用webpack的代码宰割与vue的异步组件,将代码按路由做按需加载;能够大大提高首次关上速度,页面越多成果越显著 非页面一级性能组件拆分按需加载在刚关上页面时有些性能是不须要的,比方点击后的弹窗;能够将这些性能做拆分,联合vue的异步组件与webpack的代码宰割做按需加载 每个页面都须要加载的代码存入cdn如vue.min.js、axios、vuex.js、vue-router.js等等 sourceMap相干代码不要打入js内sourceMap文件如果打入js内会大大增加js文件大小

November 27, 2020 · 1 min · jiezi

关于vue.js:vue3的ref和react的ref比较

vuevue3的组合API模式中,用ref函数使任何响应式变量在任何中央起作用 ref的应用 import { ref } from 'vue'const counter = ref(0)ref 承受参数并返回它包装在具备 value property 的对象中,而后能够应用该 property 拜访或更改响应式变量的值 import { ref } from 'vue'const counter = ref(0)console.log(counter) // { value: 0 }console.log(counter.value) // 0counter.value++console.log(counter.value) // 1在对象中包装值仿佛不必要,但在 JavaScript 中放弃不同数据类型的行为对立是必须的。这是因为在 JavaScript 中,Number 或 String 等根本类型是通过值传递的,而不是通过援用传递的。 在任何值四周都有一个包装器对象,这样咱们就能够在整个应用程序中平安地传递它,而不用放心在某个中央失去它的响应性。 提醒换句话说,ref 对咱们的值创立了一个响应式援用。应用援用的概念将在整个组合式 API 中常常应用。 回到咱们的例子,让咱们创立一个响应式的 repositories 变量 // src/components/UserRepositories.vueimport { fetchUserRepositories } from '@/api/repositories'import { ref } from 'vue'export default { components: { RepositoriesFilters, RepositoriesSortBy, RepositoriesList }, props: { user: { type: String } }, setup (props) { const repositories = ref([]) const getUserRepositories = async () => { repositories.value = await fetchUserRepositories(props.user) } onMounted(getUserRepositories) return { repositories, getUserRepositories } }, data () { return { filters: { ... }, // 3 searchQuery: '' // 2 } }}WARNING然而,因为 props 是响应式的,你不能应用 ES6 解构,因为它会打消 prop 的响应性。 ...

November 27, 2020 · 1 min · jiezi

关于vue.js:Vue-中非父子组件通过路由传参参数为对象的时候

在Vue中当2个非父子组件须要传递参数的时候,当传递的参数是对象的时候1:须要传递的界面路由跳转须要传递参数的界面 var params = JSON.stringify(params);this.$router.push({name:"A",query:{ 'queryParams':encodeURIComponent(params)}})2:须要承受参数对象的界面 let paramsArr = this.$route.query.queryParams;let params =decodeURIComponent(paramsArr);let queryparams = JSON.parse(params)

November 27, 2020 · 1 min · jiezi

关于vue.js:以-Kubernetes-为代表的容器技术已成为云计算的新界面

简介: 能够说,以 Kubernetes 为代表的容器技术正成为云计算新界面。容器提供了利用散发和交付规范,将利用与底层运行环境进行解耦。Kubernetes 作为资源调度和编排的规范,屏蔽底层架构差异性,帮忙利用平滑运行在不同基础设施上。CNCF Kubernetes 的一致性认证,进一步确保不同云厂商 Kubernetes 实现的兼容性,这也让更多的企业违心采纳容器技术来构建云时代的利用基础设施。 起源 | 阿里巴巴云原生公众号 作者 | 志敏、智清 2020 年 双11,阿里外围零碎实现了全面云原生化,扛住了史上最大流量洪峰,向业界传播出了“云原生正在大规模落地”的信号。这里蕴含着诸多阿里 "云原生的第一次”,其中十分要害的一点是 80% 外围业务部署在阿里云容器 ACK 上,可在 1 小时内扩大超百万容器。 能够说,以 Kubernetes 为代表的容器技术正成为云计算新界面。容器提供了利用散发和交付规范,将利用与底层运行环境进行解耦。Kubernetes 作为资源调度和编排的规范,屏蔽底层架构差异性,帮忙利用平滑运行在不同基础设施上。CNCF Kubernetes 的一致性认证,进一步确保不同云厂商 Kubernetes 实现的兼容性,这也让更多的企业违心采纳容器技术来构建云时代的利用基础设施。 云原生容器新界面的崛起 作为容器编排的事实标准,Kubernetes 反对 IaaS 层不同类型的计算、存储、网络等能力,不论是 CPU、GPU、FPGA 还是业余的 ASIC 芯片,都能够对立调度、高效应用异构算力的资源,同时完满撑持各种开源框架、语言和各类型利用。 随同着 Kubernetes 成为新操作系统的事实,以云原生容器为主的技术,曾经成为云计算的新界面。 云原生容器界面特色云原生容器界面具备以下三个典型特色: 向下封装基础设施,屏蔽底层架构的差异性。拓展云计算新边界,云边端一体化治理。向上撑持多种工作负载和分布式架构。1)向下封装基础设施,屏蔽底层差异性对立技能栈升高人力老本:Kubernetes 能够在 IDC、云端、边缘等不同场景进行对立部署和交付,通过云原生提倡的 DevOps 文化和工具集的应用无效晋升技术迭代速度,因而整体上能够升高人力老本。对立技术栈晋升资源利用率:多种计算负载在 Kubernetes 集群对立调度,能够无效晋升资源利用率。Gartner 预测“将来 3 年,70% 的 AI 工作运行在容器和 Serverless 上” ,而 AI 模型训练和大数据计算类工作负载更加须要 Kubernetes 提供更低的调度提早、更大的并发调度吞吐和更高的异构资源利用率。减速数据服务的云原生化:因为计算存储拆散具备微小的灵活性和老本劣势,数据服务的云原生化也逐步成为趋势。容器和 Serverless 的弹性能够简化对计算工作的容量布局。联合分布式缓存减速(比方 Alluxio 或阿里云 Jindofs)和调度优化,也能够大大晋升数据计算类和 AI 工作的计算效率。平安能力进一步增强:随着数字经济的倒退,企业的数据资产成为新“石油”,大量数据须要在云端进行替换、解决。如何保障数据的平安、隐衷、可信成为了企业上云的最大挑战。咱们须要用技术手段,建设数字化信赖根底,爱护数据,帮忙企业创立可信赖的商业单干关系,促成业务增长。比方基于 Intel SGX 等加密计算技术,阿里云为云上客户提供了可信的执行环境。不过,可信利用开发和应用门槛都很高,须要用户对现有利用进行重构,解决大量的底层技术细节,让这项技术落地十分艰难。2)拓展云计算新边界,云边端一体化治理随着边缘计算的场景和需要一直减少,“云边协同”、“边缘云原生”正在逐步成为新的技术焦点。Kubernetes 具备弱小的容器编排、资源调度能力,能够满足边缘/IoT 场景中,对低功耗、异构资源适配、云边网络协同等方面的独特需要。为了推动云原生和边缘计算穿插畛域的协同倒退,阿里巴巴于 2020 年 5 月正式对外开源边缘计算云原生我的项目 OpenYurt,推动“云边一体化”概念落地,通过对原生 Kubernetes 进行扩大的形式实现对边缘计算场景需要的反对,其次要个性有: ...

November 27, 2020 · 2 min · jiezi

关于vue.js:手把手教你如何在生产环境检查-Vue-应用程序

在开发环境中,Vue devtools 是很有用。 然而,一旦部署到生产环境,它就不再能够拜访咱们所编写的代码。 那么公布到生产环境时,咱们要怎么查看应用程序呢? 在这篇文章中,咱们会介绍一些技巧,用来检查和调试咱们的代码。 触发 Prop 值并更新除了弄清楚如何查看Vue外部变量外,咱们还尝试更新组件属性值。 假如咱们有一个组件,该组件的prop管制着一个元素的文本,那么咱们如何强制扭转该值以触发UI更新呢? <template> <h1>{{ msg }}</h1></template><script> export default { props: { msg: { type: String, default: '' } }}; </script>找到 Vue 组件实例首先,咱们须要应用Chrome devtools elements面板找到组件的顶级元素。 在本例中,元素是h1: 应用$0命令一旦咱们抉择了元素,就能够在控制台中输出$0,$0示意最初抉择的元素。$1是之前抉择的元素,依此类推.它记得最初五个元素$0 – $4. 要查看Vue实例的详细信息,能够应用 $0.__vue__。 应用document.querySelector办法咱们还能够应用任何DOM查找办法(例如querySelector或getElementById等)来抉择元素。这里咱们将应用document.querySelector来查看 Vue 实例: document.querySelector('[data-v-763db97b]').__vue__这里咱们应用通过data 属性查找元素,然而你能够在querySelector中应用任何无效的CSS选择器。 锁定 prop 值有了Vue组件实例的援用,咱们就能够在控制台中开展它,看看外面有什么内容: 认真看,在两头看到msg prop,单击三个点,就会看到以后值。 咱们能够在控制台中应用上面命令查看prop值: // Using $0$0.__vue__.msg// Using querySelectordocument.querySelector('[data-v-763db97b]').__vue__.msg更新 prop 值当初,更新prop值就是将变量从新赋值给它。因而,能够在管制台上这么做: $0.__vue__.msg = 'Hello from the updated value!'瞧,UI更新啦! ...

November 26, 2020 · 1 min · jiezi

关于vue.js:面试官说说你对vue的理解

一、web倒退历史Web是World Wide Web的简称,中文译为万维网 咱们能够将它布局成如下的几个时代来进行了解 石器时代文化时代工业革命时代百花齐放时代石器时代石器时代指的就是咱们的动态网页,能够观赏一下1997的Apple官网 最早的网页是没有数据库的,能够了解成就是一张能够在网络上浏览的报纸,直到CGI技术的呈现 通过 CGI Perl 运行一小段代码与数据库或文件系统进行交互,如过后的Google(1998年) 文化时代ASP,JSP大家应该都不会太生疏,最早呈现于 2005 年左右,先后呈现了微软的 ASP 和 Java Server Pages [JSP] 等技术,取代了 CGI ,加强了 WEB 与服务端的交互的安全性,相似于上面这样,其实就是Java + HTML <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%><!DOCTYPE html><html><head> <meta charset="utf-8"> <title>JSP demo</title></head><body> <img src="http://localhost:8080/web05_session/1.jpg" width=200 height=100 /></body></html>JSP有一个很大的毛病,就是不太灵便,因为JSP是在服务器端执行的,通常返回该客户端的就是一个HTML文本。咱们每次的申请:获取的数据、内容的加载,都是服务器为咱们返回染实现之后的 DOM,这也就使得咱们开发网站的灵便度大打折扣 在这种状况下,同年:Ajax火了(小细节,这里为什么说火了,因为 Ajax 技术并不是 2005 年呈现的,他的雏形是 1999 年),当初看来很常见的技术手段,在过后可是宝贵无比 工业革命时代到这里大家就更相熟了, 挪动设施的遍及,Jquery的呈现,以及SPA(Single Page Application 单页面利用)的雏形,Backbone EmberJS AngularJS 这样一批前端框架随之呈现,但过后SPA的路不好走,例如SEO问题,SPA 过多的页面、简单场景下 View 的绑定等,都没有很好的解决 这几年的飞速发展,节约了开发人员大量的精力、升高了开发者和开发过程的门槛,极大晋升了开发效率和迭代速度,咱们能够称之其为工业时代 百花齐放时代这里没有文字,放一张图感受一下 PS:这里为什么要说这么多Web的历史,咱们能够看到Web技术的变动之大与快,每一种新的技术呈现都是一些特定场景的解决方案,那咱们明天的配角Vue又是为了解决什么呢? 咱们接着往下看 二、vue是什么Vue.js(/vju/,或简称为Vue) 是一个用于创立用户界面的开源JavaScript框架,也是一个创立单页利用的Web利用框架。 2016年一项针对JavaScript的考察表明,Vue有着89%的开发者满意度。在GitHub上,该我的项目均匀每天能播种95颗星,为Github有史以来星标数第3多的我的项目 ...

November 26, 2020 · 1 min · jiezi

关于vue.js:Nuxt-开发搭建博客

家喻户晓,Vue SPA单页面利用对SEO不敌对,当然也有相应的解决方案。 服务端渲染 (SSR) 就是罕用的一种。 SSR 有利于 搜索引擎优化(SEO, Search Engine Optimization) ,并且 内容达到工夫(time-to-content) (或称之为首屏渲染时长)也有很大的优化空间。 Nuxt.js 是一个基于 Vue.js 的轻量级利用框架,可用来创立 服务端渲染 (SSR) 利用,也可充当动态站点引擎生成动态站点利用,具备优雅的代码构造分层和热加载等个性。 我的项目地址:明么的博客 初始化我的项目运行 create-nuxt-app通过 Nuxt 官网提供的脚手架工具 create-nuxt-app 初始化我的项目: $ npx create-nuxt-app <我的项目名>// 或者 $ yarn create nuxt-app <我的项目名>我的项目配置我的项目创立的时候会让你进行一些配置的抉择,可依据本人须要进行抉择。 我的项目运行运行完后,它将装置所有依赖项,下一步是启动我的项目: $ cd <project-name>$ yarn dev在浏览器中,关上 http://localhost:3000 目录构造.├── assets // 用于组织未编译的动态资源├── components // 用于组织利用的 Vue.js 组件├── layouts // 用于组织利用的布局组件├── middleware // 用于寄存利用的中间件├── node_modules├── pages // 用于组织利用的路由及视图├── plugins // 组织插件。├── static // 用于寄存利用的动态文件├── store // 状态治理├── nuxt.config.js // 配置文件├── package.json├── jsconfig.json├── stylelint.config.js├── README.md└── yarn.lock我的项目开发我的项目启动之后,咱们就能够进行开发阶段了。 ...

November 25, 2020 · 6 min · jiezi

关于vue.js:面试官说说你对vue的理解

@JS语音社群

November 25, 2020 · 1 min · jiezi

关于vue.js:面试官说说你对vue的理解

@JS语音社群

November 25, 2020 · 1 min · jiezi

关于vue.js:前端工作流

背景多集体做一个我的项目的时候,总是因为大家代码格调不对立,须要通过文档约定的形式来对立格调。 比方文件起名形式,有的人首字母大写,有的人首字母小写,在js,ts,vue中又有这种迥异的格调。针对这种状况,咱们起了个约定文档,规定应该怎么给文件夹命名,然而这种有个毛病就是,无奈从本源上解决,也就是新来的共事可能不晓得这个规定,而后就新建了一个非约定的文件名。 除了文件名,提交标准也是迥异的,有的人commit的时候不加type,这种咱们也是起了个约定文档。 缓缓的文件目录就多了个docs文档是有益处的,然而也无奈从本源上限度问题。所以当初的前端我的项目,引出了工作流理念,也多了很多定制工作流的辅助工具。 工作流概览多人的我的项目,总是须要规定一些标准,为了让代码格调尽量对立。咱们须要用到以下工具: 代码丑化 - prettier语法标准 - airbnb语法校验 - eslintgit-hook - husky提交标准 - commitlint文件命名标准 - ls-lint主动修复代码 - lint-stagedeslint & prettier这里有一篇写得比拟好的文章,这里就不开展讲怎么配置了。 commitlint 代码提交标准commitlint 用来帮忙团队恪守提交标准,更多信息可查看官网装置npm install --save-dev @commitlint/config-conventional @commitlint/cli格局[type]: [subject] type为以下字段 feat:新性能(feature)fix:修补bugdocs:文档(documentation)style: 格局(不影响代码运行的变动)refactor:重构(即不是新增性能,也不是批改bug的代码变动)test:减少测试chore:构建过程或辅助工具的变动upd: 更新功能模块workflow: 工作流变动subject为形容内容,比方 修复设施日志色彩值转换的问题残缺的形容,⚠️ 留神冒号后带空格,比方 git commit -m 'fix: 修复设施日志色彩值转换的问题'git commit -m 'chore: 批改commitlint配置文件'commitlint.config.jscommitlint反对终端输出指令的模式执行校验,当然也反对配置文件的模式。配置文件的具体内容如下: rulers字段,由name和配置数组组合,配置数组包含: Level[0,1,2]: 0示意禁用规定,1会被视为正告,2抛出异样Applicable always|never: 是否利用规定Value: 改规定利用的值配置数组能够是:数组,返回数组的函数,返回数组的promise。 module.exports = { extends: ['@commitlint/config-conventional'], rules: { 'type-enum': [ 2, 'always', ['upd', 'feat', 'fix', 'refactor', 'docs', 'chore', 'style', 'revert'], ], 'type-case': [0], 'type-empty': [0], 'scope-empty': [0], 'scope-case': [0], 'subject-full-stop': [0, 'never'], 'subject-case': [0, 'never'], 'header-max-length': [0, 'always', 72], },};配置git-hookgithook其实就是你在git操作时的回调。这里咱们只关怀一个git-hook就是pre-commit,提交前的回调。通过对commitlint的配置,咱们曾经对提交标准做了配置,然而咱们遇到了一个问题,什么时候才应该去校验提交的标准。 ...

November 25, 2020 · 1 min · jiezi

关于vue.js:vue中data是个函数而不是对象

在一个我的项目中,组件能够有多个,每一个组件均可当作一个结构器,注册组件的实质其实就是结构器的援用。如果间接应用对象,他们的内存地址是一样的,一个数据扭转了其余也扭转了,这就造成了数据净化,如果应用函数的话,会造成一个全新的作用域,这样data中的数据不会相互影响,从而防止数据净化。但因为根实例只有一个,所以不存在数据净化这种状况,也就能够应用对象了。

November 24, 2020 · 1 min · jiezi

关于vue.js:WEBVUE

1 vue概述Vue.js是一套构建用户界面的渐进式框架。与其余重量级框架不同的是,Vue 采纳自底向上增量开发的设计。 什么场景应用VUE?绝大多数以数据操作(增删改查)为主的PC端或挪动端我的项目都可用vue开发比方: 美团,饿了么,淘宝,知乎,公众点评,微博... 1.1 vue的MVVM设计思维MVVM是一种设计思维,对晚期的web前端开发做了加强,将前端代码按其职责的不同分成了三局部: 界面(View)局部:由html+css形成,并容许在html,css中间接应用变量,表达式,语句等。模型局部(Model):个别为一个JSON格局的对象,用于存储view中须要的数据和函数。视图模型(ViewModel):专门负责主动保护模型对象中的变量与界面中的变量同步。因为有了ViewModel的存在,数据能够主动同步到界面上,简直防止了大量反复的编码! 2 插值语法Vue.js 的外围是一个容许采纳简洁的模板语法来申明式地将数据渲染进 DOM 的零碎: <div id="app"> {{ message }}</div>var app = new Vue({ el: '#app', data: { message: 'Hello Vue!' }})后果: Hello Vue!3 vue常见的指令语法v-bind元素的属性值随着程序内容的变动而变动,可应用v-bind: <元素 v-bind:属性名="变量或js表达式">简化模式,根本语法如:<元素 :属性名="变量或js表达式"><!-- 绑定一个 attribute --><img v-bind:src="imageSrc"><!-- 缩写 --><img :src="imageSrc">v-show v-if和v-else v-else-if v-for为以后遍历的元素提供别名: <div v-for="item in items"> {{ item.text }}</div>v-on@click为v-on:click的缩写 <!DOCTYPE html><html> <head> <meta charset="utf-8"> <title></title> <script src="js/vue.js"></script> </head> <body> <div id="app"> <h1 v-on:click="handleClick(1)">{{ msg }}</h1> <h1 @click="handleClick(2)">{{ msg }}</h1> </div> </body> <script> new Vue({ el: "#app", data: { msg: "Hello Vue." }, methods:{ handleClick: function( who ){ this.msg = who+"- 你好,世界"; } } }); </script></html>v-html ...

November 24, 2020 · 2 min · jiezi

关于vue.js:vue-全屏插件

装置: npm install --save screenfull利用: import screenfull from 'screenfull'export default { name: 'test', data() { return { screenfullBut: false, // 全屏按钮 } }, methods: { // 全屏性能 fullscreen() { if (!screenfull.isEnabled) { this.$notification.open({ message: '舒适提醒', description: '您的浏览器无奈应用全屏性能,请更换谷歌浏览器或者请手动点击F11按钮全屏展现!', duration: 10, placement: 'bottomLeft', }); return false } screenfull.toggle(); if(screenfull.isFullscreen){ this.screenfullBut = false; }else{ this.screenfullBut = true; } }, }}

November 24, 2020 · 1 min · jiezi

关于vue.js:从Vue3源码中再谈nextTick

开始之前先看下官网对其的定义 定义: 在下次 DOM 更新循环完结之后执行提早回调。在批改数据之后立刻应用这个办法,获取更新后的 DOM看完是不是有一堆问号?咱们从中找进去产生问号的关键词 下次 DOM 更新循环完结之后?执行提早回调?更新后的 DOM?从下面三个疑难大胆猜测一下 vue 更新DOM是有策略的,不是同步更新nextTick 能够接管一个函数做为入参nextTick 后能拿到最新的数据好了,问题都抛出来了,先来看一下如何应用 import { createApp, nextTick } from 'vue'const app = createApp({ setup() { const message = ref('Hello!') const changeMessage = async newMessage => { message.value = newMessage // 这里获取DOM的value是旧值 await nextTick() // nextTick 后获取DOM的value是更新后的值 console.log('Now DOM is updated') } }})亲自试一试 那么 nextTick 是怎么做到的呢?为了前面的内容更好了解,这里咱们得从 js 的执行机制说起 JS执行机制咱们都晓得 JS 是单线程语言,即指某一时间内只能干一件事,有的同学可能会问,为什么 JS 不能是多线程呢?多线程就能同一时间内干多件事件了 是否多线程这个取决于语言的用处,一个很简略的例子,如果同一时间,一个增加了 DOM,一个删除了 DOM, 这个时候语言就不晓得是该添还是该删了,所以从利用场景来看 JS 只能是单线程 ...

November 23, 2020 · 2 min · jiezi

关于vue.js:白话说框架

如果你只会应用 Vue 或者 React,那么这篇文章适宜你。 本文不深刻聊原理,只比照根底性能的应用,先看上面这份数据,百度搜寻指数,很显著 Vue 搜寻指数显著高于 React 以及 Angular。 从简略学起没问题,你认为的技术之路这样的 其实你是这样的 想想本人除了 Vue, 你还有什么?写此文的目标就是让大家领悟到应用框架的办法和技巧。 上面是截取 react 与 vue 官网文档目录,共通的根底性能至多蕴含 9 项 数据绑定模板条件列表表单绑定事件处理生命周期组件 以上蕴含了当下风行框架根本必备性能,先不去想框架具体实现细节,就以上七个性能,在不手动操作 DOM 的状况下如何实现? 三大框架都借助 MVVM 的思维,其劣势就是解脱手动操作 DOM 及节点数据获取带来的低效问题,往下看 MVVMMVVM 旨在利用数据绑定函数,通过 ViewModal 主动去更新 DOM 的状态,进而从视图层中简直删除所有 GUI 代码。 既然大家都受到 VM 思维的启发,且根底性能都大抵类似,咱们逐个比照 Vue 及 React 的根底性能 数据绑定vue 双向绑定,react 单向绑定,代码比拟 // vue// 该对象被退出到一个 Vue 实例中var vm = new Vue({ data: { a: 1 }, created: function () { this.a = 2; },});// reactvar data = { a: 1 };class HelloWorld extends React.Component { constructor(props) { super(props); this.state = { a: 1 }; } componentDidMount() { // 须通过办法触发 this.setState({ a: 2, }); } render() { return ( <div> <h1>Hello, world!</h1> </div> ); }}ReactDOM.render(<HelloWorld />, document.getElementById("root"));模板表达式JSX 用 {} ,vue 用 {{}}, 代码比拟 ...

November 22, 2020 · 2 min · jiezi

关于vue.js:跳转到当前路由的时候vue的出错解决方案

import Vue from 'vue'import VueRouter from 'vue-router'Vue.use(VueRouter)// 解决跳转到以后路由的时候,控制台报错// const originalPush = VueRouter.prototype.push// VueRouter.prototype.push = function push(location) {// return originalPush.call(this, location).catch(err => err)// }const routes = [{ path: '/', name: 'index', component: () => import ('./../views/home/index') }, { path: '/movie', name: '/movie', component: () => import ('./../views/movie/index') }, { path: '/birth', name: '/birth', component: () => import ('./../views/birth/index') }, { path: '/Lifemeeting', name: '/Lifemeeting', component: () => import ('./../views/Lifemeeting/Lifemeeting') }, { path: '/Sign', name: '/Sign', component: () => import ('./../views/UserInformation/Sign.vue') },]const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes})//// router.beforeEach((from,to,next)=>{// console.log('from',from)// console.log('to',to)// next()// })export default router

November 21, 2020 · 1 min · jiezi

关于vue.js:Vuejs之watch与computed的使用及区别

watch与computed都是以Vue的依赖追踪机制为根底的,它们都试图解决这样一件事件:当某一个数据(称它为依赖数据)发生变化的时候,所有依赖这个数据的“相干”数据“主动”发生变化,也就是主动调用相干的函数去实现数据的变动。它们与methods中办法的区别就在于,methos外面的办法须要手动去调用,而它们会主动执行。watch1、watch善于解决的场景:一个数据影响多个数据2、应用 <div id="app"> <div> <span>数量: {{num}}</span> </div> <button @click="sub">数量减一</button></div>new Vue({ el: '#app', data: { num: 2, }, watch: { num: { handler(newVal, oldVal) { if (newVal == 0 && oldVal == 1) { console.log(`商品数量从${oldVal}减为 ${newVal}, 马上执行删除`); console.log('删除商品'); } else { console.log('数量缩小'); } } } }, methods: { sub: function () { this.num--; },}) 3、总结 * 相似监听机制+事件机制computed1、computed善于解决的场景:一个数据受多个数据影响2、应用 <div id="app"> <div> <span>数量: {{num}}</span> </div> <div> <span>单价: {{price}}</span> </div> <div> <span>总价: {{totalPrice}}</span> </div> <button @click="add">数量加一</button></div>new Vue({ el: '#app', data: { num: 0, price: 0, }, computed: { // 监听总价的变动 totalPrice: function () { return this.price * this.num; }, }, methods: { add: function () { this.num++; },})3、总结 ...

November 20, 2020 · 1 min · jiezi

关于vue.js:Vue-对数据对象实现深拷贝赋值

在日常的Vue开发工作中,咱们常常对申请来的数据进行变量赋值操作,再用变量去进行数据渲染。 然而咱们晓得,咱们常常用的赋值形式 “=” 实际上属于数据的浅拷贝,也就是当你扭转赋值变量时,原数据也会产生相应变动。 var a = ['1', '2', '3', '4', '5']; var b = a;b[0] = '2';console.log(a); // ['2', '2', '3', '4', '5'] console.log(b); // ['2', '2', '3', '4', '5'] //因为b浅拷贝a, ab指向同一个内存地址(堆内存中存的值) 那当咱们须要扭转变量的值然而不扭转原来数据的时候,咱们能够借助JSON办法来实现数据的深拷贝赋值: JSON.parse(JSON.stringify(this.responseData));e.g: let data1 = this.selectform.keyList let data2 = JSON.parse(JSON.stringify(this.selectform.keyList)) data1.a = 'test' console.log(data1.a) // testconsole.log(this.selectform.keyList.a) // testdata2.a = 'test222'console.log(keydata2.a) // test222console.log(this.selectform.keyList.a) // test*附深浅拷贝示意图: 浅拷贝: 深拷贝:

November 20, 2020 · 1 min · jiezi

关于vue.js:Vue30初体验-新功能以及相关库使用

前言vue3.0从公布到当初曾经有几个月了,基本上大家都处于一个试玩阶段。但搬砖的厂里有了新我的项目,领导提出新我的项目用vue3.0 + ts踩坑的想法,那么vue3.0到底怎么玩,最近也略微搞了下,上面疾速和铁汁们分享一波根底的应用。 看完文章,你会学习到: vue3的应用装置vue3的新个性vuex,vue-router的降级和应用老样子,上面咱们间接开冲! 体验Vue3的形式vue-cli官网指定cli工具,要更新最新版本。这个比较稳定,倡议刚开始应用这个 // 新版vue-cli会多出一个创立vue3的我的项目、抉择vue3之后、其余的配置就看大家们的爱好了 npm install -g @vue/cli vue create vue3-project cd vue3-project vue add vue-next npm run servewebpack这个是vue-cli还没开始反对时候,vue官网本人搞得一套webpack我的项目配置,间接clone git clone https://github.com/vuejs/vue-next-webpack-preview.git 01-vue3-webpack cd 01-vue3-webpack npm install npm run devvite这个就比拟有意思了,这个是尤大大最近着重开发的一个工具,意在代替webpack打包,外围是利用浏览器当初曾经反对import,遇到import会应用http申请去加载文件,在vite中应用koa拦挡这些申请,进行分类以及预编译,加载各个模块,在build时候应用rollup进行打包,节俭了大部分工夫,实现简单我的项目秒开 npm install -g create-vite-app create-vite-app vue3-vite cd vue3-vite npm install npm run devps: 铁汁们在应用的时候留神本人的node版本,应用vite时候须要高版本的node。 Vue3新个性Composition API体验蕴含setup、ref、computed等。因为reactive,compiler-sfc, complier-dom等外围模块的抽离,能够更加自在的在我的项目中援用应用,使函数式编程能够施展更大的作用 setup Vue3.0的重要新函数,相熟React的同学们必定常常用Hooks,其实我个人感觉这个和Hooks其实很像,当然我也不分明尤大大是不是借鉴的React(/手动狗头),不过函数式编程必定是爽的。setup是个独立的函数,外部能够应用Vue的所有模块,包含了生命周期、响应式、computed、watch等,最初返回一个对象,能够在template中间接调用。 reactive、ref 看名字就晓得是vue的三大件之一响应式的模块,这次做了很大变革,应用了proxy代替以前的defineprototype,性能上晋升很多,反对了Array的监听,并且独自抽离了进去。应用形式是传入一个对象,返回一个proxy代理监听过的对象,代理过的数据都是响应式的。 computed、watch 这次computed和watch都拆分成了独立的模块,在应用的时候按需引入进来应用形式也有了丢丢扭转 好了,说了那么多,光说不练假把式,咱们写个????来看看: <template> <div> <p>count: {{state.count}}</p> <p>doubleCount: {{doubleCount}}</p> <p>number: {{number}}</p> <div><button @click="add">add</button></div> </div></template><script> import { reactive, computed, ref } from 'vue' export default { name: 'App', setup () { const state = reactive({ count: 1 }) const number = ref(0) const doubleCount = computed(() => state.count * 2) function add () { state.count++ number.value += 10 } return { state, doubleCount, add, number } } }</script>Fragment这个我集体认为还是很爽的,反对多根节点,不必特意在里面成心套一层无用DOM,尽管一些纠错工具仍然会标红就是了.... ...

November 20, 2020 · 2 min · jiezi

关于vue.js:vue数据层次嵌套太深导致视图不跟新问题vfor循环的数组

问题:在我的项目中这个数据是这样嵌套的 json: { type: ' ', agentList: [ { name: '', id: '' }, ] },须要json.agentList 进行数据循环 ,点击删除的时候就删除其中一个数据 <div class="form-item validate dis-flex flex-center" v-for="item in json.agentList" :key='item.id'> <label class="label validate">{{ item.type==1 ?'委托代理人:' :'法定/指定代理人:'}}</label>> </div>操作删除应用了splice 删除json.agentList中一条数据 ,数据删除了,然而视图就是不更新 let index = this.json.agentList.findIndex(el => { return el.name == item.name }) this.json.agentList.splice(index, 1)解决 增加一句 this.$forceUpdate() 解决了刷新问题 let index = this.json.agentList.findIndex(el => { return el.name == item.name }) this.json.agentList.splice(index, 1) this.$forceUpdate()

November 20, 2020 · 1 min · jiezi

关于vue.js:编程鹿学Vuejs这一篇就够了万字学会通俗易懂

vue概述mvvm模式 image-20201001110548401 M:即Model,模型,包含数据和一些基本操作V:即View,视图,页面渲染后果VM:即View-Model,模型与视图间的双向操作(无需开发人员干预)在MVVM之前,开发人员从后端获取须要的数据模型,而后要通过DOM操作Model渲染到View中。而后当用户操作视图,咱们还须要通过DOM获取View中的数据,而后同步到Model中。 而MVVM中的VM要做的事件就是把DOM操作齐全封装起来,开发人员不必再关怀Model和View之间是如何相互影响的: 只有咱们Model产生了扭转,View上天然就会体现进去。当用户批改了View,Model中的数据也会跟着扭转。把开发人员从繁琐的DOM操作中解放出来,把关注点放在如何操作Model上。 mvvm模式的劣势:低耦合视图(View)能够独立于Model变动和批改,一个ViewModel能够绑定到不同的"View"上,当View变动时Model能够不变,当Model变动时View也能够不变 可重用性能够把一些视图逻辑放在一个ViewModel外面,让多个View重用这段视图逻辑代码 独立开发开发人员能够专一于业务逻辑和数据的开发(ViewModel),设计人员能够专一于页面设计。 而咱们明天要学习的,就是一款MVVM模式的框架:Vue 疾速入门装置vue下载安装下载地址:https://github.com/vuejs/vue 能够下载2.5.16版本https://github.com/vuejs/vue/... 下载解压,失去vue.js文件。能够在页面中间接通过script引入vue.js文件 应用cdn或者也能够间接应用公共的CDN服务: <!-- 开发环境版本,蕴含了用帮忙的命令行正告 --><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>或者: <!-- 生产环境版本,优化了尺寸和速度 --><script src="https://cdn.jsdelivr.net/npm/vue"></script>Vue 入门案例(演示用,不做解说)HTML模板<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>vuejs测试</title>    <script src="node_modules/vue/dist/vue.js"></script></head><body><div id="app">    <h2>{{name}},十分酷!</h2></div><script type="text/javascript"> var app = new Vue({        el: "#app", // el即element,要渲染的页面元素        data: {            name: "Vue测试"        }    });</script></body></html>首先通过new Vue()来创立Vue实例而后构造函数接管一个对象,对象中有一些属性: el :是element的缩写,通过id 选中要渲染的页面元素,本例中是一个 divdata:数据,数据是一个对象,外面有很多属性,都能够渲染到视图中 name :这里指定了一个name属性页面中的 h2 元素中,通过{{name}} 的形式,来渲染刚刚定义的 name 属性更神奇的在于,当你批改name属性时,页面会跟着变动。 双向绑定对方才的案例进行简略批改: <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>vuejs测试</title>    <script src="node_modules/vue/dist/vue.js"></script></head><body><div id="app">    <input type="text" v-model="num">    <h2>      {{name}},十分酷!      有{{num}}个酷炫性能!    </h2></div><script type="text/javascript"> var app = new Vue({        el: "#app", // el即element,要渲染的页面元素        data: {            name: "Vue测试",            num: 1        }    });</script></body></html>在data中增加了新的属性: num在页面中有一个 input 元素,通过 v-model 与 num 进行绑定同时通过 {{num}} 在页面输入能够察看到,输入框的变动引起了data中的num的变动,同时页面输入也跟着变动。 input与num绑定,input的value值变动,影响到了data中的num值页面 {{num}} 与数据num绑定,因而num值变动,引起了页面成果变动。没有任何dom操作,这就是双向绑定的魅力。 事件处理在页面增加一个按钮: <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>vuejs测试</title>    <script src="node_modules/vue/dist/vue.js"></script></head><body><div id="app">    <input type="text" v-model="num">    <button v-on:click="num++">点我</button>    <h2>      {{name}},十分酷!      有{{num}}个酷炫性能!    </h2></div><script type="text/javascript"> var app = new Vue({        el: "#app", // el即element,要渲染的页面元素        data: {            name: "Vue测试",            num: 1        }    });</script></body></html>这里用 v-on 指令绑定点击事件,而不是一般的 onclick ,而后间接操作num一般onclick是无奈间接操作num的Vue 实例创立Vue实例每个 Vue 利用都是通过用 Vue 函数创立一个新的 Vue 实例开始的: var vm = new Vue({ // 选项})在构造函数中传入一个对象,并且在对象中申明各种Vue须要的数据和办法,包含: eldatamethods… …等接下来,一一介绍。 模板或元素每个Vue实例都须要关联一段Html模板,Vue会基于此模板进行视图渲染;能够通过el属性来指定。 例如一段html模板: <div id="app"></div>而后创立Vue实例,关联这个div var vm = new Vue({ el:"#app"})这样,Vue就能够基于id为 app 的div元素作为模板进行渲染了。在这个div范畴以外的局部是无奈应用vue个性的。 ...

November 19, 2020 · 3 min · jiezi

关于vue.js:vant的field组件autofocus属性只生效一次

vant的field组件autofocus属性只失效一次问题形容<van-field autofocus ref="fieldPhone" name="phone" v-model="form.phone" label="手机号码" placeholder="手机号码" :rules="[{ required: true, message: '请输出手机号码' }]"/>应用van-field的autofocus属性,只在第一次进入页面时能胜利focus 解决办法不应用autofocus,改为页面mounted或弹框显示时手动调用van-field提供的focus办法 this.$nextTick(() => { this.$refs.fieldPhone.focus();});

November 19, 2020 · 1 min · jiezi

关于vue.js:vue中watch高级用法deep和immediate

一、handler办法和immdiate属性 watch默认绑定,页面首次加载时,是不会执行的。只有值产生扭转才会执行。 如果想立刻执行怎么办? watch:{ name:{ handler(newName,oldName){ //执行代码 }, immediate:true //true就示意会立刻执行 } }二、deep属性 如果是监听的是对象类型,当手动批改对象的某个属性时,发现是有效的。 这时候就须要deep属性。 data:{ obj:{ a:1 }},watch:{ obj:{ handler(newName,oldName){ //执行代码 }, deep:true //为true,示意深度监听,这时候就能监测到a值变动 }}deep为true,就能够监测到对象中每个属性的变动。 它会一层层遍历,给这个对象的所有属性都加上这个监听器。然而这样性能开销会比拟大,批改任何一个属性,都会登程这个监听器里的handler. 三、deep优化 能够应用字符串模式监听 data:{ obj:{ a:1 }},watch:{ 'obj.a':{ handler(newName,oldName){ //执行代码 }, deep:true //为true,示意深度监听,这时候就能监测到a值变动 }}这样vue就会一层层解析,晓得遇到属性a,而后才给a设置监听函数。

November 19, 2020 · 1 min · jiezi

关于vue.js:Vue源码组件注册

一、理解组件注册的两种形式1.1 全局组件的注册办法//main.js import Vue from 'vue' import App from './App' import router from './router' Vue.config.productionTip = false let Hello = { name: 'hello', template: '这是全局组件hello' } Vue.component('hello', Hello) new Vue({ el: '#app', router, components: { App }, template: '' })下面咱们就通过Vue.component()注册了一个全局组件hello,接下来剖析源码实现的时候也是基于这个例子来进行的。 1.2 部分组件的注册 <template> <div id="app"> <img src="./assets/logo.png"> <HelloWorld/> </div></template><script>import HelloWorld from './components/HelloWorld.vue'export default { name: 'App', components:{ HelloWorld }}</script>像这样就注册了一个HelloWorld的部分组件。 二、全局组件注册的源码1.Vue初始化的时候,会调用initGlobalAPI()//【代码块1】//代码所在文件:src/core/global-api/index.jsexport function initGlobalAPI(Vue: GlobalAPI){ //...省略其余无关代码 initAssetRegisters(Vue) //这个办法就是用于组件注册的办法}2.在initAssetRegisters()办法中执行组件的定义//【代码块2】//代码所在文件:src/core/global-api/assets.jsexport function initAssetRegister(Vue){ ASSET_TYPES.forEach(type=>{ //ASSET_TYPES包含component、directive、filter Vue[type] = function(id, definition){ //...一些条件判断 if(type === 'component' && isPlainObject(definition)){ definition.name = definition.name || id definition = this.options._base.extend(definition) //将definition转换为一个继承于Vue的构造函数 } //...其余类型的解决 this.options[type+'s'][id] = definition //将这个构造函数挂载到Vue.options.components上 return definition } })}此时,咱们能够单步调试一下咱们下面的例子,来看一下definition一开始是什么,以及执行挂载后Vue.options变成了什么样子: ...

November 19, 2020 · 2 min · jiezi

关于vue.js:uniapp无限级树形结构组件多选组件支持搜索无限级面包屑类型导航

间接上效果图 性能介绍1、反对单选和多选(选中返回的格局均为数组),多级组织 更新日志2.0.0(2020-11-18)1、修复多选不能用问题 2、修复面包屑不会主动置右的问题,3修复数据初始失败问题 1.2.2(2020-10-24)1.增加单选模式下抉择叶子节点属性,nodes,为true时只能抉择叶子节点,为false时,能够抉择任意一项 应用阐明:1、引入组件import tree from '@/components/xiaolu-tree/tree.vue'; 注册组件在页面援用组件参数阐明参数类型是否必填默认值阐明treesArray是[ ]传入的数据,见上面的例子childrenstring否children指定选项的子选项为选项对象的某个属性值searchIfBoolean否true是否开启搜寻框isCheckBoolean否true是否开启选钟操作,多选propsObject否{label:'name',children:'children'}参数配置,具体见下表props参数阐明参数类型是否必填默认值阐明labelstring否name指定选项标签为选项对象的某个属性值childrenstring否children指定选项的子选项为选项对象的某个属性值multipleBoolean否true值为true时为多选,为false时是单选checkStrictlyBoolean否false在单选模式下,你只能抉择叶子节点;而在多选模式下,启用该性能后(checkStrictly为false时),可让父子节点勾销关联,抉择任意一级选项。留神:单选和多选都是以数组传值 办法办法名参数阐明sendValuevalval 接管选中的数据留神:trees数据须要带有checked字段默认选中须要传checkList并调用checks办法 获取选中的值(重要) <tree :checkList="checkList" v-if="tree.length>0" :props="prop" @sendValue="confirm" :isCheck="true" :trees="tree" /> //获取选中的 confirm(val) { this.checkList=val },点击确认返回第一个页面时传出选中的值(蕴含小程序和h5的传值办法)·获取的数据返回的是一个数组,蕴含一个选中的对象的所有字段,若只须要某个字段,遍历一下就好 backConfirm(){ var pages = getCurrentPages(); var currPage = pages[pages.length - 1]; //以后页面 var prevPage = pages[pages.length - 2]; //上一个页面 //h5写法 prevPage.query =this.checkList //小程序写法 //prevPage.$vm.query =this.checkList uni.navigateBack(); }获取组件地址插件市场:点击跳转GitHub:点击跳转 结语:老手第一次插件,写法比拟low,望各位大佬多包涵。有不足之处欢送指出。 码 有问题能够加我qq:122720267

November 18, 2020 · 1 min · jiezi

关于vue.js:文本内容超过N行折叠并显示查看全部

本文公布于我的集体网站:https://wintc.top/article/58,转载请注明。多行文本超过指定行数暗藏超出局部并显示“...查看全副”是一个常遇到的需要,网上也有人实现过相似的性能,不过还是想本人写写看,于是就写了一个Vue的组件,本文简略介绍一下实现思路。 遇到这个需要的同学能够尝试一下这个组件,反对npm装置应用: 组件地址:https://github.com/Lushenggang/vue-overflow-ellipsis在线体验:https://wintc.top/laboratory/#/ellipsis 一、需要形容        长度不定的一段文字,最多显示n行(比方3行),不超过n行失常显示;超过n行则在最初一行尾部显示“开展”或“查看全副”之类的按钮,点击按钮则开展显示全部内容,或者跳转到其它页面展现所有内容。         预期成果如下: 二、实现原理        纯CSS很难完满实现这个性能,所以还得借助JS来实现,实现思路大体类似,都是判断内容是否超过指定行数,超过则截取字符串的前x个字符,而后而后和“...查看全副”拼接在一起,这里的x即截取长度,须要动静计算。         想通过上述计划实现,有几个问题须要解决: 怎么判断文字是否超过指定行数如何计算字符串截取长度动静响应,包含响应页面布局变动、字符串变动、指定行数变动等        上面具体钻研一下这些问题。 1. 怎么判断一段文字是否超过指定行数?        首先解决一个小问题:如何计算指定行数的高度?我首先想到的是应用textarea的rows属性,指定行数,而后计算textarea撑起的高度。另一个办法是将行高的计算值与行数相乘,即失去指定行数的高度,这个方法我没尝试过,然而想必可行。         解决了指定行数高度的问题,计算一段文字是否超过指定行数就很容易了。咱们能够将指定行数的textarea应用相对定位absolute脱离文档流,放到文字的下方,而后通过文本容器的底部与textarea的底部相比拟,如果文本容器的底部更靠下,阐明超过指定行数。这个判断能够通过getBoundingClientRect接口获取到两个容器的地位、大小信息,而后比拟地位信息中的bottom属性即可。         能够这样设计DOM构造: <div class="ellipsis-container"> <div class="textarea-container"> <textarea rows="3" readonly tabindex="-1"></textarea> </div> {{ showContent }} <-- showContent示意字符串截取局部 --> ... 查看更多 </div>        而后应用CSS管制textarea,使其脱离文档流并且不能被看到以及被触发鼠标事件等(textarea标签中的readonly以及tabIndex属性是必要的): .ellipsis-container text-align left position relative line-height 1.5 padding 0 !important .textarea-container position absolute left 0 right 0 pointer-events none opacity 0 z-index -1 textarea vertical-align middle padding 0 resize none overflow hidden font-size inherit line-height inherit outline none border none2.如何计算字符串截取长度x——双边迫近法(二分思维)        只有能够判断一段文字是否超过指定行数,那咱们就能够动静地尝试截取字符串,直到找到适合的截断长度x。这个长度满足从x的地位截断字符串,前半部分+“...查看全副”等文字刚好不会超出指定行数N,然而多截取一个字,则会超出N行。最直观的想法就是间接遍历,让x从0开始增长到显示文本总长度,对于每个x值,都计算一次文字是否超过N行,没超过则加持续遍历,超过则取得了适合的长度x - 1,跳出循环。当然也能够让x从文本总长度递加遍历。 ...

November 18, 2020 · 2 min · jiezi

关于vue.js:总结一下大佬意识

问题所在 细节问题

November 18, 2020 · 1 min · jiezi

关于vue.js:vue缓存页面keepAlive的坑数据不刷新只缓存第一次进入的页面数据

需要:A进入B,依据不同id刷新B页面数据,B进入C,C返回B,如果C有操作数据,则返回B后刷新B数据,否则B页面不刷新;第一次尝试*思路是从C进入B,缓存B,其余页面进入B,不缓存 B页面: beforeRouteLeave(to, from, next) { from.meta.keeplive= false; next();},activated(){ //依据$route.meta},C页面 // 返回上一页路由不刷新问题 beforeRouteLeave (to, from, next) { to.meta.type=this.showChange; to.meta.keeplive = true; if(this.edit){ to.meta.isrefer=true;//编辑胜利后刷新B页面的数据,状态码 }else{ to.meta.isrefer=false; } next(); },实践上没故障啊,可是问题来了第一次,A进B,B进C,C返回B,缓存了B 第二次,A进B,B会刷新,B再进C,C再返回B,B的数据是第一次进入B的时候的数据 起因:因为B的页面参数还是第一次缓存的时候的参数,所以,无论怎么从新加载数据,数据还是原来第一进入的B的数据,因为申请的参数素来没有扭转。 解决方案A页面 beforeRouteLeave (to, from, next) { to.meta.isrefer = true;//刷新B的数据 to.meta.type=false; next(); },B页面 beforeRouteEnter(to, from, next){ to.meta.keeplive= true; next(vm=>{ //这里把页面初始值从新赋值,以刷新页面 if(vm.$route.meta.isrefer){ vm.dataList=[]; vm.$route.meta.isrefer=false;//复原初始值 vm.seatList=[] vm.query={ activityId: vm.$route.query.activityId, meetplaceId: vm.$route.query.meetplaceId, } vm.getSeatImgList()//申请数据 } }) },beforeRouteLeave(to, from, next) { from.meta.keeplive= true;//每次进入页面都缓存B next();},C页面与下面不变 ...

November 18, 2020 · 1 min · jiezi

关于vue.js:vue-keepalive-include无效

查看版本确定以后的vue版本的是2.1+ 因为include和exclude是vue2.1.0新增的两个属性. package.json "vue": "^2.5.2",查看name留神,不是router.js中的name,而是单个vue组件中的name属性. 倡议将router.js中的name和vue组件的name保持一致,不要凌乱. 1. export default { 2.    name: "index" 3. } 多层嵌套网上的答案简直都是查看vue组件的name属性,但还是有一个巨坑. 那就是多级嵌套<router-view></router-view>,凡是有超过两个以上的router-view且是父子级关系,请都加上keep-alive,只加一个不会失效. // app.vue <keep-alive include="app,index">   <router-view></router-view> </keep-alive> // other.vue <keep-alive include="app,index">   <router-view></router-view> </keep-alive>

November 18, 2020 · 1 min · jiezi

关于vue.js:vue-事件总线EventBus的概念使用以及注意点

前言vue组件中的数据传递最最常见的就是父子组件之间的传递。父传子通过props向下传递数据给子组件;子传父通过$emit发送事件,并携带数据给父组件。而有时两个组件之间毫无关系,或者他们之间的结构复杂,如何传递数据呢?这时就要用到 vue 中的事件总线 EventBus的概念 公众号:前端印象不定时有送书流动,记得关注~关注后回复对应文字支付:【面试题】、【前端必看电子书】、【数据结构与算法残缺代码】、【前端技术交换群】注释EventBus的简介EventBus又称事件总线,相当于一个全局的仓库,任何组件都能够去这个仓库里获取事件,如图: EventBus的应用废话不多说,间接开始应用EventBus 一、初始化要用EventBus,首先要初始化一个EventBus,这里称它为全局事件总线。 第一种初始化办法import Vue from 'vue'//因为是全局的一个'仓库',所以初始化要在全局初始化const EventBus = new Vue() 第二种初始化办法(本文选用这种初始化办法)//在曾经创立好的Vue实例原型中创立一个EventBusVue.prototype.$EventBus = new Vue() 二、向EventBus发送事件发送事件的语法:this.$EventBus.$emit(发送的事件名,传递的参数) 曾经创立好EventBus后咱们就须要向它发送须要传递的事件,以便其余组件能够向EventBus获取。例子:有两个组件A和B须要通信,他们不是父子组件关系,B事件须要取得A事件里的一组数据data <!-- A.vue 这里是以模块化的形式解说的,即A组件和B组件别离各自一个.vue文件,所以代码中会有导入的语法--><template> <button @click="sendMsg">发送MsgA</button></template><script> export default { data(){ return{ MsgA: 'A组件中的Msg' } }, methods: { sendMsg() { /*调用全局Vue实例中的$EventBus事件总线中的$emit属性,发送事 件"aMsg",并携带A组件中的Msg*/ this.$EventBus.$emit("aMsg", this.MsgA); } }}; </script>三、接管事件接管事件的语法:this.$EventBus.$on(监听的事件名, 回调函数) A组件曾经向全局事件总线EventBus发送了一个aMsg事件,这时B组件就能够去aMsg监听这个事件,并能够取得一些数据。 <!-- B.vue --><template> <!-- 展现msgB --> <p>{{msgB}}</p> </template><script> export default { data(){ return { //初始化一个msgB msgB: '' } }, mounted() { /*调用全局Vue实例中的$EventBus事件总线中的$on属性,监听A组件发送 到事件总线中的aMsg事件*/ this.$EventBus.$on("aMsg", (data) => { //将A组件传递过去的参数data赋值给msgB this.msgB = data; }); }};</script>B组件展现后果: ...

November 17, 2020 · 1 min · jiezi

关于vue.js:vueiview中tree树形组件覆盖点击背景色和鼠标移入背景色

vue+iview中tree树形组件笼罩点击背景色和鼠标移入背景色1.开发环境 vue+iview2.电脑系统 windows10专业版3.在应用vue+iview开发的过程中,咱们依据需要会应用到树形组件,上面我来分享一下,心愿对你有所帮忙~!4.在template中增加如下代码: <Scroll style="width: 100%" height="760"> <Tree @on-select-change="chentreelick" :data="treedata" expand-node ></Tree></Scroll>5.效果图如下: 留神:第一个 背景色是鼠标移入的成果,第二个背景色 是点击之后的成果6.咱们会感觉这个款式会比拟难看,怎么笼罩默认的款式呢?代码如下: .ivu-tree-title-selected,.ivu-tree-title-selected:hover{ background-color: rgb(81, 97, 187) !important;}.ivu-tree-title:hover{ background-color: rgb(81, 97, 187) !important}7.笼罩之后的效果图如下:8.本期的分享到了这里就完结啦,心愿对你有所帮忙,让咱们一起致力走向巅峰!

November 17, 2020 · 1 min · jiezi

关于vue.js:快速手写自己的Vuex

在浏览Vuex源码之前,因为Vuex的api和应用性能稍微简单,默认认为实现起来相当简单,望而却步。然而通过深刻学习源码,发现外围性能联合vue实现起来十分奇妙,也就外围几行代码,直呼外行。本文也就100左右行代码就能疾速手写本人的Vuex代码! 前言Vuex 是⼀个专为 Vue.js应⽤程序开发的状态管理模式。它采⽤集中式存储管理应⽤的所有组件的状态,并以相应的规定保障状态以⼀种可预测的⽅式发⽣变动。那么Vuex和单纯的全局对象有什么不同呢? Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发⽣变 化,那么相应的组件也会相应地失去⾼效更新。不能间接扭转 store 中的状态。扭转 store 中的状态的唯⼀路径就是显式地提交 (commit) mutation。这样使得咱们能够⽅便地跟踪每⼀个状态的变动,从⽽让咱们可能实现⼀些⼯具帮忙我 们更好地理解咱们的应⽤。 通过以上两点认知咱们来疾速实现本人的Vuex! Vuex 初始化为什么在vue实例化的时候要传入store去实例化呢?那是为了让vue所有的组件中能够通过 this.$store来获取该对象,即 this.$store 指向 store 实例。 // Store 待实现const store = new Store({ state: { count: 0, num: 10})new Vue({ el: '#app', store: store // 此处的 store 为 this.$options.store})Vuex提供了install属性,通过Vue.use(Vuex)来注册。 const install = function (Vue) { Vue.mixin({ beforeCreate() { if (this.$options.store) { Vue.prototype.$store = this.$options.store } } })}Vue全局混⼊了⼀个 beforeCreated 钩⼦函数, options.store 保留在所有组件的 this.$store 中,这个 options.store 就是咱们在实例化 Store 对象的实例。Store 对象的构造函数接管⼀个对象参数,它蕴含 actions 、 getters 、 state 、 mutations 等核⼼概念,接下来咱们一一实现。 ...

November 15, 2020 · 5 min · jiezi

关于vue.js:vue项目本地使用icon

vue我的项目本地应用icon1.开发环境 vue2.电脑系统 windows10专业版3.在应用vue开发的过程中,咱们常常会应用到字体图标,在这里我抉择的是阿里巴巴矢量图标库,上面我来分享一下,在vue我的项目中导入本地应用icon的办法,心愿对你有所帮忙。4.将图标下载至本地5.删除红框局部6.把其余文件,复制到本人的我的项目中,在assets中新建文件并且把方才拷贝的文件放到新建目录下,构造如下:7.在main.js中增加如下代码: import './assets/chenicon/iconfont.css';//进行全局导入,这样我的所以组件中都能够应用;如果整个我的项目只有一个页面应用了,能够单个页面进行导入8.在vue组件中应用办法,增加如下代码: <i class="iconfont icongouwuche"></i><i class="iconfont iconyemian-copy"></i>9.成果如下:10.本期的分享到了这里就完结啦,是不是很nice,心愿对你有所帮忙,让咱们一起致力走向巅峰!

November 13, 2020 · 1 min · jiezi

关于vue.js:关于-Vuejs-30-UI-Library-elementplus-官网部分-Demo-失效汇总

Element Plus A Vue.js 3.0 UI Library.一、Card 卡片Card 卡片之根底 Demo - header 生效生效起因含有 heder 的示例代码中,设置 header 的形式是采纳的已废除的 slot attribute 语法。 <div slot="header"> //...</div> 解决形式在向具名插槽提供内容的时候,在 <template> 元素上应用 v-slot 指令,并以 v-slot 的参数的模式提供其名称。 <el-card shadow="shadow"> <template v-slot:header> // ... </template> <div v-for="o in 4" :key="o" class="text item"> {{'列表内容 ' + o }} </div></el-card>备注:v-slot:header 能够简写成 #header 。 二、NavMenu 导航菜单所有 Demo 生效生效起因同上,应用具名插槽的中央采纳的是已废除的 slot attribute 语法。 <template slot="title"> <i class="el-icon-location"></i>导航一</template><span slot="title">分组一</span>... 解决形式在向具名插槽提供内容的时候,在 <template> 元素上应用 v-slot 指令,并以 v-slot 的参数的模式提供其名称。 ...

November 13, 2020 · 2 min · jiezi

关于vue.js:Error-Cannot-find-module-‘commander‘

1、谬误形容 2、谬误起因 查看vue-cli版本的提醒,找不到模块commander 3、解决办法 方法1:重新安装commander, npm install commander --save  重点提醒:不要再node装置的目录去装,否在不起作用; 方法2:全局装置vue-cli, 提醒:然而我试了没啥用 参考:https://blog.csdn.net/you23hai45/article/details/80951981

November 13, 2020 · 1 min · jiezi

关于vue.js:还在为写vue文件烦恼吗快来用dotvuecli交互式生成吧

写过vue的同学都晓得,单文件组件.vue在开发中应用频率是十分高的。如果不想再手写或者CV的话,无妨尝试一下我写的这个小工具,反对交互式生成.vue文件,生成的过程只须要答复一些小问题即可。 目前仅反对vue2和局部属性,如果对这个我的项目感兴趣的话,欢送提issue,欢送提pr(适合的话我会第一工夫merge),或者fork一份改成本人想要的成果吧 我的项目地址:https://github.com/FrankKai/dot-vue-cli dot-vue-cliVue2.x single file component .vue generator. featuresSet name, props, data, computed, watch and choose lifecycles, methods by interactive command line.Import vuex, mapState, mapMutations, mapActions by interactive command line.installnpm install -g dot-vue-cliusagedot-vueType dot-vue in terminal and follow the instructions. process1.generate template configs{ filename: "foo", name: "foo", data: true, "data details": "a,b,c", computed: true, "computed details": "a,b,c", watch: true, "watch details": "a,b,c", methods: true, "methods details": "a,b,c", "vue lifecycle hooks": ["mounted", "destroyed"], "vuex helpers": ["mapState", "mapMutations", "mapActions"],};2.generate target .vue file based on template literals ...

November 13, 2020 · 1 min · jiezi

关于vue.js:Vue

vue-cli卸载Vue2.0 npm uninstall -g vue-cli 装置vue-cli 查看版本 创立我的项目 创立我的项目的配置通过高低箭头可设置选项,按回车键确定 运行我的项目 留神 local:集体创立的Vue我的项目Network:团队创立的Vue我的项目 Vue目录剖析目录 目录解析 数据绑定数据绑定的常见形式便是{{}},也被称为插值表达式数据绑定的形式v-text:相比插值表达式更加简洁,且没有闪动问题v-html:填充HTML片段,具备跨站脚本攻打v-pre:跳过编译过程,显示原始信息<template><!-- vue模板内容中 所有的内容都是要被一个根节点包裹--><div id="app"> <div>{{name}}</div> <div v-text="html"></div> <div v-html='html'></div> <div v-pre>{{msg}}</div></div></template><script>export default { name: '#app', // data:业务逻辑外面定义的数据 data() { return { name: '尧子陌', text: 'v-text', html: '<h1>v-html</h1>', } }}</script><style></style> Vue中的循环v-for v-for 指令须要以 site in sites 模式的非凡语法, sites 是源数据数组并且 site 是数组元素迭代的别名。 v-for 能够绑定数据到数组来渲染一个列表: <template><!-- vue模板内容中 所有的内容都是要被一个根节点包裹--><div id="app"> <ul> <li v-bind:key='item.id' v-for='(item) in list '>{{item}}</li> <li v-bind:key="item.id" v-for="(item,index) in list2"> {{item.title}} {{index}} </li> <li v-bind:key='item.id' v-for="(item,index) in list3"> {{item.catch +'----'+ index}} <ol> <li v-bind:key="fruit" v-for="fruit in item.list4"> {{fruit.title}} </li> </ol> </li> </ul></div></template><script>export default { name: '#app', // data:业务逻辑外面定义的数据 data() { return { list: ['apple', 'banner', 'cat', 'pear'], list2: [{ 'title': 'apple' }, { 'title': 'apple' }, { 'title': 'apple' }], list3: [{ 'catch': '国内新闻', list4: [{ 'title': 'apple' }, { 'title': 'apple' }, { 'title': 'apple' }] }] } }}</script><style></style> ...

November 13, 2020 · 1 min · jiezi

关于vue.js:在VS-Code-中调试Vuejs

步骤关上vscode,装置Debugger for Chrome应用vue cli3创立vue利用我的项目根门路增加"vue.config.js" 文件module.exports = { configureWebpack: { devtool: 'source-map' }}.vscode文件中的launch.json增加: "version": "0.2.0", "configurations": [ { "type": "chrome", "request": "launch", "name": "vuejs: chrome", "url": "http://localhost:8080", "webRoot": "${workspaceFolder}/src", "breakOnLoad": true, "sourceMapPathOverrides": { "webpack:///src/*": "${webRoot}/*" } } ]}设置一个断点在根目录关上你习用的终端并应用 Vue CLI 开启这个利用:npm run serve来到 Debug 视图,抉择“vuejs:chrome/firefox”配置,而后按 F5 或点击那个绿色的 play 按钮。 随着一个新的浏览器实例关上 http://localhost:8080,你的断点当初应该被命中了

November 13, 2020 · 1 min · jiezi

关于vue.js:vue-同一页面多次引用封装好的echarts组件

在咱们在封装了echarts组件之后,须要在同一个页面中引入屡次时,会呈现数据笼罩,id不能复用等问题 解决办法:首先把id删掉,增加ref属性 <div class="bar" ref="bar"></div>而后批改js: 初始版本: this.barCharts = echarts.init(document.getElementById("bar"));批改后: this.barCharts = echarts.init(this.$refs.bar);解决!

November 12, 2020 · 1 min · jiezi

关于vue.js:一个基于JavaSpringBoot-Uniapp的开源商城项目

我所在的开发团队绝对还是比拟厉害的,在码云上已经开源过一个PHP版的基于TP6.0+vue的开源商城我的项目,取得了不错的Start量,也有很多开发者参加进来一起欠缺这个我的项目,通过几年的保护目前曾经绝对十分稳固的我的项目,大大降低了大家二开造轮子的工夫精力老本,随着我的项目的不断完善,有很多JAVA开发者就提出能不能用这个PHP版的架构再开源一个java版的商城零碎,通过一众开发者的日夜辛苦,以及大家踊跃的反馈测试,明天终于能够告诉大家,实现啦!????????开源啦!???????? 开源地址所有的代码、文件全副都开源到 Gitee仓库中,并没有任何藏着掖着的行为,不会说短少哪个页面或者某个重要性能,包含前后端的前端源码都开源在我的项目中,并且接口文档也十分仔细的给大家打包进了我的项目,次要是为了不便大家能疾速的上手及二次开发 当然,也心愿感兴趣的敌人能够找找其中的问题,提一些 pr 或者 issue,让这个开源我的项目可能缩小问题并且放弃提高。 crmeb_java电商营销零碎Gitee开源地址crmeb_java电商营销零碎GitHub开源地址crmeb_php电商营销零碎开源地址预览地址本我的项目曾经部署到了线上供大家测试预览,相干挪动端演示地址以及后盾演示地址在开源仓库里能够看到。 备注:进入演示站点,为了不便大家测试,给的演示权限就是超管的权限,所以请大家不要随便改明码!请大家不要随便改明码!请大家不要随便改明码!技术栈CRMEB商城JAVA版,SpringBoot + Maven + Swagger + Mybatis Plus + Redis + Uniapp +Vue 蕴含挪动端、小程序、PC后盾、Api接口;有产品、用户、购物车、订单、积分、优惠券、营销、余额、权限、角色、零碎设置、组合数据、可利落拽的form表单等模块,大量的缩小了二开的老本。 SprinBootMavenSwaggerMybatis PlusRedisUniappVueVue-RouterVuex 次要个性有具体的代码正文,有残缺零碎手册 SpringBoot框架应用SpringBoot框架框架开发前端采纳Vue CLI框架前端应用Vue CLI框架nodejs打包,页面加载更晦涩,用户体验更好标准接口标准接口、前后端拆散,二次开发更不便反对队列升高流量顶峰,解除耦合,高可用无缝事件机制行为扩大更不便,不便二次开发数据表格导出Excel数据导出,导出表格更加好看可视;数据统计分析后盾应用ECharts图表统计,实现用户、产品、订单、资金等统计分析弱小的后盾权限治理后盾多种角色、多重身份权限治理,权限能够管制到每一步操作弱小的表单生成控件能够自在配置开发表单,缩小前端工作量,后端接口对立调预览图本我的项目齐全采纳前后端拆散开发,实际上蕴含了三个我的项目,后盾前端我的项目,前台前端我的项目以及后端接口我的项目,前台前端应用的是uni-app,特地不便大家二次编译适配多个平台,以及封装APP。 后盾界面 前台界面 我的项目构造具体阐明 crmeb │ ├─ crmeb_log 日志 │ ├─ image 图片长期文件夹 │ ├─ /src/main/ │ ├─ java/com │ ├─ aop 切片 │ ├─ common 专用根底类 │ ├─ constants 常量类 │ ├─ exception 异样 │ ├─ filter 过滤器 │ ├─ interceptor 拦截器 │ ├─ utils 工具类 │ ├─ zbkj.crmeb 模块服务 │ ├─ article 文章 │ ├─ authorization 后盾用户登录,token │ ├─ category 分类服务 │ ├─ config 配置 │ ├─ export 导出 │ ├─ express 物流 │ ├─ finance 资金 │ ├─ front 对挪动端接口 │ ├─ marketing 营销 │ ├─ payment 领取 │ ├─ pub 公共服务(可依据本人状况决定此处是否暗藏) │ ├─ sms 短信 │ ├─ statistics 统计 │ ├─ store 产品、订单 │ ├─ system 零碎服务 │ ├─ task 打算工作 │ ├─ upload 上传 │ ├─ user 用户 │ ├─ validatecode 验证码 │ ├─ wechat 微信相干 │ └─ wechatMessage 微信音讯 │ ├─resource 资源文件 │ ├─ mapper mapper文件 按模块分文件夹 │ ├─ application-*.yml 配置文件,在启动我的项目的时候应用 └─sql sql文件目录代码奉献这个版本曾经迭代到了1.2版,尽管曾经测试过几轮,优化修复了已知的很多bug,目前曾经新增了秒杀性能和财务管理性能,还在继续欠缺,应该还会有一些问题存在,也心愿大家能够提出一些优化倡议,能够提交issue,也能够给我留言或者到交换群里间接艾特群主。 ...

November 12, 2020 · 1 min · jiezi

关于vue.js:vant-单选按钮-怎么实现在单元格中并排放

须要实现效果图: 实现过程:依附vant本身的布局代码: <van-cell title="性别"> <van-radio-group v-model="sex" > <van-row> <van-col span="12"> <van-radio name="M">男</van-radio> </van-col> <van-col span="12"> <van-radio name="F">女</van-radio> </van-col> </van-row> </van-radio-group></van-cell>over

November 12, 2020 · 1 min · jiezi

关于vue.js:关于vue更新数组项你知道多少

vue 中如何更新数组某一项,这是开发中常常遇到的问题 例如:data 外面有个 list 数组,数组外面有三项 export default { data() { return { list: [ 'foo', 'bar', 'baz' ] } }}如何将第二项的值更新为 'jerry' 不少小伙伴可能都试过 this.list[1] = 'jerry' ,但遗憾的是页面并不会更新这种办法的确扭转了 list[1] 的值,但没法触发页面更新 那么在 Vue 中,如何更新数组某一项呢?上面是总结的一些办法: 数组原生办法Array.prototype.splice 被称为数组最弱小的办法,具备删除、减少、替换性能,能够用 splice 来更新 this.list.splice(1, 1, 'jerry')为什么 splice 能够触发更新?Vue 将被侦听的数组(这里就是list)的变更办法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的办法包含: push()pop()shift()unshift()splice()sort()reverse()splice 不再是数组原生办法了,而是 Vue 重写过的办法局部源码: const methodsToPatch = [ 'push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse']/** * Intercept mutating methods and emit events */methodsToPatch.forEach(function (method) { // cache original method const original = arrayProto[method] def(arrayMethods, method, function mutator (...args) { const result = original.apply(this, args) const ob = this.__ob__ let inserted switch (method) { case 'push': case 'unshift': inserted = args break case 'splice': inserted = args.slice(2) break } if (inserted) ob.observeArray(inserted) // notify change ob.dep.notify() return result })})能够看到,splice 除了执行自身的逻辑(original.apply(this, args))之外,会把插入的值变成响应式对象(observeArray(inserted)),而后调用 ob.dep.notify() 手动触发依赖告诉。详情src/core/observer/array.js ...

November 12, 2020 · 3 min · jiezi

关于vue.js:Vue通过引入cdn方式请求接口渲染数据axios渲染数据

这个不须要npm搭建脚手架装置Vue,只须要简略引入Vue的cdn链接,即可实现,通过引入Axios进行渲染数据到html页面。 index.html<!DOCTYPE html><html><head><meta charset="utf-8"><title>Vue axios 渲染数据</title><script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script><script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script><style type="text/css">[v-cloak] { display: none;}</style></head><body><div id="app" v-cloak> <h1>Vue Cdn Axios 渲染数据</h1> <div v-for="site in info"> {{ site.title }}<br/> {{ site.url }}<br/><br/> </div></div><script type = "text/javascript">new Vue({ el: '#app', data () { return { info: null } }, mounted () { axios .get('./data.json') .then(response => (this.info = response.data.list)) // 把后果集传到info这个数组 .catch(function (error) { console.log(error); }); }})</script></body></html>data.json{ "list": [ { "title":"百度一下,你就晓得","url":"www.baidu.com"}, { "title":"让天下没有难做的生意","url":"www.taobao.com"}, { "title":"再小的个体,也是一个品牌","url":"www.weixin.com"} ]}demo ...

November 11, 2020 · 1 min · jiezi

关于vue.js:基于vue-pc端模态框组件vue-layer弹窗

介绍vlayer 一款交融Alert|Dialog|Modal|Message|Notify|Popover|Toast|ActionSheet等泛滥性能的桌面端弹出框组件。在设计开发之初,参考借鉴了Layer弹层插件、antd及iView等组件库。 疾速开始在main.js中引入弹窗组件。 import VLayer from './components/vlayer';Vue.use(VLayer);提供了标签式和函数式2种可供选择的调用形式。 <v-layer v-model="isConfirm" title="题目内容" content="<div style='color:#06f;padding:15px;'>弹窗内容信息!</div>" xclose z-index="2002" lockScroll="false" resize dragOut :btns="[ {text: '勾销', click: () => isConfirm=false}, {text: '确定', style: 'color:#f90;', click: handleFn}, ]"/>因为vlayer挂载了全局函数,反对函数式写法。 let $el = this.$vlayer({ title: '题目内容', content: '<div style='color:#06f;padding:15px;'>弹窗内容信息!</div>', xclose: true, zIndex: 2002, lockScroll: false, resize: true, dragOut: true, btns: [ {text: '勾销', click: () => { $el.close(); }}, {text: '确定', click: () => this.handleFn()}, ]});成果预览 参数配置vlayer反对多达30+种参数任意配置。 @@默认参数v-model 以后组件是否显示title 题目content 内容(反对自定义插槽内容)type 弹窗类型(toast | footer | actionsheet | android/ios | contextmenu | drawer | iframe | message/notify/popover)layerStyle 自定义弹窗款式icon toast图标(loading | success | fail)shade 是否显示遮罩层shadeClose 是否点击遮罩时敞开弹窗lockScroll 是否弹窗呈现时将 body 滚动锁定opacity 遮罩层透明度xclose 是否显示敞开图标xposition 敞开图标地位(left | right | top | bottom)xcolor 敞开图标色彩anim 弹窗动画(scaleIn | fadeIn | footer | fadeInUp | fadeInDown | fadeInLeft | fadeInRight)position 弹出地位(auto | ['100px','50px'] | t | r | b | l | lt | rt | lb | rb)drawer 抽屉弹窗(top | right | bottom | left)follow 追随元素定位弹窗(反对元素.kk #kk 或 [e.clientX, e.clientY])time 弹窗主动敞开秒数(1、2、3)zIndex 弹窗层叠(默认8080)topmost 置顶以后窗口(默认false)area 弹窗宽高(默认auto)设置宽度area: '300px' 设置高度area:['', '200px'] 设置宽高area:['350px', '150px']maxWidth 弹窗最大宽度(只有当area:'auto'时,maxWidth的设定才无效)maximize 是否显示最大化按钮(默认false)fullscreen 全屏弹窗(默认false)fixed 弹窗是否固定drag 拖拽元素(可定义选择器drag:'.xxx' | 禁止拖拽drag:false)dragOut 是否容许拖拽到窗口外(默认false)resize 是否容许拉伸尺寸(默认false)btns 弹窗按钮(参数:text|style|disabled|click)------------------------------------------@@组件式事件open 关上弹出层时触发(@open="xxx")close 敞开弹出层时触发(@close="xxx")------------------------------------------@@函数式事件onOpen 关上弹窗回调onClose 敞开弹窗回调vlayer弹窗模板 ...

November 11, 2020 · 5 min · jiezi

关于vue.js:Vue项目自适应页面配置

开发我的项目须要自适应页面咱们能够在根目录创立utils文件夹,在文件夹创立rem.js文件 // 设置 rem 函数(function () { function setRem () { // 1920 默认大小16px;每个元素px根底上/16 const htmlWidth = document.documentElement.clientWidth || document.body.clientWidth document.documentElement.style.fontSize = htmlWidth * 16 / 1920 + 'px' } // 初始化 setRem() window.addEventListener('resize', setRem, false)})()而后引入到main.js import '@/utils/rem'

November 10, 2020 · 1 min · jiezi

关于vue.js:学了这-7-个-CSS-属性我的-CSS-技能又进步啦

作者:Mustapha Aouas 译者:前端小智起源:dev点赞再看,养成习惯本文 GitHub https://github.com/qq44924588... 上曾经收录,更多往期高赞文章的分类,也整顿了很多我的文档,和教程材料。欢送Star和欠缺,大家面试能够参照考点温习,心愿咱们一起有点货色。 大家都说简历没我的项目写,我就帮大家找了一个我的项目,还附赠【搭建教程】。 学习CSS是构建难看网页的一种形式。 然而,在学习过程中,咱们偏向于(大部分工夫)限度本人,一遍又一遍地应用雷同的属性。 毕竟,咱们是一种习惯性的动物,咱们会应用本人习惯且相熟的货色。 因而,在这篇文章中,向你介绍7个 比拟少见且好用的 CSS 属性,心愿对你有所帮忙。 1. vertical-alignCSS 的属性 vertical-align 用来指定行内元素(inline)或表格单元格(table-cell)元素的垂直对齐形式。 就像定义说的,这个属性容许你垂直对齐文本。它对于程序指示器(st, nd等)、须要的输出星号(*)或没有正确居中的图标特地有用。vertical-align取其中一个值:super | top | middle | bottom | baseline (default) | sub | text-top | text-bottom,或从基线开始的长度(px,%, em, rem等等)。 baseline: 使元素的基线与父元素的基线对齐。HTML标准没有具体阐明局部可替换元素的基线,如<textarea> ,这意味着这些元素应用此值的体现因浏览器而异。 sub:使元素的基线与父元素的下标基线对齐。 super:使元素的基线与父元素的上标基线对齐。 text-top:使元素的基线与父元素的上标基线对齐。 text-bottom:使元素的底部与父元素的字体底部对齐。 middle:使元素的中部与父元素的基线加上父元素x-height(译注:x高度)的一半对齐。 留神 vertical-align 只对行内元素、表格单元格元素失效:不能用它垂直对齐块级元素。 资源:MDN。 2. writing-mode writing-mode 属性定义了文本程度或垂直排布以及在块级元素中文本的前进方向。为整个文档设置书时,应在根元素上设置它(对于 HTML 文档应该在 html 元素上设置)。 它采纳以下值之一horizontal-tb (default) | vertical-rl | vertical-lr。 ...

November 10, 2020 · 1 min · jiezi

关于vue.js:Vue路由权限控制分析

本文已获作者受权转载 作者:低微前端原文:https://juejin.im/post/689229... 前言自己在公司次要负责中后盾零碎的开发,其中路由和权限校验算是十分重要且最为根本的一环。理论开发我的项目中,对于登录和路由权限的管制参照了vue-element-admin这个明星我的项目,并在此基础上基于业务进行了整合,接下来我会以这个我的项目为例,认真地分析整个路由和权限校验的过程,也算是对这个知识点的一些总结。 我的项目总体目录构造进入明天主题之前,咱们先来梳理下整个我的项目,src 目录下的。 api: 接口申请assets: 动态资源components: 通用组件directive: 自定义指令filters: 自定义过滤器icons: 图标layout: 布局组件(页面架构外围)router: 路由配置(路由权限外围模块)store: 状态治理styles: 款式文件utils: 工具办法views: 页面组件permission.js 权限治理对这我的项目感兴趣的同学能够自行,有针对性地学习,除了路由权限校验的性能以外,也蕴含了很多有意思的性能,置信可能学到不少货色。 路由权限管制逻辑路由解决流程图 路由 2.png 路由解决源码剖析咱们先找到 permission.js 文件,此处定义全局路由守卫,也是路由权限中十分要害的外围代码。为不便大家浏览,只摘取了跟路由相干的代码 import router from './router'import store from './store'import { Message } from 'element-ui'import NProgress from 'nprogress' // progress barimport 'nprogress/nprogress.css' // progress bar styleimport { getToken } from '@/utils/auth' // get token from cookie NProgress.configure({ showSpinner: false }) // NProgress Configuration const whiteList = ['/login', '/auth-redirect'] // 白名单配置 router.beforeEach(async(to, from, next) => { // start progress bar NProgress.start() // 有token if (hasToken) { if (to.path === '/login') // 如果以后门路为/login,重定向到首页 next({ path: '/' }) NProgress.done() // hack: https://github.com/PanJiaChen/vue-element-admin/pull/2939 } else { // determine whether the user has obtained his permission roles through getInfo const hasRoles = store.getters.roles && store.getters.roles.length > 0 if (hasRoles) { next() } else { try { // 获取用户信息 const { roles } = await store.dispatch('user/getInfo') // 依据用户的角色,动静生成路由 const accessRoutes = await store.dispatch('permission/generateRoutes', roles) // 动静增加路由 (将根本的路由信息跟动静路由进行合并) router.addRoutes(accessRoutes) // 持续拜访 next({ ...to, replace: true }) } catch (error) { // 删除token await store.dispatch('user/resetToken') Message.error(error || 'Has Error') // 重定向到登录页面 next(`/login?redirect=${to.path}`) NProgress.done() } } } } else { // 没有token if (whiteList.indexOf(to.path) !== -1) { // 如果在白名单中,则不须要进行任何校验,间接放行 next() } else { // 如果不存在于白名单中,则重定向到登录页面. next(`/login?redirect=${to.path}`) NProgress.done() } }}) router.afterEach(() => { // finish progress bar NProgress.done()})留神到,代码中的/login?redirect=\${jto.path}, 这里的 redirect 参数次要是用于,在用户登录胜利后进行跳转的页面门路。具体性能在/views/login/index.vue 文件下 ...

November 9, 2020 · 3 min · jiezi

关于vue.js:Vue组件

Vue组件化开发组件化开发思维组件祖册Vue调试工具用法组件间数据交互组件插槽基于组件的案例组件化的开发思维编程中的组件化开发思维 一个组件就是一个性能,多个组件组成一个残缺的APP,抽取一个组件并不会影响其它组件的运行。 组件化标准: Web Components官网:https://developer.mozilla.org... 组件的注册组件的注册<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue组件的应用</title></head><body> <div id="app"> <button-count></button-count> <button-count></button-count> <button-count></button-count> <button-count></button-count> </div></body><script src="../vue.js"></script><script> Vue.component('button-count', { data() { return { count: '0', } }, template: `<button @click='count++'>点击{{count}}次</button>` }) let vm = new Vue({ el: "#app", data: { } })</script></html> Vue组件注册之注意事项注意事项 dta必须是一个函数组件模板内容必须是单个根元素组件模板内容能够是模板字符串(ES6语法)<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue组件的注意事项</title></head><body> <div id="app"> <button-count></button-count> <button-count></button-count> <button-count></button-count> <button-count></button-count> </div></body><script src="../vue.js"></script><script> Vue.component('button-count', { //data必须是一个函数 data() { return { count: '0', } }, //组件模板的内容必须是单个根元素 且能够应用模板字符串语法 template: ` <div> <button @click='count++'>点击{{count}}次</button> <button>按钮</button> </div> ` }) let vm = new Vue({ el: "#app", data: { } })</script></html> ...

November 9, 2020 · 2 min · jiezi

关于vue.js:Vue之vue语法

(备注阐明:该vue语法常识的梳理是依据vuejs官网文档为外围,辅助一些集体了解或者其余一些案例阐明,所以文章不能说原创,顶天为一个伪原创。) Vue根底语法vue实例let vm = new Vue({ el: '#app', // 示意挂载的DOM节点 data: { // 数据 如果是单个组件 data是一个函数 每个实例的数据是不共享的 message: 'hello vue!' }, methods: { // 外面是vue实例的办法 })插值文本当插入一个数据 进行文本解析 间接应用{{}} <p>{{message}}</p> HTML如果插入的数据进行html解析 应用 v-html <p v-html = 'msg'>{{msg}}</p> <!-- 对应vue实例中的data数据的变量 -->节点属性当你须要对个节点增加属性的话 应用 v-bind: 能够应用简写 : <p v-bind:id = 'newId'></p> <!-- 对应vue实例中的data数据的变量 -->当属性值为布尔值的时候,如果为false 或者 null 或者 undefined 这个属性将不被渲染进去其余所有值都会默认为true值(存在就是真谛) <p :attr = 'attr'></p> <!-- 对应vue实例中的data数据的变量 --> `let app = new Vue({ el: '#app', data: { attr: false } })`javaScript表达式插值外面除了放data属性外 还能够放入js表达式 ...

November 9, 2020 · 2 min · jiezi

关于vue.js:Vue版轮播图

mySwiper.vue <template> <div class="swiper-box" ref="swiperBox"> <!-- 滑块主体 --> <div class="swiper-wrapper" :style="{width: width + 'rem', height: oHeight}" @touchstart="startMove" @touchend="endMove" @touchmove="move" ref="sliderBox"> <slot class="swiper-sliber" /> </div> <!-- 按钮 --> <div class="btn-box" v-if="nextBtn" @touchstart="startMove" @touchend="endMove" @touchmove="move"> <p @click.stop="handleLast" :class="{'click': isClickL}"><i class="iconfont icon-arrow-left-s-fill"></i></p> <p @click.stop="handleNext" :class="{'click': isClickR}"><i class="iconfont icon-arrow-right-s-fill"></i> </p> </div> <!-- 分页文字 --> <div v-if="pagingText !== 'none'" class="paging-text-box" :class="{left: pagingPosition === 'left', right: pagingPosition === 'right'}"> <span class="paging">{{pagingText !== 'none'? pagingText : ''}}{{loop ? length-2 + '/' + index : length + '/' + (index + 1)}}</span> </div> <!-- 分页器 --> <div class="hint-list-box" v-if="paging !== 'none'"> <ul class="hint-list" :class="{center: paging === 'center', right: paging === 'right' }"> <li class="item" v-for="item in hintLen" :key="item" :class="{active: (item === index && loop === true) || (!loop && item === index + 1)}"> </li> </ul> </div> </div></template><script> export default { name: 'my-swiper', data() { return { startX: 0, endX: 0, nowLeft: 0, isClickL: false, isClickR: false, length: 0, index: 0, width: 0, resistance: 1, itemWidth: 0, timer: null, autoTimer: null, zoomTimer: null } }, props: { oHeight: { //设置组件高度 type: String, default: 'auto' }, nextBtn: { //是否显示切换按钮默认false type: Boolean, default: false }, loop: { //是否循环播放默认false type: Boolean, default: false }, paging: { // 是否显示分页器默认none不显示 可选 left, center, right type: String, default: 'center' }, pagingText: { // 是否显示页数 默认none不显示 传入字符串为页数文字前缀 type: String, default: 'none' }, pagingPosition: { //页数定位默认center居中 可选left right type: String, default: 'center' }, defaultIndex: { //默认开始轮播索引 默认0 请填写你传入元素长度内的 数字 type: Number, default: 0 }, automation: { // 是否主动轮播 为0时不主动轮播 默认3000 每3000ms轮播一次 type: Number, default: 0 }, zoom: { // 是否启动zoom模式 要配合子组件宽度一起应用 必须在loop模式下开启 type: Boolean, default: false }, retract: { // 是否缩进显示 要配合子组件宽度一起应用 必须在loop模式下开启 type: Boolean, default: false } }, methods: { // 手指点击时触发办法, 次要记录手指要开始滑动时x坐标用于计算滑动完结与开始的差值, 触控时革除 主动轮播与轮播动画的定时器 startMove(e) { clearInterval(this.timer) // 革除轮播动画定时器 clearInterval(this.autoTimer) // 革除主动轮播定时器 this.startX = e.targetTouches[0].clientX // 获取触控时x坐标 this.nowLeft = this.$refs.sliderBox.offsetLeft // 记录以后滑块left值 }, // 手指拖动时触发的,滑动动画 slider(nowX) { if (this.$refs.sliderBox.offsetLeft > 0 && !this.loop) { // 不是循环模式下 在第一个元素向右拖拽时速度衰减 this.resistance += 0.03 window.console.log(55555) this.$refs.sliderBox.style.left = (nowX - this.startX) / this.resistance + 'px' return } else if (this.$refs.sliderBox.offsetLeft < -this.maxLeft && !this.loop) { // 不是循环模式下 在最初一个元素向左拖拽时速度衰减 this.resistance += 0.03 this.$refs.sliderBox.style.left = this.nowLeft + (nowX - this.startX) / this.resistance + 'px' return } this.$refs.sliderBox.style.left = this.nowLeft + (nowX - this.startX) + 'px' }, // 依据子元素计算 滑块宽度 getItemDom() { let itemArr = Array.prototype.slice.call(this.$refs.sliderBox.children, 0) this.length = this.$refs.sliderBox.children.length itemArr.forEach((ele) => { this.width += parseFloat(ele.style.width) }) }, // zoom模式下滑动动画 zoomMove(nowX) { if (nowX - this.startX < 0) { let scale = (-(nowX - this.startX) * 0.001) + 0.8 > 1 ? 1 : (-(nowX - this.startX) * 0.001) + 0.8 let opacity = (-(nowX - this.startX) * 0.001) + 0.5 > 1 ? 1 : (-(nowX - this.startX) * 0.0015) + 0.5 this.$refs.sliderBox.children[this.index + 1].style.transform = 'scale(' + scale + ')' this.$refs.sliderBox.children[this.index + 1].style.opacity = opacity } else { let scale = ((nowX - this.startX) * 0.001) + 0.8 > 1 ? 1 : ((nowX - this.startX) * 0.001) + 0.8 let opacity = ((nowX - this.startX) * 0.001) + 0.5 > 1 ? 1 : ((nowX - this.startX) * 0.0015) + 0.5 this.$refs.sliderBox.children[this.index - 1].style.transform = 'scale(' + scale + ')' this.$refs.sliderBox.children[this.index - 1].style.opacity = opacity } }, // 手指拖动时触发该办法 move(e) { let nowX = e.targetTouches[0].clientX this.slider(nowX) // 调用滑动动画函数 this.zoom && this.zoomMove(nowX) // 调用zoom动画函数 }, // 拖动完结时触发 该办法 endMove(e) { this.endX = e.changedTouches[0].clientX if (this.resistance !== 1) this.resistance = 1 // 判断拖动间隔 是否扭转index if (this.distance > 50) { this.handleLast('touch') } else if (this.distance < -50) { this.handleNext('touch') } else { this.animation(this.$refs.sliderBox, this.target) } // 在主动轮播时 拖动完结重新启动定时器 this.autoTimer = this.automation ? this.handleAuto() : null }, // 切换下一个函数, 次要以扭转index形式切换 handleLast(isTouch) { this.isClickL = true if (!this.loop) { if (!this.index && isTouch !== 'touch') { this.index = this.length - 1 } else if (this.index) { this.index-- } else { this.animation(this.$refs.sliderBox, this.target) } } else { if (this.index === 1) { this.transposition() this.index = this.length - 2 } else { this.index-- } } this.zoom && this.$refs.sliderBox && this.zoomAnimation(this.$refs.sliderBox.children[this.index]) setTimeout(() => { this.isClickL = false }, 300) }, // 切换上一个函数, 次要以扭转index形式切换 handleNext(isTouch) { this.isClickR = true if (!this.loop) { if (this.index === this.length - 1 && isTouch !== 'touch') { this.index = 0 } else if (this.index !== this.length - 1) { this.index++ } else { this.animation(this.$refs.sliderBox, this.target) } } else { if (this.index === this.length - 2) { this.transposition('isLast') this.index = 1 } else { this.index++ } } this.zoom && this.$refs.sliderBox && this.zoomAnimation(this.$refs.sliderBox.children[this.index]) setTimeout(() => { this.isClickR = false }, 300) }, // 切换动画 animation(dom, target) { clearInterval(this.timer) let origin = null let speed = null this.timer = setInterval(() => { origin = dom.offsetLeft speed = (target - origin) / 9 speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed) if (Math.abs(target - dom.offsetLeft) < 2) { dom.style.left = target + 'px' clearInterval(this.timer) return } dom.style.left = origin + speed + 'px' }, 16) this.endX = 0 this.startX = 0 if (this.zoom) { this.isZoomActive() } }, // zoom动画 zoomAnimation(dom) { clearInterval(this.zoomTimer) let originScale = Number(this.getDomTransform(dom, 'scale')) let originOpacity = Number(dom.style.opacity) if (originScale === 1 && originOpacity === 1) { clearInterval(this.zoomTimer) return } let speed = 0.02 this.zoomTimer = setInterval(() => { if (originScale >= 1 && originOpacity >= 1) { clearInterval(this.zoomTimer) return } originScale += speed originOpacity += speed dom.style.transform = originScale > 1 ? `scale(1)` : `scale(${originScale})` dom.style.opacity = originOpacity }, 16) }, // 获取元素transform函数 getDomTransform(dom, type) { let transformStr = dom.style.transform let tarnArr = transformStr.split(' ') let obj = {} tarnArr.forEach(item => { let tempArr = item.split('(') obj[tempArr[0]] = tempArr[1].slice(0, -1) }) return type ? obj[type] : obj }, // loop模式的后期渲染函数, 感觉这里写的不是很漂亮要害是想把,滑块中的每一项以标签模式传进来,没想到更好的办法,如果是数组的模式就要好些 renderLoop() { if (this.loop) { let divArr = Array.prototype.slice.call(this.$refs.sliderBox.children, 0) let len = divArr.length let deviceWidth = document.documentElement.clientWidth let first = divArr[0].cloneNode(true) let last = divArr[len - 1].cloneNode(true) this.$refs.sliderBox.appendChild(first) this.$refs.sliderBox.insertBefore(last, this.$refs.sliderBox.children[0]) setTimeout(() => { this.$refs.sliderBox.style.left = -(this.defaultIndex + 1) * this.$refs.sliderBox.children[0].offsetWidth + (deviceWidth - this.$refs.sliderBox.children[0].offsetWidth)/2 + 'px' window.console.log('-----', this.$refs.sliderBox.style.left) if (this.defaultIndex <= this.length - 1) { this.index = this.defaultIndex + 1 } }) } else { setTimeout(() => { this.$refs.sliderBox.style.left = -this.defaultIndex * this.$refs.sliderBox.children[0].offsetWidth + 'px' this.index = this.defaultIndex }) } this.getItemDom() }, // zoom模式中款式调整 isZoomActive() { if (this.$refs.sliderBox) { for (let i = 0; i < this.$refs.sliderBox.children.length; i++) { if (i !== this.index) { this.$refs.sliderBox.children[i].style.transform = 'scale(0.8)' this.$refs.sliderBox.children[i].style.opacity = '0.5' } else { this.$refs.sliderBox.children[i].style.transform = 'scale(1)' this.$refs.sliderBox.children[i].style.opacity = '1' } } } }, // 循环模式中的换位函数 transposition(isLast) { if (isLast) { if (this.$refs.sliderBox) this.$refs.sliderBox.style.left = this.distance + 'px' return } this.$refs.sliderBox.style.left = -(this.length - 1) * this.$refs.sliderBox.children[0].offsetWidth + this.distance + 'px' }, // 启动主动模式 handleAuto() { if (this.automation) { return (setInterval(() => { this.handleNext() }, this.automation)) } } }, computed: { // 手指触碰与来到的差值 distance() { return this.endX - this.startX }, // 计算滑块目的地 target() { if (this.swiperWidth - this.$refs.sliderBox.children[0].offsetWidth !== 0 && this.retract) { return -this.index * this.$refs.sliderBox.children[0].offsetWidth + (this.swiperWidth - this.$refs.sliderBox.children[0].offsetWidth) / 2 } return -this.index * this.$refs.sliderBox.children[0].offsetWidth }, // 分页个数 hintLen() { return this.loop && this.length ? this.length - 2 : this.length }, // box宽度 swiperWidth() { return this.$refs.swiperBox && this.$refs.swiperBox.offsetWidth }, // 滑块极限值 maxLeft() { return this.$refs.sliderBox && this.$refs.sliderBox.offsetWidth - this.$refs.sliderBox.children[0].offsetWidth } }, watch: { // 监控index变动 index() { this.animation(this.$refs.sliderBox, this.target) } }, mounted() { this.renderLoop() this.autoTimer = this.automation ? this.handleAuto() : null }, beforeDestroy() { clearInterval(this.timer) clearInterval(this.autoTimer) clearInterval(this.zoomTimer) } }</script><style lang="scss" scoped> .swiper-box { width: 100%; overflow: hidden; position: relative; .swiper-wrapper { position: relative; overflow: hidden; display: flex; } .btn-box { position: absolute; width: 100%; top: 50%; display: flex; justify-content: space-between; transform: translateY(-50%); overflow: hidden; p { overflow: hidden; color: rgba(4, 4, 4, .4); background-color: rgba(8, 8, 8, .1); &.click { background-color: rgba(8, 8, 8, .6); .iconfont { color: rgba(4, 4, 4, .6); } } .iconfont { font-size: .8rem; } } } .hint-list-box { position: absolute; width: 100%; bottom: .2rem; .hint-list { display: flex; &.center { justify-content: center; } &.right { justify-content: flex-end; } } .item { width: .2rem; height: .2rem; border-radius: 50%; background-color: #eeeeec; margin-left: .2rem; &.active { background: linear-gradient(#6a3, #4e6); } } } .paging-text-box { position: absolute; top: .1rem; text-align: center; width: 100%; &.right { text-align: right; span { margin-right: 1rem; } } &.left { text-align: left; span { margin-left: 1rem; } } } }</style>mySwiperItem.vue ...

November 9, 2020 · 8 min · jiezi

关于vue.js:Vue引入TinyMCE富文本组件时遇到的问题

Q: TypeError: Object(...) is not a function at Module../node_modules/_@tinymce_tinymce-vue@4.0.0@@tinymce/tinymce-vue/lib/es2015/main/ts/components/Editor.js (Editor.js:37)A:版本兼容问题因为 @tinymce/tinymce-vue@4.0.0 仅针对Vue@3.x版本,须要降级。 Q:未找到图标A:解决形式:import 'tinymce/icons/default/icons.min.js'

November 9, 2020 · 1 min · jiezi

关于vue.js:Vue3开发踩坑

作者:vita2333链接:https://juejin.im/post/689231... 期待了很久的vue3,一公布就上手体验了一把,这里记录几个本人碰到的网上不常见的小坑~自定义全局参数定义: // main.jsconst app = createApp(App)app.config.globalProperties.$test = 'test'除了setup()须要先取得实例,其余中央能够间接通过$test应用: <tempalte> <div>{{ $test }}</div></tempalte><script>import { getCurrentInstance } from 'vue'export default { setup() { const test = getCurrentInstance()?.appContext.config.globalProperties.$test console.log('test===') console.log(test) },}</script>Vite通过alias别名援用在webpack中,配置src的别名为@,能够这么写: // 援用src/views/PageOne.vueimport PageOne from '@/views/PageOne.vue'复制代码如果应用Vite,则须要做以下批改: // vite.config.jsmodule.exports={ alias: { '/@/': path.resolve(__dirname, './src'), },}// tsconfig.json{ "compilerOptions": { "paths": { "@/*": ["src/*"], "/@/views/*": ["src/views/*"] } }}import PageOne from '/@/views/PageOne.vue'更加标准的props和emits在vue3中,父子组件传值的props和emits写法更加标准(命名更对立),体现在: v-model的变动<template> <child-component v-model:value="myValue"></child-component></template>v-model:value等同于props:'value'和emits('update:value') 须要指定emits为了便于管理,倡议在emits中定义所有用到的emit export default { emits: ['update:value', 'otherEmit'], setup(props, { emit }) { emit('update:value') emit('otherEmit') }, }跟踪attrs和slots原本认为能够通过watch()函数间接watch(()=>attrs.xxx),后果是不行。这里官网有些,一开始本人没留神: ...

November 8, 2020 · 2 min · jiezi

关于vue.js:VuejsMVVM

Vue是时下最火的前端框架之一。 MVVM:Model-View-ViewModel M:Model,是数据层,可能是咱们固定的死数据,也可能是来自服务器的数据。不过更多的是来自服务器的数据(从网络上申请下来的数据)。 V:View,是视图层,通常就是咱们前端开发中的DOM层,次要作用是给用户展现各种信息。 VM:ViewModel,是视图模型层,有两方面性能,一方面是数据绑定,将model的扭转实时的反馈到view中,另一方面是:DOM监听,当DOM产生了一些事件的时候能够监听到,并在须要的状况下扭转相应的data。

November 8, 2020 · 1 min · jiezi

关于vue.js:开发Vue或React项目时路径别名智能提示方案

开发Vue或React我的项目时门路别名智能提醒计划前言在咱们开发Vue或React我的项目时,每次配置完门路别名,在输出门路时都没有对应的智能提醒门路,如何解决这个痛点呢?笔者通常都是应用vscode,本次应用vscode来进行演示解决,非常简单的 计划一: path-alias插件俗话说的好「工欲善其事,必先利其器」那么有没有一种插件能让咱们不同的我的项目中每次在输出门路别名时时,有相干的门路提醒呢?答案是:当然有的,而且简直零配置哦,上面让咱们来看上面???? 未装置成果没有门路别名智能提醒,vscode并不能默认并不能辨认你配置的门路别名 装置成果和性能在vscode插件商城中搜寻并装置: path-alias不光具备路径别名智能提醒,还能够点击别名门路跳转到该文件看上面性能演示???? 并反对从别名中导入导入函数或者变量,有相干的智能提醒 选择性配置入选后面咱们说了零配置,怎么这么快要打脸了?????别急别急,听我一一道来,俗话说..,好吧别打脸????回归正题:因为path-alias插件只默认配置门路@映射到我的项目的src目录 当须要有更多的门路别名有对应的映射有智能提醒,只能配置一下了,也是非常简单的,不要慌进入你的vscode的settings.json文件 如果不晓得settings.json文件在哪里能够右插件键进入设置,如????图所示 ![](https://gitee.com/xmkm/cloudPic/raw/master/img/20201028204449.png) 增加如下????// 开发我的项目时应用门路别名时会有"智能提醒" "pathAlias.aliasMap": { // key是你要定义的别名 | 应用${cwd}来代替当前工作目录的绝对路径 "@": "${cwd}/src", "~": "${cwd}/src", "components": "${cwd}/src/components"}, 这时门路输出 component 也会有智能提醒了 一点点毛病当然没有美中不足的插件,毛病就是: 占用内存有一点点高,作者近期也在保护的这个次要还是看本人应用的体验和占用内存是否成正比,当然如果你想不每次新建我的项目都要配置jsconfig.json或tsconfig.json的别名门路智能提醒的话,倡议间接应用这个插件即可当然占用内存如果感觉过高的话,上面倡议应用jsconfig.json,也就是计划二????计划二: jsconfigjsconfig.json在你的我的项目根目录下新建: jsconfig.ison文件内存小举荐????,复制如下到你的文件,从新vscode即可{ "compilerOptions": { "experimentalDecorators": true, "baseUrl": "./", "paths": { "@/": ["src/"], "components/": ["src/components/"], "assets/": ["src/assets/"], "views/": ["src/views/"], "common/": ["src/common/"], } }, "exclude": ["node_modules", "dist"]} 总结一下如果想一次配置且不在乎占用内存状况,倡议间接应用path-alias插件如果本机内存不够或感觉这个插件应用体验不佳, 倡议应用jsconfig.json

November 7, 2020 · 1 min · jiezi

关于vue.js:Vue模板语法

Vue简介尤雨溪:Vue.js的创建者 2014年2月,Vue.js正式公布2015年10月27日,正式公布1.0.02016年4月27日,公布2.0的预览版本Vue:渐进式JavaScript框架 申明式渲染→组件零碎→客户端路由→集中式状态治理→我的项目构建Vue的长处 易用:相熟HTML、CSS、JavaScript常识后,可疾速上手Vue灵便:在一个库和一套残缺框架之间自若伸缩高效:20kB运行大小,超快虚构 DOMVue的根本应用传统模式 Vue的根本应用Vue的根本应用 1. 提供标签用于填充数据2.引入Vue的库文件3.能够应用Vue相干的语法性能4.把Vue提供的数据填充到html标签中Vue实例的参数el:元素的挂载地位data:模型数据(值是一个对象或函数)<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Vue的根本应用</title></head><body> <div id="app"> <div>{{msg}}</div> <div>{{5>3?'正确':'不正确'}}</div> <div>{{20+40}}</div> </div></body><script src="./vue.js"></script><script> let vm = new Vue({ el: "#app", data() { return { msg: 'hello word' } }, })</script></html> 插值表达式的作用把数据填充到html标签中插值表达式反对根本的计算操作Vue代码运行的原理 前端渲染把数据填充到HTML标签中前端渲染的形式原生JS拼接字符串应用前端模板引擎应用Vue的模板语法Vue的模板语法 插值表达式指令事件绑定属性绑定款式绑定分支循环构造插值表达式插值表达式:{{}}把数据填充到html标签中插值表达式反对根本的计算操作指令自定义指令的实质 自定义属性。指令的格局:以v-开始v-clockv-clock是为了解决插值表达式的闪动问题,先暗藏,替换好值之后显示最终的后果

November 7, 2020 · 1 min · jiezi

关于vue.js:Vue-使用-tinymce-控制台报-Resource-interpreted-as-Stylesheet-but

Vue 应用 tinymce 控制台报 Resource interpreted as Stylesheet but transferred with MIME type text/html 导致编辑器不显示设置 skin_url 指定 css 门路: { ... language: 'zh_CN', skin_url: '/src/assets/tinymce/skins/ui/oxide', ...}但控制台提醒: Resource interpreted as Stylesheet but transferred with MIME type text/html: "http://localhost:8080/src/assets/tinymce/skins/ui/oxide/skin.min.css".Resource interpreted as Stylesheet but transferred with MIME type text/html: "http://localhost:8080/src/assets/tinymce/skins/ui/oxide/content.min.css".导致编辑器区域为空白,显示不进去。 在 tinymce-react Issues Skin false does not prevent loading of skins #53 发现解决办法: 手动引入 css在 export default 下面引入: import 'tinymce/skins/ui/oxide/skin.min.css'import 'tinymce/skins/ui/oxide/content.inline.min.css'而后设置初始参数: ...

November 7, 2020 · 1 min · jiezi

关于vue.js:jTopo入门-简单实现拓扑图

最近我的项目中须要绘制拓扑图,于是钻研了下绘制拓扑图的组件,jtopo是一款比较简单易上手的开发工具包,分享给大家。 jtopo特点1、齐全基于HTML5 Canvas开发,API平易近人、简直简略到了极致。2、不依赖任何其余库、执行仅需一个Canvas。3、体积小,压缩后仅几十KB。5、收费! 下载jtopo大家能够去官网自行下载 http://www.jtopo.com/download/jtopo-0.4.8-min.js,目前版本是0.4.8,官网有API文档和案例。 jtopo官网地址:http://www.jtopo.com/jQuery目前我是vue我的项目中引入的jtopo,jtopo只反对在jQuery语言编写,须要我的项目中引入jQuery,不是vue我的项目的能够自行去官网下载jQuery.js,vue引入jQuery可参考https://blog.csdn.net/JQdazhuang/article/details/107152192 举例代码html代码: <template> <div style="position: relative; width: 100%; height: 100%; margin: auto" id="topo_content" > <canvas id="topology-canvas" width="1000" height="600"></canvas> </div></template>js代码: var canvas = document.getElementById("topology-canvas"); var stage = new JTopo.Stage(canvas);//创立一个画布 var scene = new JTopo.Scene(stage);//创立一个背景 _this.scene = scene; var childs = topoData; for (let i in childs) { var a = childs[i]; if (a.elementType == "node") {//如果是拓扑节点 //节点 var node = new JTopo.Node(a.text); node.setLocation(a.x, a.y); node.setImage("/static/img/" + a.nodeImage, true); node.fontColor = "0,0,0"; node.nodeId = a.nodeId; node.nodeType = a.nodeType; node.nodeImage = a.nodeImage; node.scaleX = a.scaleX; node.scaleY = a.scaleY; node.devIp = a.devIp; node.textPosition = a.textPosition; if (node) { node.alarm = a.alarm; node.alarmColor = "255,0,0"; node.alarmAlpha = 0.5; } scene.add(node); } else if (a.elementType == "link") { //如果是连线 var link = null; if (link == null) { var nodes = stage.find("node"); var nodeA, nodeZ; if (a.nodeSrc && a.nodeDst) { nodes.forEach(function (nodeElement) { if (nodeElement.elementType == "node") { if (nodeElement.nodeId == a.nodeSrc) { nodeA = nodeElement; //终点 } if (nodeElement.nodeId == a.nodeDst) { nodeZ = nodeElement; //起点 } } }); } //绘制折线 var c = null; if (nodeA && nodeZ) { // 折线和直线绘制 if (a["lineType"] == "line") { c = new JTopo.Link(nodeA, nodeZ); c.lineType = "line"; } if (a["lineType"] == "foldLine") { c = new JTopo.FoldLink(nodeA, nodeZ); c.bundleOffset = 40; c.direction = a.direction; c.lineType = "foldLine"; } if (a["lineType"] == "flexLine") { c = new JTopo.FlexionalLink(nodeA, nodeZ); c.offsetGap = 40; c.direction = a.direction; c.lineType = "flexLine"; } if (a["lineType"] == "curveLine") { c = new JTopo.CurveLink(nodeA, nodeZ); c.lineType = "curveLine"; } c.alpha = 1; c.shadow = false; c.font = "12px Consolas"; c.arrowsRadius = 0; c.lineWidth = 1.5; c.bundleGap = 0; c.eagleEyeVsibleDefault = false; c.id = a.id; c.strokeColor = a.strokeColor; c.lineClass = a.lineClass; c.nodeSrc = nodeA.nodeId; c.nodeDst = nodeZ.nodeId; c.localDevId = a.localDevId; c.localDevIp = a.localDevIp; c.localDevIfindex = a.localDevIfindex; c.localDevIfname = a.localDevIfname; c.remoteDevId = a.remoteDevId; c.remoteDevIp = a.remoteDevIp; c.remoteDevIfindex = a.remoteDevIfindex; c.remoteDevIfname = a.remoteDevIfname; scene.add(c); } } else { link.strokeColor = a.strokeColor; } } }代码运行效果图如下: ...

November 6, 2020 · 2 min · jiezi

关于vue.js:vue组件中的样式属性scoped使用分享

vue组件中的款式属性scoped实例1.开发环境 vue2.电脑系统 windows10专业版3.在应用vue开发的过程中,咱们在style标签上会加上 scoped,然而如果咱们应用了其余的的一起框架,咱们会发现如果加上了 scoped之后无奈批改款式,上面是我对 scoped 总结,心愿对你有所帮忙!4.什么是 scoped ? Scoped CSS标准是Web组件产生不净化其余组件,也不被其余组件净化的CSS标准。vue组件中的style标签标有scoped属性时表明style里的css款式只实用于以后组件元素。5.如何应用scoped? vue应用办法:在 style 标签上 加上 scoped6.vue+element应用table组件,你会发现加上 scoped 属性之后,有的款式没有失效,增加 scoped 之前的成果:7.增加scoped之后的成果: css局部代码如下:.chenshebei .el-table--enable-row-hover .el-table__body tr:hover > td { background-color: #003b51 !important;}.chenshebei .el-table th,.chenshebei .el-table tr { background-color: #0a2732 !important; box-sizing: border-box; color: #83c7e3 !important; opacity: 0.6;}.chenshebei .el-table { background-color: #003b51 !important; box-sizing: border-box; margin: 1% auto; position: absolute; bottom: 0%; right: 2%;}7.解决办法,css代码,如下: .chenshebei /deep/ .el-table--enable-row-hover .el-table__body tr:hover > td { background-color: #003b51 !important;}.chenshebei /deep/ .el-table th,.chenshebei /deep/ .el-table tr { background-color: #0a2732 !important; box-sizing: border-box; color: #83c7e3 !important; opacity: 0.6;}.chenshebei /deep/ .el-table { background-color: #003b51 !important; box-sizing: border-box; margin: 1% auto; position: absolute; bottom: 0%; right: 2%;}//留神:深度选择器: /deep/ 也能够应用: >>> ,成果是一样的。一些预处理程序例如sass不能解析>>>属性,这种状况下能够用deep,它是>>>的别名,工作原理雷同。7-1.效果图如下:8.本期的分享到了这里就完结啦,是不是很nice,心愿对你有所帮忙,让咱们一起致力走向巅峰! ...

November 6, 2020 · 1 min · jiezi

关于vue.js:vue项目elment按需导入

vue我的项目elment按需导入1.开发环境 vue+element2.电脑系统 windows10专业版3.在应用 vue+element开发的的过程中,咱们可能只是应用element-ui的几个组件,如果咱们把整个element-ui引入的话,就会导致我的项目过大。上面是element-ui按需导入的办法,心愿对你有所帮忙。4.在终端执行命令: npm add element-uinpm install babel-plugin-component -D5.在babel.config.js增加如下代码: module.exports = { presets: [ '@vue/app' ], "plugins":[ [ "component", { "librayName":"element-ui", "styleLibraryName":"theme-chalk" } ] ]}6.在main.js中增加如下代码: import {Button,Progress} from 'element-ui';Vue.use(Button);Vue.use(Progress);7.在vue模板中应用: <el-button type="success" round>胜利按钮</el-button> <el-progress :text-inside="true" :stroke-width="26" :percentage="70"></el-progress>8.本期分享到了这里就完结啦,是不是很nice,心愿对你有所帮忙,让咱们一起致力走向巅峰!

November 6, 2020 · 1 min · jiezi

关于vue.js:手把手教你如何搭建一个vue项目

1、先进去node.js官网下载,https://nodejs.org/zh-cn/download/2、装置胜利后,命令框执行: node -v(查看以后node版本) npm -v(查看以后npm版本)3、装置cnpm 指令:npm install cnpm -g (装置cnpm,-g代表全局装置) 查看是否装置胜利:cnpm -v(查看以后cnpm版本)4、装置webpack 指令:npm intsall webpack -g 查看装置后果:webpack -v5、装置vue-cli 指令:npm install vue-cli -gcnpm install -g @vue/cli6、开始创立一个vue我的项目 1.上面筹备在D盘目录下的WebstormProjects下创立一个vue我的项目2.首先依照下图中所示形式进入到当前目录下的cmd窗口 3.在Cmd命令窗口输出如下命令,新建一个vue我的项目 vue init webpack my-project4.在建设vue我的项目中次要须要输出如下信息Project name my-project --我的项目的名称,间接默认回车 Project description A Vue.js project --我的项目形容,间接默认回车Author syf --作者姓名,输出名字(syf)回车Install vue-router? Yes --是否装置路由,输出y回车Use ESLint to lint your code? No --是否用ESLint标准代码,输出n回车Set up unit tests No --是否须要单元测试,输出n回车Setup e2e tests with Nightwatch? No --是否须要单元测试,输出n回车 5.进入到my-project文件夹下 cd my-project 6.装置依赖 cnpm install 7.启动我的项目 npm run dev具体查看:https://www.cnblogs.com/shenyf/p/8341641.html记得设置镜像哦~1、查看淘宝镜像:npm config get registry2、设置淘宝镜像:npm config set registry url ...

November 5, 2020 · 1 min · jiezi

关于vue.js:Vue-中使用-axios-的get请求无法传递对象问题及解决办法

get申请问题形容利用get传递对象,会被主动转换为字符串模式解决办法在我的项目根目录下载qsnpm i qs引入import qs from "qs"应用axios({ url: "接口", method: "get", params: { data: this.data,//传递的对象 }, paramsSerializer: function (params) { return qs.stringify(params, { arrayFormat: "indices" }); },});post申请post能够失常传入对象模式

November 5, 2020 · 1 min · jiezi

关于vue.js:数百万台车联网设备同时在线0故障中瑞集团的云原生探索之路-云原生Talk

简介: 在放弃对业界趋势调度关注的同时,始终选用最适宜本身的技术,这可能是中瑞能在车联网畛域引领行业的重要起因之一,正如中瑞CTO所说“阿里云云原生产品体系带给咱们的,不是单纯的IT工具,而是整个团队战斗力的晋升”。 中瑞团体成立于2011年,是一家青岛外乡的物联网独角兽企业。中瑞团体致力于利用物联网和人工智能技术,交融智慧交通、智慧城管、智慧出行、智慧物流、智慧风控、智慧审计、智慧车险、智慧校园、智慧批发等业务场景,为数万家政府和企业客户提供资产数字化治理解决方案。自2015年以来,团体业务营收年均复合增长率超过100%,2019年营收超过20亿人民币。中瑞团体累计服务7000余家汽车经销商、200余家金融机构、20多家出名出行机构。2020年10月平台累计在线车联网终端设备超过678万台,是全国车联网在线终端规模No.1的利用平台。 商用车辆数字化治理是中瑞团体的外围业务之一,在这个畛域,中瑞团体已联动包含整车厂、银行、汽车金融机构、保险公司、根底技术提供方等十数家机构,造成以传感器、人工智能算法、数据管理平台为外围的整体解决方案,为客户提供高度定制个性化服务,同时辅以汽车金融、保险、规范制订、平台经营等衍生性能板块,业务能力涵盖数字化治理我的项目设计、建设和经营的各个阶段。 商用车辆数字化治理,通过车联网技术连贯大量终端配备,实时收集并解决海量数据。智能车载传感设施会依据不同行业属性,如物流、出行、工程作业、农业作业等,产生人、车、货、设施等数据。中瑞团体基于对车联网行业实际的深度积攒,将物联网与挪动互联网技术相结合,依附云计算、大数据等技术的反对,自主研发中瑞车联云平台。通过对在线经营车辆数据的收集、解决和剖析,反馈到整车厂研发、设计、洽购、生产、销售及售后各个环节,无效改善了整车设计程度,晋升了零部件品质,优化了销售策略,进步了售后实时性及准确度。 车联网智能设施实时上报的数据,会同步流转到多个业务零碎进行解决,其中包含中瑞自建的在线业务平台、离线剖析平台和实时计算平台,还有一部分数据会通过API的形式进行透出,提供给配备所属机构和政府监管部门应用。中瑞团体依据政府监管政策要求,承建智慧城市出行平台,通过部署车载联网终端设备,会集合乎当地监管要求和技术标准的车辆作业数据,上传归集至当地政府数据中心,同时建设遵循国家标准的凋谢数据接口,提供给各部委调用。 对于中瑞的技术团队而言,每一条通过车联网上报的数据都是十分宝贵的,其背地蕴藏着微小的业务价值。因而,在进行零碎架构设计的时候,须要思考到如下几个重要的业务诉求: 1、 对于上报的数据,通过一个两头模块进行音讯散发,交给不同的零碎进行解决,缩小音讯复制的老本。2、 当上游业务模块的音讯处理速度比拟快的时候,要确保音讯流转的低时延。这个需要对于大多数在线业务场景都是十分重要的,比方当车联网用户发动一个新的指令的时候,云端须要尽可能快的对指令进行解决,并及时给予回复。3、 当上游业务模块的音讯处理速度跟不上数据上报速度的时候,须要音讯能尽可能多的在两头模块进行暂存,并在单方速度拉平的时候,让之前暂存的音讯可能失去正确的解决。这是一种典型的异步化通信思路,在绝大多数的离线剖析场景,以及局部在线业务场景中被宽泛的应用,可能显著晋升零碎整体的稳定性和吞吐量。 通过引入音讯队列,可能比较顺利的实现这几大业务诉求,音讯散发、暂存的工作都能够交给音讯队列来实现,不须要在具体的业务模块中自行实现。 在整个零碎架构中,所有音讯的流转都须要通过音讯队列来实现。在业务高峰期,会有超过100万台车联网设施同时在线,每秒的产生的音讯数量,也会达到百万级别,因而音讯队列的稳定性以及吞吐能力至关重要。在音讯队列的选型上,中瑞的技术团队针对业界支流的产品进行了深刻摸索。 在音讯队列产品选型过程中,咱们排除了是无奈通过程度扩大的形式线性晋升整体性能的音讯队列产品。这类产品以ActiveMQ和RabbitMQ为代表,尽管在业界失去了宽泛应用,但无奈撑持来自于海量设施的大吞吐量需要。最实质的起因是这类产品并不是依照原生的分布式理念进行设计,当性能无奈满足业务需要的时候,只有通过垂直晋升硬件性能的形式实现,降级过程中对业务有感知,而且性能晋升的水平无限,不具备可操作性。 Kafka是一个比拟好的抉择,其原生的分布式设计理念能确保性能能够通过程度扩容而实现线性的晋升。中瑞的技术团队对Kafka进行了大量技术预研,心愿可能通过Kafka的程度扩大能力撑持起中瑞的高并发业务场景。但随着钻研的深刻,中瑞的技术团队发现Kafka也存在肯定的局限性。对于流转到在线业务模块以及第三方合作伙伴的音讯,须要确保音讯的可达性,也就是说不论零碎的哪个环节呈现了异常情况,都应该确保重要的音讯不失落。这一点Kafka没有方法在协定层提供保障,并在测试过程中也失去了验证:过后Kafka与在线业务模块之间的网络呈现了短暂抖动,这原本应该是一个很常见的异常情况,零碎能够比拟快的工夫内复原运行。但理论应用过程中,这次网络抖动造成了一批音讯的永久性失落,这在一些金融风险管制相干的要害业务场景中是不能被承受的。 在测试的过程中,中瑞还发现往Kafka集群退出新的节点的时候,会造成集群的性能呈现抖动状况,通常会继续1小时以上。这个过程中尽管集群层面能确保高可用,但对于业务仍然会造成肯定的影响,这是由Kafka底层的ISR机制的实现原理导致的,整个技术界都没有太好的优化方向。 通过深刻的评估,中瑞最终决定采纳RocketMQ来建设音讯队列集群。RocketMQ是阿里巴巴在历年双11业务的积淀下,构建的低提早、高并发、高可用、高牢靠的分布式消息中间件。最后RocketMQ的诞生,也参考了Kafka的分布式模型,但在Kafka的根底上围绕在线交易类业务场景进行了多项优化。对于中瑞来说,RocketMQ建设在协定层的音讯必达性保障能够避免重要的数据在流转的过程中失落,这种必达性保障通过了各种刻薄场景的验证,齐全能够应用在金融相干业务中。对于每一个发往RocketMQ的音讯,只有发送方收到了来自于RocketMQ的回执,就能确保这条音讯肯定会被对应的生产方接管并正确的解决。 早在2012年,RocketMQ就被募捐给了开源组织,并在随后成为Apache的顶级我的项目,因而RocketMQ在整个业界具备十分高的影响力,对于RocketMQ的实现原理、优化计划,都能在技术论坛找到大量的材料。但在到底应用开源RocketMQ进行自建,还是应用云上商业版RocketMQ的问题上,中瑞的技术团队倒是很快达成了统一:对于一只以业务倒退为第一导向的技术团队而言,云上商业版在老本和效率上体现进去的劣势是不言而喻的。 RocketMQ人造具备高可用性,不论是Name Server集群还是Broker集群,当有节点宕机的时候,整个集群仍然能够对外提供服务,不会对业务造成影响。但在这种状况下,RocketMQ集群处于一种比拟软弱的状态,须要使用者想方法进行系统性的补救,以确保在下一次呈现节点宕机的时候,RocketMQ集群仍然可能稳固得运行。比方当一个Master Broker节点呈现故障后,尽管Slave Broker节点仍然能够承当音讯收发的工作,而且RocketMQ的音讯同步机制确保了这个过程中的音讯不失落,但使用者须要尽快将Slave节点降级为Master节点,并引入新的Slave节点。否则当原有的Slave节点再次遇到故障的时候,整个集群将进行工作,这会对业务造成十分重大的影响。在开源RocketMQ的实现中,并没有提供欠缺的机制来实现主从Broker的互相切换,须要使用者自行实现计划,危险十分大。在前期的版本中,尽管提供了Dledger多正本机制实现主从切换,但操作难度很大,切换的过程中也并不能保障平滑过渡,会使业务造成肯定的抖动。 RocketMQ集群的扩容也是一项十分有挑战性的工作,在引入新节点的过程中,须要投入大量运维工作量,扩容所须要的工夫也比拟长。每一步的操作都必须小心谨慎,一旦呈现操作失误,就会导致整个集群不可用。在中瑞的业务场景中,因用户流量的突增而引发零碎紧急扩容的需要比拟频繁。音讯队列是整个零碎的外围,必须保障每一次扩容都能够在保障业务不中断的前提下疾速实现。 阿里云版本的RocketMQ完满的解决了高可用和弹性伸缩这两个方面的挑战。这样的能力来自于阿里巴巴本身业务场景的积淀和历练,也就是每年双11流动的极其考验。随着阿里云的飞速发展,RocketMQ成为了阿里云音讯队列产品家族的最重要组成部分。云上的商业版RocketMQ残缺保留了在阿里团体本身业务场景中积淀的高吞吐量、沉积能力、高可用性、高安全性、低提早性,并针对云上的使用者在易用性方面进行了大量加强。中瑞的技术团队在零碎架构中全面应用阿里云版RocketMQ作为音讯队列后,对集群进行了屡次程度扩容,以满足更大用户量更高并发的需要。在业务值峰期间,数百万台车联网设施同时在线,给零碎带来了微小的压力,但阿里云版RocketMQ作为音讯流转的外围组件,始终保持稳定进行,至今为止0故障。 当一支技术团队的工作内容从简单的底层技术细节中解放出来后,他们就有了更多的精力来实现业务畛域的翻新。这也是云计算以及云原生理念为宽广企业带来的微小价值,随着业务的飞速发展,中瑞的技术团队还会持续围绕云原生技术,摸索更多节俭IT老本、晋升业务效率的新方向。以后,中瑞正在将现有的微服务利用进行容器化革新,并全面接入阿里云实时利用监控ARMS,以实现全栈式的性能监控和端到端的全链路追踪诊断。此外,他们还踊跃尝试通过函数计算FC的形式对局部业务零碎进行Serverless化革新,从而全面的升高计算资源老本,更充沛的利用云计算的弹性能力。 在放弃对业界趋势调度关注的同时,始终选用最适宜本身的技术,这可能是中瑞能在车联网畛域引领行业的重要起因之一,正如中瑞CTO杨少杰所说:“阿里云云原生产品体系带给咱们的,不是单纯的IT工具,而是整个团队战斗力的晋升”。 原文链接本文为阿里云原创内容,未经容许不得转载。

November 5, 2020 · 1 min · jiezi

关于vue.js:eltable导致TypeError-thiselquerySelectorAll-is-not-a-function

在应用Vue的过程中报以下谬误,特此记录 报错截图vue.runtime.esm.js?2b0e:1888 TypeError: data.reduce is not a function at Proxy.render (table.js?ad41:2558)at VueComponent.Vue._render (vue.runtime.esm.js?2b0e:3548)at VueComponent.updateComponent (vue.runtime.esm.js?2b0e:4066)at Watcher.get (vue.runtime.esm.js?2b0e:4479)at Watcher.run (vue.runtime.esm.js?2b0e:4554)at flushSchedulerQueue (vue.runtime.esm.js?2b0e:4310)at Array.eval (vue.runtime.esm.js?2b0e:1980)at flushCallbacks (vue.runtime.esm.js?2b0e:1906)TypeError: this.$el.querySelectorAll is not a function at VueComponent.onColumnsChange (table.js?ad41:2475)at VueComponent.updated (table.js?ad41:2467)at invokeWithErrorHandling (vue.runtime.esm.js?2b0e:1854)at callHook (vue.runtime.esm.js?2b0e:4219)at callUpdatedHooks (vue.runtime.esm.js?2b0e:4351)at flushSchedulerQueue (vue.runtime.esm.js?2b0e:4336)at Array.eval (vue.runtime.esm.js?2b0e:1980)at flushCallbacks (vue.runtime.esm.js?2b0e:1906) 报错地位判断绑定:data后报错,所以可能和rightList无关 // Rights.vue<!-- 表格区域 --> <el-table :data="rightList" stripe> </el-table>发现在定义rightList时初始化为一个空对象 // Rights.vue<script>export default { data() { return { // 权限列表数据,就是这里导致了报错 rightList: {}, } },}</script>解决element-ui中el-table中要求data类型为数组类型所以批改为数组即可,批改后代码如下 ...

November 4, 2020 · 1 min · jiezi

关于vue.js:vue-中-fullcalendar-使用案例

fullcalendar官网应用版本:@fullcalendar/vue": "^5.3.1" <template> <div class="calendar"> <div class="top-content"> <!-- <div id="tooltip" title="">I'm a tooltip</div> --> <!-- <div id="tooltip1">I'm a tip of tooltip</div> --> <div class="left"> <span @click="prevFn" class="op el-icon-arrow-left"></span> <span>2020年xx月 第x周</span> <span @click="nextFn" class="op el-icon-arrow-right"></span> </div> <div class="center"> <el-input v-model="filterKey" placeholder="搜寻" suffix-icon="el-icon-search" @keyup.enter.native="searchFn" size="small" /> </div> <div class="right"> <el-button @click="todayFn" type="primary" class="today-btn">今日</el-button> <el-radio-group v-model="viewType" @change="changeViewTypeFn"> <el-radio-button label="dayGridMonth">月</el-radio-button> <el-radio-button label="timeGridWeek">周</el-radio-button> <el-radio-button label="listWeek">日程</el-radio-button> </el-radio-group> </div> </div> <div class="calendar-content"> <div class="event-info"> <div class="tags"> <span class="level level-1"></span> <span class="label">紧急变更</span> </div> <div class="tags"> <span class="level level-2"></span> <span class="label">惯例变更(重大、较大)</span> </div> <div class="tags"> <span class="level level-3"></span> <span class="label">惯例变更(个别、中等)</span> </div> <div class="tags"> <span class="level level-4"></span> <span class="label">规范变更</span> </div> <div class="event-size"> 本月变更共计: <span class="num">18</span> 条 </div> </div> <FullCalendar ref="calendarRef" :options="calendarOptions"> <!-- <template #eventContent="{ timeText, event }"> <b>{{ timeText }}</b> <i>{{ event.title }}</i> </template> --> </FullCalendar> </div> </div></template><script>import module from './calendar.js'export default { ...module}</script><style lang="scss" scoped>@import './calendar.scss';</style>import FullCalendar from '@fullcalendar/vue'import dayGridPlugin from '@fullcalendar/daygrid'import timeGridPlugin from '@fullcalendar/timegrid'import listPlugin from '@fullcalendar/list'import interactionPlugin from '@fullcalendar/interaction'import $ from 'jquery'import 'jquery-ui-dist/jquery-ui'import 'jquery-ui-dist/jquery-ui.css'window.$ = $// fc-day-sat 周六加款式的形式export default { components: { FullCalendar // make the <FullCalendar> tag available }, data() { return { filterKey: '', // 搜寻条件 viewType: 'dayGridMonth', // 显示方式 // 日历配置项 calendarOptions: { locale: "zh-cn", // 中文 height: '100%', plugins: [ dayGridPlugin, timeGridPlugin, interactionPlugin, listPlugin ], initialView: 'dayGridMonth', dateClick: this.handleDateClick, // 点击某一天 // 想要触发dateClick事件必须先装置援用interaction插件 eventClick: (event, el, jsEvent, view) => { // 点击某个事件 console.log('eventClick') console.log(event, el, jsEvent, view) }, eventDidMount: this.eventDidMount, eventWillUnmount: this.eventWillUnmount, viewDidMount: (info) => { console.log('viewDidMount') }, // eventAdd: this.afterEventAdd, headerToolbar: false, // headerToolbar: { // left: 'title', // center: '', // right: '' // }, // buttonText: { // today: 'today', // month: 'month', // list: 'list' // }, // timeGridEventMinHeight: '20', // 设置事件的最小高度 aspectRatio: 1.65, // 设置日历单元格宽度与高度的比例 // dayMaxEventRows: 2, // ??? dayMaxEvents: 3, events: [{ id: 1, title: 'BCH237', start: '2020-11-12T10:30:00', end: '2020-11-12T11:30:00', extendedProps: { department: 'BioChemistry' }, description: 'Lecture' }], slotEventOverlap: false, // 雷同时间段的多个日程视觉上是否容许重叠,默认true容许 noEventsContent: '暂无变更', } } }, computed: { }, mounted () { this.addDayEvent() // this.$nextTick(() => { // $("#tooltip").tooltip({ // content: $('#tooltip1') // }); // }) }, methods: { // 切换到上一页 prevFn () { const calendarApi = this.$refs.calendarRef.getApi() calendarApi.prev() }, // 切换到下一页 nextFn () { const calendarApi = this.$refs.calendarRef.getApi() calendarApi.next() }, // 切换到明天 todayFn () { const calendarApi = this.$refs.calendarRef.getApi() calendarApi.today() }, // 获取以后形容 getCurrentTitle () { }, // 切换显示类型 changeViewTypeFn (type) { const calendarApi = this.$refs.calendarRef.getApi() calendarApi.changeView(type) // , '2020-11-05' }, // 按日增加事件 addDayEvent () { const calendarApi = this.$refs.calendarRef.getApi() // 增加当月事件 calendarApi.addEvent(this.genEvent('level-1')) calendarApi.addEvent(this.genEvent('level-2')) calendarApi.addEvent(this.genEvent('level-3')) calendarApi.addEvent(this.genEvent('level-4')) calendarApi.addEvent(this.genEvent('level-2')) calendarApi.addEvent(this.getVacation()) }, // 获取假期 getVacation () { const id = new Date().getSeconds() + Math.floor(Math.random() * 10000) return { id: id, date: '2020-11-05', classNames: 'event-cls-vacation', display: 'background', color: '#eee', // daysOfWeek: [0, 6] } }, // 依据类型获取事件 genEvent (type) { const id = new Date().getSeconds() + Math.floor(Math.random() * 10000) const tempObj = { id: id, title: type, date: '2020-11-05', // startTime: '09:10:00', // endTime: '10:10:00', start: "2020-11-05T09:10:00+00:00", end: '2020-11-05T09:00:05+00:00', } tempObj.classNames = ['event-cls', 'event-cls-' + type] tempObj.display = 'list-item' if (type === 'level-1') { tempObj.textColor = 'white' tempObj.backgroundColor = 'red' } else if (type === 'level-2') { tempObj.textColor = 'white' tempObj.backgroundColor = 'orange' } else if (type === 'level-3') { tempObj.textColor = 'white' tempObj.backgroundColor = 'yellow' } else if (type === 'level-4') { tempObj.textColor = 'white' tempObj.backgroundColor = 'blue' } return tempObj }, // 搜寻 searchFn () { }, // 事件被渲染 eventDidMount (info) { console.log('eventDidMount') console.log(info) if (!$(info.el).tooltip( "instance" )) { $(info.el).attr('title', '') $(info.el).tooltip({ content: '<a style="color: red">aaaaaaa</a>',// $('#tooltip1'), position: { my: "left+0 center", at: "left center" } }); } else { $(info.el).tooltip('disable') $(info.el).tooltip('destroy') } }, eventWillUnmount (info) { if ($(info.el).tooltip( "instance" )) { $(info.el).tooltip('disable') $(info.el).tooltip('destroy') } }, // 新增事件后回调 afterEventAdd () { console.log('afterEventAdd') }, // 点击某一天 handleDateClick: function(arg) { console.log('date click! ' + arg.dateStr) } }}.calendar { width: 100vw; height: 100vh; .top-content { display: flex; align-items: center; padding: 20px; box-shadow: 0px 0px 10px #eee; .left { display: flex; align-items: center; margin-right: 30px; line-height: 24px; font-weight: bold; .op { cursor: pointer; font-size: 18px; padding: 0 10px; line-height: 24px; &:hover { color: #3e3bee; } } } .center { flex: 1; .el-input { width: 300px; } } .today-btn { margin-right: 20px; } } .calendar-content { height: calc(100% - 73px); padding: 20px; overflow-y: auto; .event-info { display: flex; align-items: center; margin-bottom: 15px; .tags { display: flex; align-items: center; margin-right: 20px; .level { display: inline-block; width: 16px; height: 16px; &.level-1{ background-color: red; } &.level-2{ background-color: orange; } &.level-3{ background-color: yellow; } &.level-4{ background-color: blue; } } .label { margin-left: 10px; font-size: 12px; height: 16px; line-height: 16px; } } .event-size { flex: 1; text-align: right; font-size: 12px; .num { color: orange; } } } } >>> .fc { // 展现某月 .fc-dayGridMonth-view { // 头部款式 .fc-col-header-cell { background-color: #e7ebfd; } // 日 .fc-daygrid-day { // 事件款式 .event-cls { .fc-daygrid-event-dot { border-radius: 0; border-left-width: 3px; border-right-width: 3px; border-top-width: 6px; border-bottom-width: 6px; margin-right: 8px; } .fc-event-title { color: blue; } } // 日期文本靠左 .fc-daygrid-day-top { direction: rtl; } // 休息日 .event-cls-vacation { opacity: 0.8; &::after { content: '休'; position: absolute; top: 0; right: 0; width: 30px; height: 30px; line-height: 30px; text-align: center; color: #fff; background: orange; border-bottom-left-radius: 10px; } } } } }}

November 4, 2020 · 4 min · jiezi

关于vue.js:vuenode使用websocket

vue+node应用websocket1.开发环境 vue+node2.电脑系统 windows10专业版3.在应用vue+node开发的过程中,咱们常常会应用到websocket,上面我来分享一下如何应用,心愿对你有所帮忙!4.node我的项目中终端中输出以下命令: npm install nodejs-websocket5.在node我的项目对应的路由中增加如下代码: var express = require('express');var router = express.Router();var ws = require("nodejs-websocket");var timer;var server = ws.createServer(function (conn) { console.log("New connection") conn.on("text", function (str) { clearInterval(timer); console.log("接管到客户端发来的音讯: " + str) // 给客户端发消息 let a = 1; let arr = [ [20, 21, 22, 23, 20, 20, 18, 26], [21.5, 20, 23, 25, 21, 24, 22, 28], [22, 26, 35, 27, 26.3, 34, 35, 28], [21.5, 20, 37, 29, 21, 27, 22, 28], [21.5, 20, 39, 25, 42, 24, 27.5, 28], [21.5, 24, 23, 25, 36, 24, 22, 45], [21.5, 20, 23, 23, 21, 45, 22, 46], [21.5, 27, 23, 35, 21, 37, 22, 28], [21.5, 20, 24, 25, 21, 35, 22, 27], [21.5, 20, 23, 25, 38, 24, 10, 28] ] conn.sendText(str) timer = setInterval(function () { let obj = { zao: arr[Math.floor(Math.random() * 10)], zhong: arr[Math.floor(Math.random() * 10)], wan: arr[Math.floor(Math.random() * 10)], a: str + a++ } conn.sendText(JSON.stringify(obj)) }, 1000); }) conn.on("close", function (code, reason) { console.log("Connection closed") })}).listen(8003)module.exports = router;6.留神,node我的项目的目录构造如下:7.vue代码如下: ...

November 4, 2020 · 2 min · jiezi

关于vue.js:vue中实现部分页面引入公共组件

前言咱们能够把公共组件放到App.vue中,然而有时候咱们心愿某个页面不须要这写公共局部,那么须要怎么设置呢? 本文为大家介绍三种局部页面引入公共组件的办法。 办法一:利用子路由创立一个layout页面来寄存公共局部(页头、页脚、侧边栏) <!-- Layout --><template> <div class=""> <el-container> <el-header></el-header> <el-container> <el-aside width="200px"></el-aside> <el-main><router-view /></el-main> </el-container> </el-container> </div></template>在router/index.js中给想应用公共局部的页面增加子路由 export default new Router({ routes: [ { path: "/", component: Layout, redirect: "/dashboard", children: [ { name: "Dashboard", path: "dashboard", component: () => import("@/views/home/Index") } ] }, { name: "Login", path: "/login", component: () => import("@/views/login/index") } ]});办法二:联合$route.meta在App.vue中<template> <div id="app"> <div v-if="$route.meta.keepAlive"> <el-header></el-header> <router-view></router-view> </div> <router-view v-if="!$route.meta.keepAlive"></router-view> </div></template>在router.js中配置想要显示公共组件的meta.keepAlive值为true,反之则是false{ path: '/home', name: "Home", component: Home, meta: { keepAlive: true }},{ path: '/login', name: "Login", component: Login, meta: { keepAlive: false }},形式三:利用路由判断是否显示在App.vue中利用v-if判断以后路由是否显示,并用watch来监听路由的扭转 ...

November 4, 2020 · 1 min · jiezi

关于vue.js:vue-elementui-中-elcascader的异步使用包括回显过滤

<template> <!-- 异步数据字典联动控件封装 --> <div class="data-dict" v-loading="!isFinishedGetOptions" element-loading-spinner="el-icon-loading" element-loading-background="rgba(255, 255, 255, 0)" element-loading-custom-class="loading-cascader"> <el-cascader ref="dictCascaderRef" v-model="_current" :options="filterOptions || null" :key="isFinishedGetOptions" :props="dictTreeProps" :disabled="disabled" :filterable="filterable" :clearable="clearable" :multiple="multiple" :size="size" :before-filter="beforeFilter" @blur="blurFn" @change="changeFn" ></el-cascader> </div></template><style lang="scss" scoped>>>> .loading-cascader { line-height: 32px; .el-loading-spinner { height: 32px; line-height: 32px; top: 0; margin-top: 0; text-align: right; padding-right: 10px; }}.data-dict { position: relative; .el-cascader, .el-select { display: block; width: 100%; }}</style> import { arrayValueEquals } from '@/utils/util.js' export default { components: { }, model: { prop: 'value', event: 'input' }, props: { value: { // 对应父组件v-model中的值 type: [Array], default: () => null }, dictKey: { // type: String, required: true, default: () => '' }, checkStrictly: { type: Boolean }, needReturnCheckedNodes: { type: Boolean, }, disabled: { type: Boolean }, multiple: { type: Boolean }, filterable: { type: Boolean }, clearable: { type: Boolean }, size: { type: String }, }, data () { return { filterKey: '', filterOptions: [], orginList: [], currentVal: [], isFinishedGetOptions: false, dictTreeProps: null } }, computed: { _current: { get () { return this.currentVal }, set (val) { this.currentVal = val this.$emit('input', val) } } }, watch: { value: { handler (newVal, oldVal) { if (newVal && Array.isArray(newVal) && newVal.length) { this.currentVal = newVal } else { this.currentVal = [] } if (this.isFinishedGetOptions || arrayValueEquals(newVal, oldVal)) { return } if (this.currentVal && this.currentVal.length) { // 如果以后有值,则获取数据用于回显 this.getAllTreeByCurrent() } else { this.getTreeInfo() } }, immediate: true } }, created () { const ths = this console.log('created') ths.dictTreeProps = { lazy: true, children: 'children', label: 'name', value: 'key', multiple: ths.multiple, checkStrictly: ths.checkStrictly, lazyLoad (node, resolve) { if (node.level === 0) { ths.getInitTree(resolve) } else { ths.getChildrenInfo(node, resolve) } } } if (!ths.dictKey) { ths.isFinishedGetOptions = true return false } }, methods: { beforeFilter (val) { const ths = this ths.filterKey = val const promise = new Promise((resolve,reject)=>{ const params = { key: val, source_uri: ths.dictKey } ths.$store.dispatch('xxxxxxx/getAllTreeByKeyword', params).then(res => { const tempList = Array.isArray(res.data) ? res.data : (res.data ? [res.data] : []) if (tempList && tempList.length) { ths.filterOptions = tempList resolve(tempList) } else { reject(new Error()) } }).catch(res => { reject(new Error()) }) }) return promise }, blurFn () { this.filterKey = '' }, // 值变动后回调 changeFn (value) { let nodes = [] if (this.needReturnCheckedNodes) { nodes = this.$refs.dictCascaderRef.getCheckedNodes() || [] } this.$emit('change', value, nodes) }, // 获取子项列表 getChildrenInfo (current, resolve) { if (!current || !current.data || !current.data.id) { return false } // 如果曾经有返回子节点数据 if (current.data.leaf || (resolve && current.data.children && current.data.children.length)) { resolve([]) } else { const params = { node_id: current.data.id } const ths = this ths.$store.dispatch('dictdata/getTreeChildByKey', params).then(res => { let tempList = [] if (res.data && res.data.length && res.data[0].children && res.data[0].children.length) { tempList = this.removeEmptyFn(res.data[0].children || []) } if (resolve) { resolve(tempList) } }).catch(res => { resolve([]) }) } }, // 移除子列表为空 removeEmptyFn (list = []) { const ths = this const tempList = list tempList.forEach(item => { if (!item.children || !item.children.length) { delete item.children } else { item.children = ths.removeEmptyFn(item.children) } }) return tempList }, /** * 依据以后值获取树(用于回显 *例如 [[11,111,1111], [13,131]] 则从后盾返回第一级别所有数据【11;12;13...】,【11】children的所有数据,【111】children的所有数据,【13】children的所有数据,) */ getAllTreeByCurrent () { const ths = this const params = { path: ths.currentVal || [], source_uri: ths.dictKey } ths.isFinishedGetOptions = false ths.$store.dispatch('xxxx/getAllTreeByCurrent', params).then(res => { const tempList = Array.isArray(res.data) ? res.data : (res.data ? [res.data] : []) if (tempList && tempList.length) { ths.isFinishedGetOptions = true ths.orginList = tempList } else { ths.getTreeInfo() } }).catch(res => { ths.isFinishedGetOptions = true }) }, // 初始化信息 getTreeInfo () { const ths = this const params = { key: ths.dictKey, view_type: 'tree' } ths.isFinishedGetOptions = false ths.$store.dispatch('xxx/getTreeInfo', params).then(res => { const tempList = res.data || [] ths.orginList = tempList }).catch(res => { }).finally(() => { ths.isFinishedGetOptions = true }) }, // 初始化第一级信息 getInitTree (resolve) { const ths = this if (ths.isFinishedGetOptions) { if (resolve) { resolve(ths.orginList) } } else { setTimeout(() => { ths.getInitTree(resolve) }, 300) } } } }

November 4, 2020 · 3 min · jiezi

关于vue.js:04VUE中的常用指令操作

背景剖析传统的html并不反对表达式、分支语句、循环语句等构造的定义,为了补救其有余很多前端框架,模板引擎通过在html元素中增加自定义属性,而后底层再借助解析引擎对html自定义属性进行解决,以这样的形式来加强html的性能。 Vue中的罕用指令v-bind在html中如果心愿元素的属性值随程序内容的产生而变动,能够借助v-bind或:代替,其根本语法如: <元素 v-bind:属性名="变量或js表达式">也能够采纳其简化模式,其根本语法如: <元素 :属性名="变量或js表达式">案例剖析: <div id="app"> <font :color="color">hello</font> </div> <script> new Vue({ el:"#app", data:{ color:"red" } }); </script>v-showv-show为一个专门管制元素的显示暗藏的非凡指令,其根本语法为: <元素 v-show="bool类型的变量或返回bool类型的js表达式">当Vue对象扫描到v-show时,就会立即执行""中的变量或js表达式,如果变量或js表达式的值为true,则什么也不干,元素放弃原样显示。如果变量或js表达式的值为false,则new Vue()主动为以后元素增加display:none。 示例要害代码如下: <style> .pop{ width:300px; height:150px; background-color:lightGreen; } .pop>.close{ float:right; padding:5px 10px; cursor:pointer; } </style> <div id="app"> <button @click="show">show</button> <div v-show="display" class="pop"> <span class="close" @click="hide">×</span> </div> </div> <script> //2. 创立new Vue对象 new Vue({ el:"#app", data:{ display:false }, methods:{ show(){ this.display=true; }, hide(){ this.display=false; } } }) </script>v-if 和 v-elsev-if 和 v-else 是在html实现分支管制,二选一的一种实现形式,在应用时,v-if和v-else对应的的两个元素必须紧挨着写!两头不能插入其余元素,其根本语法为: ...

November 3, 2020 · 2 min · jiezi

关于vue.js:vue-cli30去除严格模式验证的方法之一

删除这一项,从新serve就好了

November 3, 2020 · 1 min · jiezi

关于vue.js:在-Vuejs-中集成-CSS-框架

作者:Dave Berning翻译:疯狂的技术宅 原文:https://www.digitalocean.com/... 未经容许严禁转载 CSS 框架之所以杰出是有很多起因的:比方代码更容易了解、Web 利用更容易保护、简化实现原型时的步骤等。一般来说在 VUE 中集成 CSS 框架的办法是雷同的,本文以被宽泛应用的 Bootstrap 4 为例。 筹备工作在下载 CSS 框架之前,先用 Vue CLI 创立一个新我的项目: npm install vue-clivue init webpack project-name装置并集成 Bootstrap 4创立并初始化新的 Vue 我的项目后,用 npm 下载 Bootstrap 4。因为 Bootstrap 4 的 JavaScript 依赖于 jQuery,所以还须要装置 jQuery。 npm install bootstrap jquery --save你须要在本人的 Vue 的 main.js 文件中增加 Bootstrap 依赖项,这样就能够在整个程序中全局应用。 import './../node_modules/jquery/dist/jquery.min.js';import './../node_modules/bootstrap/dist/css/bootstrap.min.css';import './../node_modules/bootstrap/dist/js/bootstrap.min.js';如果你的程序构建失败,应该装置 popper.js 依赖项。之后应该就不会报错了。 npm install --save popper.js这样 Bootstrap 4 就被集成到 Vue 重了。 ...

November 3, 2020 · 2 min · jiezi

关于vue.js:一个vue项目中配置请求多个服务端解决方案

前言:最近我的项目开发中,遇到这么个状况,一个前端我的项目须要搭配两个服务端接口,所以前端的代理须要从新批改,遂记录一、解决方案1.1 形容接口context-path后端的两个接口服务申请前缀,如下: 前缀1: /mini-rest前缀2: /1.2 vue.config.js配置devServer: { port: 8005, proxy: { // 第一台服务器配置 '/mini-rest': { target: 'http://localhost:8085', ws: true, changeOrigin: true, pathRewrite: { '^/mini-rest': '/mini-rest' } }, // 第二台服务器配置 '/': { target: 'http://localhost:8899', ws: true, changeOrigin: true, pathRewrite: { '^/': '/' } } }}1.3 axios批改// api base_url,设置前缀不存在const BASE_URL = ''// 创立 axios 实例const service = axios.create({ baseURL: BASE_URL, timeout: 6000 // 申请超时工夫})此时axios不须要间接指定baseUrl配置1.4 发送申请// 申请前缀为“/”dibootApi.get("/trans").then(res => { console.log('/', res)}).catch(err => { console.log(err)})// 申请前缀为“mini-rest”dibootApi.get("/mini-rest/getTest").then(res => { console.log('/mini-rest', res)}).catch(err => { console.log(err)})注:申请的时候手动加上前缀1.5 后果展现 ...

November 2, 2020 · 1 min · jiezi

关于vue.js:vue的复制粘贴-clipboardjs

点击复制性能次要通过 clipboard.js 来实现 1、引入clipboard.js,办法如下: 第一种间接npm装置:npm install clipboard --save 第二种:<script src="js/clipboard.min.js"></script>(下载地址:https://clipboardjs.com/) 2、在须要应用的组件中import 援用办法:import Clipboard from 'clipboard'; components: {Clipboard},3、增加须要复制的内容 例如:<button class="tag-read" data-clipboard-text="我是能够复制的内容,请点击复制" @click="copy">立刻浏览</button> 解析: data-clipboard-text 后边跟须要复制的内容 4、增加点击后的办法 copy(index){ var clipboard = new Clipboard('.copyStr'+index); clipboard.on('success', e => { this.$message.success("复制胜利"); // 开释内存 clipboard.destroy() }) clipboard.on('error', e => { // 不反对复制 this.$message.warning("该浏览器不反对主动复制"); // 开释内存 clipboard.destroy() })},

November 2, 2020 · 1 min · jiezi

关于vue.js:从新认识零代码aPaaS看JNPF带飞开发

什么是零代码平台“零代码”开发平台是为那些不晓得也不须要晓得任何理论的编程语言来应用应用程序的开发者而构建的。 零代码平台的长处零代码开发平台把开发软件所须要的权限、界面、数据、交互、流程形象进去,组成一套简略好用配置页面。即便没有丰盛的计算机专业常识和代码能力,在这些aPaaS平台中,任何人都能够创立一个有用的应用程序。 什么是aPaaS你能够把aPaaS了解为PaaS的一种子模式。aPaaS的全称是application Platform as a Service,即应用程序平台即服务。Gartner对其所下的定义是:“这是基于PaaS(平台即服务)的一种解决方案,反对应用程序在云端的开发、部署和运行,提供软件开发中的根底工具给用户,包含数据对象、权限治理、用户界面等。” aPaaS有什么益处对于中小企业而言,aPaaS的益处是不言而喻的,咱们来自认真看下aPaaS的三大次要特色: 零代码: 应用aPaaS的解决方案,非技术人员也能构建业务应用程序。 零代码的益处是不言而喻的,以往须要数月或数年能力实现的软件开发我的项目,个别能够在几周甚至几天内实现。而依据Garter的调研,应用aPaaS工具节俭的人力费用可高达350% 可扩展性: aPaaS工具另一个特点是具备很高的拓展性。假如你利用某个平台开发了一套订单管理系统,前期发现须要减少新的工具。依照以往的做法,必定是找到技术人员,或者厂商帮你定制某个性能,然而在aPaaS平台中,你只须要找到一个纯熟业务的人员,即可在短时间内疾速让该性能上线。 云服务: 跟本地化软件相比,aPaaS天生就有云技术的劣势。这象征,你能够在多个设施、任何工夫拜访数据。同时,aPaaS厂商的IT运维能力也远远高于个别中小企业,保证数据的安全可靠。另外,在应用老本上,云服务的费用也远远低于本地开发。 Gartner的说法:“简化的预算编制和对利用程序开发老本的更好可见性,从而能够进行更精确的我的项目估算。”借助aPaaS,残缺的Web应用程序生命周期可立刻应用:构建,测试,部署,治理和更新。因为底层根底构造曾经被编写、测试和优化,所以该平台容许进行低代码开发,而经验丰富的程序员能够节省时间去发明更有价值的货色。 零代码+aPaaS:疾速开发可能怎么做零代码+aPaaS最大的作用在于解放开发的效率,在JNPF中蕴含大量的性能组件,光一个报表就包含了计算编辑器,柱状图、折线图、排名表、表格、双轴图图、饼状图等近20种图表,计数、分组、平均值、排序、条件返回等20余种公式函数设置,这些组件当初都不必本人从新去写了,间接拖拽调用就能应用了。 而且JNPF是一体化开发平台,可同时开发PC端和挪动端,适配多种浏览器和小程序平台,大大节约了企业资源。 两者的联合,让企业开发效率大大提高,同时随着零代码技术的日趋成熟,开发日益智能化,即便是个性化需要下的开发,也能满足。

November 2, 2020 · 1 min · jiezi