【全栈第一课】Vue快速入门

往期文章

【全栈第二课】微信小程序快速入门
【全栈第三课】通过ChatGPT快速入门NodeJS
【全栈第四课】TypeScript 入门教程

一、前端工程化

image-20221115083618555

JS的复用就是模块化

UI样式复用就是组件化(LayUI里面的都是组件化)

所以说前端工程化就是有规范的写,不能你一个样式我一个样式,不够统一不够专业!

二、WebPack

是什么

image-20221115084730331

前端工程化的具体实现方案

基本使用

实现奇偶行变色

1.初始化包管理工具

通过npm init -y生成

image-20221115085243047

2.安装jquery

-S的意思是–save

npm install jquery -S

3.在项目中安装webpack

-D就是把包放到devDependencies下,打包运行的时候不会被打包

-D为–save-dev简写

npm install webpack@5.42.1 webpack-cli@4.7.2 -D 

image-20221115095016557

4.在项目中配置webpack

在项目根目录中,创建名为 webpack.config.js 的 webpack 配置文件,并初始化如下的基本配置:

module.exports = {mode: 'development'
};

在 package.json 的 scripts 节点下,新增 dev 脚本如下:

image-20221115102840682

tips:webpack要和src同目录

image-20221115102745568

5.运行代码

通过npm run dev运行

这里的webpack将用jQuery写的操作和一些新的写法转换成了能被浏览器兼容的js文件(dist下的main.js)

image-20221115103323407

实现效果如下:

image-20221115104323386

mode 的可选值

development

开发环境

不会对打包生成的文件进行代码压缩和性能优化

打包速度快,适合在开发阶段使用

production

生产环境

会对打包生成的文件进行代码压缩和性能优化

打包速度很慢,仅适合在项目发布阶段使用

image-20221115104043506

webpack.config.js 文件的作用

webpack.config.js 是 webpack 的配置文件。

webpack 在真正开始打包构建之前,会先读取这个配置文件, 从而基于给定的配置,对项目进行打包。

注意:由于 webpack 是基于 node.js 开发出来的打包工具,因此在它的配置文件中,支持使用 node.js 相关 的语法和模块进行 webpack 的个性化配置。

webpack 中的默认约定

在 webpack 4.x 和 5.x 的版本中,有如下的默认约定:

① 默认的打包入口文件为 src -> index.js

② 默认的输出文件路径为 dist -> main.js

注意:可以在 webpack.config.js 中修改打包的默认约定

自定义打包的入口与出口

在 webpack.config.js 配置文件中,通过 entry 节点指定打包的入口。通过 output 节点指定打包的出口。

示例代码如下:

const path = require('path')//导入node.js中专门操作路径的模块module.exports = {mode: 'production',entry: path.join(__dirname,'./src/index.js'),//打包的入口文件output: {path: path.join(__dirname,'./dist'),//存放路径filename: "nice.js"//输入的文件名}
};

image-20221115105746224

webpack中的插件

webpack 插件的作用

通过安装和配置第三方的插件,可以拓展 webpack 的能力,从而让 webpack 用起来更方便。最常用的webpack 插件有如下两个:

① webpack-dev-server

类似于 node.js 阶段用到的 nodemon 工具(修改代码自动重新打包和构建)

每当修改了源代码,webpack 会自动进行项目的打包和构建(最常用)

② html-webpack-plugin

webpack 中的 HTML 插件(类似于一个模板引擎插件)

可以通过此插件自定制 index.html 页面的内容

安装之后我们还不能直接访问,因为打包生成的文件存放到了内存中

生成到内存中的文件该如何访问?

webpack-dev-server 生成到内存中的文件,默认放到了项目的根目录中,而且是虚拟的、不可见的。

可以直接用 / 表示项目根目录,后面跟上要访问的文件名称,即可访问内存中的文件

例如 /bundle.js 就表示要访问 webpack-dev-server 生成到内存中的 bundle.js 文件

所以我们只有把index页面放到根目录它才能和bundle.js联合使用,才能实现实时更新

怎么实现呢?拷贝过去一份不就行了!我们用下面的方法来实现

html-webpack-plugin

html-webpack-plugin 是 webpack 中的 HTML 插件,可以通过此插件自定制 index.html 页面的内容。

需求:通过 html-webpack-plugin 插件,将 src 目录下的 index.html 首页,复制到项目根目录中一份!

安装

npm install html-webpack-plugin@5.3.2 -D

配置

const path = require('path')//导入node.js中专门操作路径的模块
const HtmlPlugin = require('html-webpack-plugin')// 创建html插件的实例对象
const htmlPlugin = new HtmlPlugin({template: './src/index.html',//源文件存放路径filename: './index.html'//生成的文件存放路径
})module.exports = {mode: 'development',plugins: [htmlPlugin]//通过plugins节点,使htmlPlugin插件生效
};

总结

  • 通过 HTML 插件复制到项目根目录中的 index.html 页面,也被放到了内存中
  • HTML 插件在生成的 index.html 页面,自动注入了打包的 bundle.js 文件

devServer 节点

在 webpack.config.js 配置文件中,可以通过 devServer 节点对 webpack-dev-server 插件进行更多的配置, 示例代码如下:

module.exports = {mode: 'development',plugins: [htmlPlugin],//通过plugins节点,使htmlPlugin插件生效devServer: {open: true,// host: '',port: 80}
};

mac中要加sudo才能监听

webpack 中的 loader

loader 概述

在实际开发过程中,webpack 默认只能打包处理以 .js 后缀名结尾的模块。其他非 .js 后缀名结尾的模块, webpack 默认处理不了,需要调用 loader 加载器才可以正常打包,否则会报错!

loader 加载器的作用:协助 webpack 打包处理特定的文件模块。比如:

  • css-loader 可以打包处理 .css 相关的文件
  • less-loader 可以打包处理 .less 相关的文件
  • babel-loader 可以打包处理 webpack 无法处理的高级 JS 语法

image-20221115142755075

loader 的调用过程

image-20221115141421952

打包处理 css 文件

  • 运行 npm i style-loader@3.0.0 css-loader@5.2.6 -D 命令,安装处理 css 文件的 loader

  • 在 webpack.config.js 的 module -> rules 数组中,添加 loader 规则如下:

module: {rules: [{test: /\.css$/, use: ['style-loader', 'css-loader']}]
}

image-20221115143446870

打包处理 less 文件

less文件可以让CSS写的更简单,这里是让无序列表的间隙消失

html,
body,
ul{margin: 0;padding: 0;li{line-height: 30px;padding-left: 20px;font-size: 12px;}
}

之后在index.js文件中引入改less文件即可

如果不设置less文件加载器,也会报错.所以运行 npm i less-loader@10.0.1 less@4.1.1 -D 命令

在 webpack.config.js 的 module -> rules 数组中,添加 loader 规则如下:

module: {rules: [{test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader']}]
}

效果不放了因为太刺眼了

打包发布

通过前面的学习我们也能知道,你输入npm run dev 的时候它就会生成一个dist目录,这个dist目录其实就是打包好的,可以直接点index文件去访问的

现在项目要上线了,我们要减少dist文件的体积,其实就是运行npm run 生产环境的配置

在package.json配置一下:

"scripts": {"dev": "webpack serve","build": "webpack --mode production"
},

image-20221115155918186

运行程序:

npm run build

总结

webpack了解概念即可,后面使用脚手架这东西都是配置好的

  • 运行程序npm run dev
  • 发布程序npm run build

如果不是这个两个命令,那就去看它的package咋写的替换run 后面的单词即可

三、Vue基础入门

Vue简介

什么是Vue

构建用户界面的框架

  • 构建用户界面

用 vue 往 html 页面中填充数据,非常的方便

  • 框架

框架是一套现成的解决方案,程序员只能遵守框架的规范,去编写自己的业务功能!

要学习 vue,就是在学习 vue 框架中规定的用法!

vue 的指令、组件(是对 UI 结构的复用)、路由、Vuex、vue 组件库

Vue 的两个特性

数据驱动视图:

  • 数据的变化会驱动视图自动更新
  • 好处:程序员只管把数据维护好,那么页面结构会被 vue 自动渲染出来!

image-20221115161034333

双向数据绑定:

在网页中,form 表单负责采集数据,Ajax 负责提交数据

  • js 数据的变化,会被自动渲染到页面上
  • 页面上表单采集的数据发生变化的时候,会被 vue 自动获取到,并更新到 js 数据中

注意:数据驱动视图和双向数据绑定的底层原理是 MVVM(Mode 数据源、View 视图、ViewModel 就是 vue 的实例)

image-20221115161236461

MVVM的原理

image-20221115161907387

image-20221115164735079

总结

课件其实已经总结的很好了,MVVM最重要的就是VUE的实例VM(ViewModel)

  • 它监听DOM的变化,当表单中的值发生变化时,VM会把数据同步到Model源中
  • 它监听Model的变化,当Model发生变化时,它会把最新数据同步到View里

Vue的基本使用

Vue的基本使用步骤

  • 导入vue.js文件
  • 在页面声明一个将要被vue所控制的DOM区域
  • 创建vm实例
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><title>Title</title></head><body><div id="app">{{username}}</div><script src="./lib/vue-2.6.12.js"></script><script>const vm = new Vue({el: "#app",data: {username: "zs",},});</script></body>
</html>

基本代码与 MVVM 的对应关系

image-20221115173712799

Vue指令

内容渲染指令

  1. v-text 指令的缺点:会覆盖元素内部原有的内容!
  2. {{ }} 插值表达式:在实际开发中用的最多,只是内容的占位符,不会覆盖原有的内容!
  3. v-html 指令的作用:可以把带有标签的字符串,渲染成真正的 HTML 内容!

属性绑定指令

注意:插值表达式只能用在元素的内容节点中,不能用在元素的属性节点中!

  • 在 vue 中,可以使用 v-bind: 指令,为元素的属性动态绑定值;

  • 简写是英文的 :

  • 在使用 v-bind 属性绑定期间,如果绑定内容需要进行动态拼接,则字符串的外面应该包裹单引号,例如:

    <div :title="'box' + index">这是一个 div</div>
    

事件绑定

  1. v-on: 简写是 @

  2. 语法格式为:

    <button @click="add"></button>methods: {add() {// 如果在方法中要修改 data 中的数据,可以通过 this 访问到this.count += 1}
    }
    
  3. $event 的应用场景:如果默认的事件对象 e 被覆盖了,则可以手动传递一个 $event。例如:

    <button @click="add(3, $event)"></button>methods: {add(n, e) {// 如果在方法中要修改 data 中的数据,可以通过 this 访问到this.count += 1}
    }
    
  4. 事件修饰符:

    • .prevent

      <a @click.prevent="xxx">链接</a>
      
    • .stop

      <button @click.stop="xxx">按钮</button>
      

image-20221115192231374

v-model 指令

  1. input 输入框
    • type=“radio”
    • type=“checkbox”
    • type=“xxxx”
  2. textarea
  3. select

条件渲染指令

  1. v-show 的原理是:动态为元素添加或移除 display: none 样式,来实现元素的显示和隐藏
    • 如果要频繁的切换元素的显示状态,用 v-show 性能会更好
  2. v-if 的原理是:每次动态创建或移除元素,实现元素的显示和隐藏
    • 如果刚进入页面的时候,某些元素默认不需要被展示,而且后期这个元素很可能也不需要被展示出来,此时 v-if 性能更好

在实际开发中,绝大多数情况,不用考虑性能问题,直接使用 v-if 就好了!!!

v-if 指令在使用的时候,有两种方式:

  1. 直接给定一个布尔值 true 或 false

    <p v-if="true">被 v-if 控制的元素</p>
    
  2. 给 v-if 提供一个判断条件,根据判断的结果是 true 或 false,来控制元素的显示和隐藏

    <p v-if="type === 'A'">良好</p>
    

过滤器

Vue3已经放弃,Vue2可以用

怎么理解过滤器?就跟linux里的grep命令一样,就是筛选,它定义在filters里面

我们来看看代码示例:

  • 要定义到 filters 节点下,本质是一个函数
  • 在过滤器函数中,一定要有 return 值
  • 在过滤器的形参中,可以获取到“管道符”前面待处理的那个值
  • 如果全局过滤器和私有过滤器名字一致,此时按照“就近原则”,调用的是”私有过滤器“
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<div id="app"><p>message的值是{{message | capi}}</p>
</div><script src="/lib/vue-2.6.12.js"></script><script>const vm = new Vue({el: '#app',data: {message: 'hello vue.js'},filters:{//过滤器函数形参中的val,永远都是"管道符"前面的那个值capi(val){const first = val.charAt(0).toUpperCase()const other = val.slice(1)return first + other}}})
</script></body>
</html>

全局过滤器

全局过滤器 - 独立于每个 vm 实例之外
Vue. filter()方法接收两个参数:
第1 个参数,是全局过滤器的”名字”
第2 个参数,是全局过滤器的”处理函数”

Vue.filter('capi',(val) =>{return val.charAt(0).toUpperCase() + val.slice(1) + '~~~~~~~~~~~~~'
})

连续调用多个过滤器

把 message 的值,交给 filterA 进行处理
把 filterA 处理的结果,再交给 filterB 进行处理
最终把 filterB 处理的结果,作为最终的值這染到页面上
{{ message 1 filterA I filterB }}

{{ message | filterA | filterB }}

过滤器传参

过滤器的本质是 JavaScript 函数,因此可以接收参数,格式如下:

image-20221116113238654

示例代码如下:

image-20221116113315121

入门实例

实现增删查功能

实现思路:

  • 增加功能

首先要收集品牌名称,然后阻止表单的默认提交行为,改为调用自定义方法add

在add中定义要添加的对象,name为收集到的brand,状态为status设置为默认值即可,创建时间也设置一个默认值即可

id的话想要保证自增,所以可以自定义一个id,然后每添加一个对象id+1

对象创建好之后,直接push进list列表即可

  • 删除功能

从list列表中过滤对象,通过传入的对象id即可过滤

  • 查询功能

通过v-for去遍历data区域的list数组

image-20221116105130811

完整代码如下:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>品牌列表案例</title><link rel="stylesheet" href="./lib/bootstrap.css"><link rel="stylesheet" href="./css/brandlist.css">
</head><body><div id="app"><!-- 卡片区域 --><div class="card"><div class="card-header">添加品牌</div><div class="card-body"><!-- 添加品牌的表单区域 --><!--            表单有默认的提交行为,通过@submit.prevent可以阻止它的默认行为--><form @submit.prevent="add"><div class="form-row align-items-center"><div class="col-auto"><div class="input-group mb-2"><div class="input-group-prepend"><div class="input-group-text">品牌名称</div></div><input type="text" class="form-control" placeholder="请输入品牌名称" v-model.trim="brand"></div></div><div class="col-auto"><button type="submit" class="btn btn-primary mb-2">添加</button></div></div></form></div></div><!-- 表格区域 --><table class="table table-bordered table-hover table-striped"><thead><tr><th scope="col">#</th><th scope="col">品牌名称</th><th scope="col">状态</th><th scope="col">创建时间</th><th scope="col">操作</th></tr></thead><tbody><tr v-for="item in list" :key="item.id"><td>{{item.id}}</td><td>{{item.name}}</td><td><div class="custom-control custom-switch"><input type="checkbox" class="custom-control-input" :id="'cd' + item.id" v-model="item.status"><label class="custom-control-label" :for="'cd' + item.id" v-if="item.status">已启用</label><label class="custom-control-label" :for="'cd' + item.id" v-else>已禁用</label></div></td><td>{{item.time}}</td><td><a href="javascript:;" @click="remove(item.id)">删除</a></td></tr></tbody></table>
</div><script src="./lib/vue-2.6.12.js"></script><script>const vm = new Vue({el: '#app',data: {//品牌的列表数据brand: "",list: [{id: 1, name: '宝马', status: true, time: new Date()},{id: 2, name: '奔驰', status: false, time: new Date()},{id: 3, name: '奥迪', status: true, time: new Date()},],nextId: 4,},methods: {remove(id) {// console.log(id)this.list = this.list.filter(item => item.id != id)},add() {// console.log(this.brand)// 如果判断到brand的值为空字符串,则return出去if (this.brand === '') return alert("必须填写品牌名称")// 如果没有return出去,应该去执行添加的逻辑// 先把要添加的品牌对象,整理出来const obj = {id: this.nextId,name: this.brand,status: true,time: new Date()}this.list.push(obj)this.brand = ''this.nextId += 1}}})
</script>
</body></html>

四、Vue基础进阶

watch 侦听器

什么是侦听器

watch 侦听器允许开发者监视数据的变化,从而针对数据的变化做特定的操作

image-20221116114639935

侦听器的格式

  1. 方法格式的侦听器

    • 缺点1:无法在刚进入页面的时候,自动触发!!!
    • 缺点2:如果侦听的是一个对象,如果对象中的属性发生了变化,不会触发侦听器!!!
  2. 对象格式的侦听器

    • 好处1:可以通过 immediate 选项,让侦听器自动触发!!!

    image-20221116152955400

    • 好处2:可以通过 deep 选项,让侦听器深度监听对象中每个属性的变化!!!

    image-20221116153008596

侦听器测试

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><div id="app"><input type="text" v-model="username">
</div>
<script src="/lib/vue-2.6.12.js"></script><script>const vm = new Vue({el: '#app',data: {username: '',},watch: {username(newOlder, oldValue) {console.log('监听到了username发生了变化', newOlder, oldValue)},}})
</script></body>
</html>

image-20221116120019015

计算属性

是什么?

计算属性指的是通过一系列运算之后,最终得到一个属性值。

这个动态计算出来的属性值可以被模板结构或 methods 方法使用。示例代码如下:

image-20221117110139193

特点

  • 定义的时候,要被定义为“方法”
  • 使用计算属性的时候,当普通的属性使用即可

好处

  • 实现了代码的复用
  • 只要计算属性中依赖的数据源变化了,则计算属性会自动重新求值!

axios

axios(发音:艾克C奥斯) 是一个专注于网络请求的库!

它封装了Ajax(通过 Ajax 可以异步从服务器请求数据并将数据更新到网页中,整个过程不需要重载(刷新)整个网页,可以将网页的内容更快的呈现给用户。)

axios 的基本使用

发起 GET 请求

axios({// 请求方式method: 'GET',// 请求的地址url: 'http://www.liulongbin.top:3006/api/getbooks',// URL 中的查询参数params: {id: 1},//请求体参数data:{}
}).then(function (result) {console.log(result)
})

简写:

const resu = axios.get('https://www.escook.cn/api/cart')
resu.then(function (books) {console.log(books)
})

axios返回的是一个Promise对象,在Promise对象中并不是服务器返回的结果,而是axios对服务器返回的结果又进行了一次封装,如下:

image-20221119172253294

简化如下:

image-20221119171748440

发起 POST 请求

document.querySelector('#btnPost').addEventListener('click', async function () {// 如果调用某个方法的返回值是 Promise 实例,则前面可以添加 await!// await 只能用在被 async “修饰”的方法中const { data: res } = await axios({method: 'POST', url: 'http://www.liulongbin.top:3006/api/post',data: {name: 'zs',age: 20}})console.log(res)
})

使用解构赋值

基于axios

image-20221119182015125

vue-cli

什么是单页面应用程序?

SPA(Single Page Application)

指的就是一个Web网站中只有唯一的一个HTML页面,所有的功能与交互都是在这唯一的一个页面完成

一般Vue项目打包之后会生成一个dist文件,这个dist文件就是下面这个样式的

image-20221117110545419

什么是vue-cli?

快速生成一个vue项目的开发环境,程序员可以专注在撰写应用上,而不必花好几天去纠结 webpack 配置的问题。

安装和使用

image-20221117111105875

  1. 在终端下运行如下的命令,创建指定名称的项目:

    vue cerate 项目的名称
    
  2. vue 项目中 src 目录的构成:

    assets 文件夹:存放项目中用到的静态资源文件,例如:css 样式表、图片资源
    components 文件夹:程序员封装的、可复用的组件,都要放到 components 目录下
    main.js 是项目的入口文件。整个项目的运行,要先执行 main.js
    App.vue 是项目的根组件。
    

vue项目的运行流程

在工程化的项目中,vue 要做的事情很单纯:通过main.jsApp.vue渲染到 index.html 的指定区域中。

image-20221117152015785

  • App.vue 用来编写待渲染的模板结构
  • index.html 中需要预留一个 el 区域
  • main.js 把 App.vue 渲染到了 index.html 所预留的区域中

渲染之后,会代替index页面原有的代码

image-20221117152808987

vue组件

组件化开发

组件化开发指的是:根据封装的思想,把页面上可重用的 UI 结构封装为组件,从而方便项目的开发和维护。

vue 中的组件化开发

vue 是一个支持组件化开发的前端框架。 vue 中规定:组件的后缀名是 .vue。之前接触到的 App.vue 文件本质上就是一个 vue 的组件

vue 组件的三个组成部分

每个.vue组件都由3部分构成,分别是:

template -> 组件的模版结构

Script -> 组件的JavaScript行为

Style -> 组件的样式

其中,每个组件中必须包含 template 模板结构,而 script 行为和 style 样式是可选的组成部分

template

vue 规定:每个组件对应的模板结构,需要定义到<template>节点中

<template>
<!--当前组件的DOM结构,需要定义到template标签的内部 -->
</template>

tips:

  • template是vue提供的容器标签,只起到包裹性质的作用,他不会被渲染为真正的DOM元素
  • template 中只能包含唯一的根节点

script

vue 规定:开发者可以在 <script> 节点中封装组件的 JavaScript 业务逻辑。

image-20221117114636442

.vue 组件中的 data 必须是函数

image-20221117114820766

style

image-20221117114843269

image-20221117114906636

实例

<template><div class="wahahaha"><h3>这是用户自定义的vue组件--{{ username }}</h3></div>
</template><!--固定写法-->
<script>
export default {data() {return {username: 'zs'}}
}
</script><style>.wahahaha{background-color: pink;}
</style>

启用less语法以及唯一根节点

  • 组件中只能有一个根节点,也就是说不能写多个一级div,只能在一级div里定义多个低级div
  • less语法就是让css的编写更简单
<template><div><div id="wahahaha"><h3>这是用户自定义的vue组件--{{ username }}</h3><button @click="changeName">点我改变名字</button></div><div>123</div></div></template><!--固定写法-->
<script>
export default {data() {return {username: 'zs'}},methods: {changeName() {console.log(this),this.username = 'Wahahah'}},// 当前组件的监听器watch: {},// 当前组件的计算属性computed: {}
}
</script><style lang="less">
#wahahaha {background-color: pink;h3 {color: azure;}
}
</style>

组件之间的父子关系

image-20221117114957733

使用组件的三个步骤

image-20221117115039148

实例

image-20221117163916959

Hello.vue是我后来加

image-20221117165053906

通过 components 注册的是私有子组件

例如:

  • 在组件 A 的 components 节点下,注册了组件 F。

  • 则组件 F 只能用在组件 A 中;不能被用在组件 C 中。

注册全局组件

在 vue 项目的 main.js 入口文件中,通过 Vue.component() 方法,可以注册全局组件。

实例如下:

image-20221117115346254

组件的props

props 是组件的**自定义属性**,在封装通用组件的时候,合理地使用 props 可以极大的提高组件的复用性!

  • props中的数据,可以直接在模版结构中使用

image-20221117200707847

实例

left组件

  • 使用v-bind可以给属性赋值
  • 这里init自定义属性为字符串类型,通过v-bind代表你后面写的是js表达式,数字在js中就是Number型
<template><div class="left-container"><h3>我是left</h3><MyCount :init="9"></MyCount></div>
</template><script>
export default {name: "Left",
}
</script><style>
.left-container {padding: 0 20px 20px;background-color: #42b983;min-height: 250px;flex: 1;
}
</style>

count组件

<template><div><p>count的值是:{{ init }}</p><button @click="init += 1">Hi,点我给count+1</button></div>
</template><script>
export default {props: ['init'],name: "Count",data() {return {count: 0,}}
}
</script><style scoped></style>

如图所示:

image-20221117200944902

props 是只读的

image-20221117201751163

要想修改 props 的值,可以把 props 的值转存到 data 中,因为 data 中的数据都是可读可写的!

所以props值的作用就是做一个初始化,最好是去操作data里的数据,所以这里可以通过this.init去把初始值赋给data里的count

this代表当前组件对象

<template><div><p>count的值是:{{ count }}</p><button @click="count += 1">Hi,点我给count+1</button></div>
</template><script>
export default {props: ['init'],name: "Count",data() {return {count: this.init}}
}
</script><style scoped></style>

props 的 default 默认值

在声明自定义属性时,可以通过 default 来定义属性的默认值。示例代码如下:

props:{

​ 自定义属性A:{},

​ 自定义属性B:{},

​ 自定义属性C:{},

}

export default {props: {init: {default: 0,}},name: "Count",data() {return {count: this.init}}
}

props 的 type 值类型

在声明自定义属性时,可以通过 type 来定义属性的值类型。示例代码如下:

export default {props: {init: {default: 0,}},name: "Count",data() {return {count: this.init,type: Number}}
}

props 的 required 必填项

就是说,你自定义的这个属性是必填项,不填就会报错

image-20221117203428415

组件之间的样式冲突问题

scoped

默认情况下,写在 .vue 组件中的样式会全局生效,因此很容易造成多个组件之间的样式冲突问题。

导致组件之间样式冲突的根本原因是:

  • 单页面应用程序中,所有组件的 DOM 结构,都是基于唯一的 index.html 页面进行呈现的
  • 每个组件中的样式,都会影响整个 index.html 页面中的 DOM 元素

为了提高开发效率和开发体验,vue 为 style 节点提供了 scoped 属性,从而防止组件之间的样式冲突问题:

image-20221117204209632

/deep/ 样式穿透

image-20221117204641697

什么时候会用到

如果代码引入了第三方组件库,想修改它的样式不能去直接修改它的源码,找到要修改的组件位置通过/deep/做样式穿透

五、生命周期&数据共享

生命周期 & 生命周期函数

生命周期(Life Cycle)是指一个组件从创建 -> 运行 -> 销毁的整个阶段,强调的是一个时间段

生命周期函数:是由 vue 框架提供的内置函数,会伴随着组件的生命周期,自动按次序执行。

注意:生命周期强调的是时间段,生命周期函数强调的是时间点。

组件生命周期函数的分类

image-20221118072616877

生命周期详解

简洁版本

回调函数是你留个处理方法给事件,事件发生了以后会自动执行你留下调处理方法

钩子函数是好比找了个代理,监视事件是否发生,如果发生了这个代理就执行你的事件处理方法;在这个过程中,代理就是钩子函数

在某种意义上,回调函数做的处理过程跟钩子函数中要调用调方法一样
但是有一点: 钩子函数一般是由事件发生者提供的。直白了说,它留下一个钩子,这个钩子的作用就是钩住你的回调方法

==钩子函数是在一个事件触发的时候,在系统级捕获到了他,然后做一些操作。==一段用以处理系统消息的程序,用以处理系统消息的程序,是说钩子函数是用于处理系统消息的

img

详细版本

lifecycle

最重要的三个阶段

  • created

    组件的 porps/data/methods已创建好,都处于可用的状态。但是组件的模板结构尚未生成!

  • mounted

    已经把内存中的 HTML 结构,成功的渲染到了浏览器之中。此时浏览器中己然包含了当前组件的 DOM 结构。

  • update

    组件的最新数据,可以操作最新的DOM结构

组件之间的关系

在项目开发中,组件之间的最常见的关系分为如下两种:

① 父子关系

② 兄弟关系

image-20221118083359316

父子组件之间的数据共享

父子组件之间的数据共享又分为:

① 父 -> 子共享数据

② 子 -> 父共享数据

父组件向子组件共享数据

父组件向子组件共享数据需要使用自定义属性

如下:

父组件

<template><img alt="Vue logo" src="./assets/logo.png"><HelloWorld msg="Welcome to Your Vue.js App"/><div class="box"><Left></Left><Right :username=userinfo :passwd=passwd></Right></div>
</template><script>
import HelloWorld from './components/HelloWorld.vue'
import Left from "@/components/Left";
import Right from "@/components/Right";export default {name: 'App',components: {HelloWorld,Left,Right},data() {return {userinfo: {name: 'zs', age: 12},passwd: 123}}
}
</script><style>
#app {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;margin-top: 60px;
}.box {display: flex;
}
</style>

子组件

<template><div class="rightContainer"><h2>我是right</h2><h2>您的姓名是:{{username}}</h2><h2>您的密码是:{{passwd}}</h2></div></template><script>
export default {name: "Right",props: ['username','passwd']
}
</script><style scoped>
.rightContainer {background-color: aquamarine;flex: 1;height: 300px;
}
</style>

子组件向父组件共享数据

子组件向父组件共享数据使用自定义事件。

image-20221118101743108

如下:

image-20221118102521747

image-20221118102135369

兄弟组件之间的数据共享

在 vue2.x 中,兄弟组件之间数据共享的方案是 EventBus

image-20221118103529647

EventBus 的使用步骤

  1. 创建 eventBus.js 模块,并向外共享一个 Vue 的实例对象
  2. 在数据发送方,调用 bus.$emit(‘事件名称’, 要发送的数据) 方法触发自定义事件
  3. 在数据接收方,调用 bus.$on(‘事件名称’, 事件处理函数) 方法注册一个自定义事件

ref 引用

ref 用来辅助开发者在不依赖于 jQuery 的情况下,获取 DOM 元素或组件的引用。

每个 vue 的组件实例上,都包含一个 $refs 对象,里面存储着对应的 DOM 元素或组件的引用。默认情况下,组件的 $refs 指向一个空对象。

什么是 ref 引用

ref 用来辅助开发者在不依赖于 jQuery 的情况下获取 DOM 元素或组件的引用。

每个 vue 的组件实例上,都包含一个 $refs 对象,里面存储着对应的 DOM 元素或组件的引用。默认情况下,

组件的 $refs 指向一个空对象。

image-20221118114026831

使用 ref 引用 DOM 元素

如果想要使用 ref 引用页面上的 DOM 元素,则可以按照如下的方式进行操作:

image-20221118114121487

使用 ref 引用组件实例

image-20221118114137863

控制文本框和按钮的按需切换

image-20221118114709005

让文本框自动获得焦点

当文本框展示出来之后,如果希望它立即获得焦点,则可以为其添加 ref 引用,并调用原生 DOM 对象的 .focus() 方法即可。示例代码如下:

image-20221118114802704

this.$nextTick(cb) 方法

组件的 $nextTick(cb) 方法,会把 cb 回调推迟到下一个 DOM 更新周期之后执行。通俗的理解是:等组件的 DOM 更新完成之后,再执行 cb 回调函数。从而能保证 cb 回调函数可以操作到最新的 DOM 元素。

image-20221118143829921

image-20221118143842473

数组中的方法

some循环

  • 简单来说some循环就是遇到终止条件可以停止继续寻找
  • foreach即使遇到终止条件也会继续寻找
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><script>const arr = ['詹姆斯', '科比', '2届MVP得主库里', '1.5']arr.forEach((item, index) => {console.log('ok')if (item === '2届MVP得主库里') {console.log(index)}})console.log('arr.some使用效果如下:')arr.some((item, index) => {console.log('ok')if (item === '2届MVP得主库里') {console.log(index)return true}})</script></body>
</html>

image-20221118145828031

foreach循环

foreach就是循环每一项,some是循环到满足条件就停下来

every循环

判断数组中的数据是否被全选了使用every循环

image-20221118150334089

reduce的基本用法

不用reduce计算总和

image-20221118150529758

用reduce计算总和

image-20221118150948771

reduce的简化写法

image-20221118151333626

购物车案例

导入,注册,使用组件

这里的组件是写好的,我们直接导入,注册,使用

Tips:

  • 导入的组件名称一般都给它设置为首字母大写.这样和普通标签能有一个区分

image-20221119163139000

基于axios请求列表数据

axios是对ajax的封装,向后端发送请求就用它

这里是先定义一个封装请求列表数据的方法,然后在vue的created的生命周期阶段调用

created() {this.initCartList()
},
methods: {//封装请求列表数据的方法async initCartList() {//调用axios的get方法,请求列表数据const {data: res} = await axios.get('https://www.escook.cn/api/cart')// 只要请求回来的数据,在页面渲染期间要用到,则必须转存到data里this.list = res.list}
},

这里的await是用来解构赋值的它一般和async联合使用

那么解构赋值是什么呢?

就是前段通过axios向后端发送请求之后,后端返回的数据会先经过axios进行一次封装,不能直接拿到真实数据

如下:

image-20221119171748440

所以为了直接拿到真实数据,我们需要解构,从回复的数据中取出真实数据

{{data:res}}这是啥意思呢?

axios返回的是一个Promise对象,在Promise对象中并不是服务器返回的结果,而是axios对服务器返回的结果又进行了一次封装,如下:

image-20221119172253294

通过{{data:res}}意思就是取出Promise对象中的data区域数据,并把名字重命名为res

渲染Goods组件

1.商品数据其实就是一个个Goods组件

导入,注册,使用组件

<Goods></Goods>

2.给组件赋值,这里通过v-for来实现

首先看看请求到的结果

image-20221120093440652

list数组里不就是如下一个个的对象吗,然后赋值的时候通过对象.属性即可取得对应的值

这里的:key,:id,:title等都是为子组件的自定义属性,父组件向子组件传递数据就是通过自定义属性来进行传递的

<!--    这里为啥一直要写v-bind呢因为在等号后面我们写的是js表达式,如果不写v-bind则相当于我们传给它了一个字符串!-->
<Goodsv-for="item in list":key="item.id":id="item.id":title="item.goods_name":img="item.goods_img":price="item.goods_price":state="item.goods_state "
>
</Goods>

3.修改商品的勾选状态

修改商品的勾选状态为子组件向父组件共享数据

通过自定义事件来实现

3.1 在子组件中为复选框绑定自定义事件

复选框状态每发生一次改变就会触发自定义事件

<input type="checkbox" class="custom-control-input" :id="'cb' + id" :checked="state"@change="stateChange"/>

3.2 在子组件中自定义事件如下

自定义时间名字为state-change,传递给父组件的数据为id和value

  • id表示当前商品
  • value表示最新的勾选状态
methods: {stateChange(e) {// console.log(e)console.log(e.target.checked)const newState = e.target.checked// 触发自定义事件this.$emit('state-change', {id: this.id, value: newState})}
}

3.3 父组件绑定自定义事件

通过参数e来接受子组件传来的数据

通过some循环找到改变状态的子组件判断的条件是id,找到之后给组件的状态赋值为子组件传来的真实数据

<Goods @state-change="getNewState"></Goods>
methods: {getNewState(e) {console.log(e)this.list.some(item => {if (item.id === e.id) {item.goods_state = e.value}})}},

渲染Footer组件

引入footer组件

footer组件做二件事:

  • 全选
  • 计算总价

全选为子组件向父组件共享数据 => 自定义事件

计算总价为父组件向子组件共享数据 => 自定义属性

<Footer:is-full="fullState"@fullChange="getFullState":total-prices="amt"
></Footer>

全选功能的实现

//子组件
<input type="checkbox" class="custom-control-input" id="cbFull" :checked="isFull" @change="fullChange"/>methods: {fullChange(e) {// console.log(e.target.checked)// 触发自定义事件this.$emit('fullChange', e.target.checked)}}// 动态计算全选的状态是true还是false
fullState() {return this.list.every(item => item.goods_state)
},//父组件// 动态计算全选的状态是true还是falsefullState() {return this.list.every(item => item.goods_state)},

计算总价功能的实现

子组件

props: {isFull: {type: Boolean,default: true},totalPrices: {type: Number,default: 0}
},<div><span>合计:</span>
<span class="total-price">{{ totalPrices.toFixed(2) }}</span>
</div><!-- 结算按钮 -->
<button type="button" class="btn btn-primary btn-settle">结算({{ totalPrices.toFixed() }}</button>

父组件

computed: {//总价格amt() {// 先filter过滤,在reduce累加return this.list.filter(item => item.goods_state)//只有一行的箭头函数,可以省略return和{}花括号.reduce((total, item) =>(total += item.goods_price * item.goods_count),0)}
},

购买数量实现

和计算总价实现一个思路

  • 从集合中过滤出选中的商品
  • 取得选中商品的数量

取得数量之后,还需要和子组件共享数据,所以就用自定义属性来传递数据

computed: {//总数量totalQuantity() {return this.list.filter(item => item.goods_state).reduce((total, item) => (total += item.goods_count), 0)}

子组件

<!-- 结算按钮 -->
<button type="button" class="btn btn-primary btn-settle">结算({{ totalNum}}</button>props: {totalNum:{type:Number,default:0}},

六、动态组件&插槽&自定义指令&axios

动态组件

什么是动态组件

动态组件指的是动态切换组件的显示与隐藏

如何实现动态组件渲染

vue 提供了一个内置的 组件,专门用来实现动态组件的渲染。示例代码如下:image-20221120194223304

使用 keep-alive 保持状态

默认情况下,切换动态组件时无法保持组件的状态。此时可以使用 vue 内置的 组件保持动态组 件的状态。示例代码如下:

image-20221120194246584

keep-alive 对应的生命周期函数

当组件被缓存时,会自动触发组件的 deactivated 生命周期函数。

当组件被激活时,会自动触发组件的 activated 生命周期函数。

image-20221120194329705

keep-alive 的 include 属性

include 属性用来指定:只有名称匹配的组件会被缓存。多个组件名之间使用英文的逗号分隔:

image-20221120194346399

插槽

插槽(Slot)是 vue 为组件的封装者提供的能力。允许开发者在封装组件时,把不确定的、希望由用户指定的 部分定义为插槽。

image-20221120194532307

可以把插槽认为是组件封装期间,为用户预留的内容的占位符。

体验插槽的基础用法

在封装组件时,可以通过 元素定义插槽,从而为用户预留内容占位符。示例代码如下:

image-20221120194635365

vue 官方规定:每一个 slot 插槽,都要有一个 name 名称–;
如果省略了 slot 的 name 属性,则有一个默认名称叫做 default

v-slot只能放在组件上和template上,放在其他上面会报错

默认情况下,在使用组件的时候,提供的内容都会被填充到名字为default 的插槽之中

image-20221120200200258

为具名插槽提供内容

在向具名插槽提供内容的时候,我们可以在一个 <template>(包裹作用) 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称。示例代码如下:

image-20221120200451005

具名插槽的简写形式

跟 v-on 和 v-bind 一样,v-slot 也有缩写,即把参数之前的所有内容 (v-slot:) 替换为字符 #。

例如 v-slot:header 可以被重写为 #header:

image-20221120200547696

作用域插槽

在封装组件的过程中,可以为预留的插槽绑定 props 数据,这种带有 props 数据的 叫做作用 域插槽

示例代码如下:

image-20221120201822789

使用作用域插槽

可以使用 v-slot: 的形式,接收作用域插槽对外提供的数据。示例代码如下:

image-20221120202402592

实例

image-20221120203040876

解构插槽 Prop

作用域插槽对外提供的数据对象,可以使用解构赋值简化数据的接收过程。

示例代码如下:

image-20221120202640156

实例

image-20221120203414937

自定义指令

什么是自定义指令

vue 官方提供了 v-text、v-for、v-model、v-if 等常用的指令。除此之外 vue 还允许开发者自定义指令。

自定义指令的分类

vue 中的自定义指令分为两类,分别是:

  • 私有自定义指令

  • 全局自定义指令

私有自定义指令

在每个 vue 组件中,可以在 directives 节点下声明私有自定义指令。示例代码如下:

image-20221120204949304

使用自定义指令

在使用自定义指令时,需要加上 v- 前缀。示例代码如下

image-20221120204724614

为自定义指令动态绑定参数值

为自定义指令动态绑定参数值

在 template 结构中使用自定义指令时,可以通过等号(=)的方式,为当前指令动态绑定参数值:

image-20221120205114156

通过 binding 获取指令的参数值

在声明自定义指令时,可以通过形参中的第二个参数,来接收指令的参数值:

image-20221120205143256

update 函数

bind 函数只调用 1 次:当指令第一次绑定到元素时调用,当 DOM 更新时 bind 函数不会被触发。 update 函 数会在每次 DOM 更新时被调用。示例代码如下:

image-20221120205222590

函数简写

如果 insert 和update 函数中的逻辑完全相同,则对象格式的自定义指令可以简写成函数格式:

image-20221120205243275

全局自定义指令

全局共享的自定义指令需要通过“Vue.directive()”进行声明

示例代码如下:

image-20221120205317529

把axios挂载到vue原型上

缺点是无法对api接口实现复用!

image-20221202144907847

在其他组件上直接通过this. h t t p . g e t 或者 t h i s . http.get或者this. http.get或者this.http.post来发请求就行了

七、路由

是什么?

一组对应关系,在 SPA 项目中,不同功能之间的切换,要依赖于前端路由来完成

前端路由的工作方式

image-20221120215504662

实现简易的前端路由

步骤1:通过 <component>标签,结合 comName 动态渲染组件。示例代码如下:

image-20221120215552901

步骤2:在 App.vue 组件中,为 链接添加对应的 hash 值:

image-20221120215736699

步骤3:在 created 生命周期函数中,监听浏览器地址栏中 hash 地址的变化,动态切换要展示的组件的名称:

image-20221120215812178

vue-router 的基本用法

vue-router 是 vue.js 官方给出的路由解决方案。它只能结合 vue 项目进行使用,能够轻松的管理 SPA 项目 中组件的切换。

vue-router 的官方文档地址:https://router.vuejs.org/zh/

vue-router安装

在 vue2 的项目中,安装 vue-router 的命令如下:

npm i vue - router@3.5.2 -S

创建路由模块

在 src 源代码目录下,新建 router/index.js 路由模块,并初始化如下的代码:

image-20221121093807714

导入并挂载路由模块

在 src/main.js 入口文件中,导入并挂载路由模块。示例代码如下:

image-20221121094045835

声明路由链接和占位符

image-20221121094102418

声明路由的匹配规则

image-20221121094227580

路由重定向

路由重定向指的是:用户在访问地址 A 的时候,强制用户跳转到地址 C ,从而展示特定的组件页面。 通过路由规则的 redirect 属性,指定一个新的路由地址,可以很方便地设置路由的重定向:

image-20221121094327986

嵌套路由

image-20221121094346744

声明子路由链接和子路由占位符

image-20221121094440465

通过 children 属性声明子路由规则

image-20221121094457351

动态路由匹配

动态路由指的是:把 Hash 地址中可变的部分定义为参数项,从而提高路由规则的复用性。 在 vue-router 中使用英文的冒号(:)来定义路由的参数项。示例代码如下:

image-20221121094619335

$route.params 参数对象

image-20221121094644113

使用 props 接收路由参数

image-20221121094656134

声明式导航 & 编程式导航

vue-router 中的编程式导航 API

image-20221121095018303

$router.push

image-20221121095038559

$router.replace

image-20221121095059840

$router.go

image-20221121095112629

$router.go 的简化用法

image-20221121095123592

导航守卫

image-20221121095140954

全局前置守卫

什么是回调函数?

回调函数是一个参数,将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,在执行传进去这个函数,这个过程就叫回调!

白话文:主函数的事先干完,回头在调用传进来的那个函数.

image-20221121095154479

守卫方法的 3 个形参

next 函数的 3 种调用方式

image-20221121095226022

控制后台主页的访问权限

image-20221121095241472

八、补充知识

URL种的#是什么意思?

#代表网页中的一个位置。

比如,http://www.example.com/index.html#print就代表网页index.html的print位置。浏览器读取这个URL后,会自动将print位置滚动至可视区域。

在VUE中,路由的实现方式有两种,其中一种就是通过#标识符进行页面内导航从而实现路由切换。

image-20221202172317471

HTTP请求不包括#

#是用来指导浏览器动作的,对服务器端完全无用。所以,HTTP请求中不包括#。
比如,访问下面的网址,http://www.example.com/index.html#print,浏览器实际发出的请求是这样的:

GET /index.html HTTP/1.1Host: www.example.com

#后的字符

在第一个#后面出现的任何字符,都会被浏览器解读为位置标识符。这意味着,这些字符都不会被发送到服务器端。
比如,下面URL的原意是指定一个颜色值:http://www.example.com/?color=#fff,但是,浏览器实际发出的请求是:

GET /?color= HTTP/1.1Host: www.example.com

改变#不触发网页重载

单单改变#后的部分,浏览器只会滚动到相应位置,不会重新加载网页。
比如,从http://www.example.com/index.html#location1改成http://www.example.com/index.html#location2,浏览器不会重新向服务器请求index.html。

说明同第一个,例如单页面应用SPA一样,路由的切换,不会重新加载页面,只是切换位置,或者切换组件;第二种应用就是在单个页面里面通过name和id切换当前显示的位置。

改变#会改变浏览器的访问历史

每一次改变#后的部分,都会在浏览器的访问历史中增加一个记录,使用"后退"按钮,就可以回到上一个位置。这对于ajax应用程序特别有用,可以用不同的#值,表示不同的访问状态,然后向用户给出可以访问某个状态的链接。值得注意的是,上述规则对IE 6和IE 7不成立,它们不会因为#的改变而增加历史记录。

说明:通过#的切换,是算在浏览器的访问历史中的,前进和后退都是生效的。

?说明

连接作用

通过?来带参数,连接域名和参数,经常会用到。

http://www.xxx.com/Show.asp?id=77&nameid=2905210001&page=1

清除缓存

http://www.xxxxx.com/index.html

http://www.xxxxx.com/index.html?test123123

两个url打开的页面一样,但是后面这个有问号,说明不调用缓存的内容,而认为是一个新地址,重新读取。

因为在做http请求的时候,如果浏览器检测到你的地址完全没变,会从缓存里读取先前请求过的数据,不再发送请求。有些时候是页面资源的加载,有些时候是API的get请求,都有可能。加上这个,会让浏览器认为这是一个新的地址,从而保证重新获取资源。

&说明

不同参数的间隔符

http://www.xxx.com/Show.asp?id=77&nameid=2905210001&page=1

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/47844.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

猿辅导、作业帮忙“圈钱”,跟谁学、有道、51Talk狂“烧钱”,在线教育钱途在哪?

文/螳螂财经&#xff08;ID:TanglangFin&#xff09; 作者/王文文 2020年&#xff0c;诸行业艰难&#xff0c;本应受疫情利好的在线教育行业&#xff0c;也同样冰火两重天。在线教育头部企业纷纷上演融资大戏&#xff0c;动辄以“亿美元”为单位&#xff0c;行业头部机构垄断…

有没有和作业帮一样的计算机,学霸君、学习宝和作业帮哪个好【对比】

国内各种开发商自然会推出新应用&#xff0c;制作了很多可以解决各种科目作业的应用。学霸君、学习宝和作业帮哪个好&#xff1f;大家还记得当年的假期作业是怎么完成的呢?自己搞定?抄同学的还是直接不做呢?现在看起来&#xff0c;抄作业已经 OUT 了&#xff0c;在搜索引擎上…

作业帮家长版的计算机怎么打开,作业帮家长版安装方法 作业帮家长版app特色...

作业帮怎么安装?作业帮家长版是一款帮助想辅导自己孩子功课但缺无从下手的家长们设计的app。下面小编就为玩家带来作业帮家长版安装方法&#xff0c;一起来看看吧。 作业帮家长版安装方法 作业帮家长版是一款帮助想辅导自己孩子功课但缺无从下手的家长们设计的app。通过这款ap…

ChatGPT终于被我问到胡说八道的程度了!

问&#xff1a;Python是强类型语言&#xff0c;还是弱类型语言 chatgpt&#xff1a;Python是强类型语言。Python很少会隐式地转换变量的类型&#xff0c;所以Python是强类型的语言 问&#xff1a;什么是强类型语言 chatgpt&#xff1a;强类型语言是指在编程语言中&#xff0…

【FPGA协议篇】UART通信及其verilog实现(代码采用传参实现模块通用性,适用于快速开发)

UART通信 UART通信简介verilog实现顶层模块接收模块发送模块 仿真波形实测结果 UART通信简介 ​ 即通用异步收发器(Universal Asynchronous Receiver/Transmitter)&#xff0c;是一种串行、异步、全双工的通信协议。特点是通信线路简单&#xff0c;适用于远距离通信&#xff0…

echarts图表使用v-show控制图表显示不全的问题

最近做echarts图表时&#xff0c;因为涉及到使用开关变量控制不同图表的显示隐藏&#xff0c;用 v-if 时会出现没有获取到dom结构而报错&#xff0c;所以改用 v-show&#xff0c;但是 v-show 本身是结构已经存在&#xff0c;当数据发生变化时&#xff0c;结构并未重新渲染&…

插件ucharts制作图表,tooltip报错不展示数据

项目场景&#xff1a; uni开发小程序 使用插件ucharts制作图表&#xff0c;tooltip报错不展示数据 后端返回两组数据&#xff0c;前端渲染两条折线图。横坐标一样。第1组数据只有0-5月的数据&#xff0c;另2组1-12月均有。点击6-12月段数据的折线图&#xff0c;报错如下&…

Microsoft Excel 教程:如何在 Excel 中显示或隐藏图表图例?

欢迎观看 Microsoft Excel 教程&#xff0c;小编带大家学习 Microsoft Excel 的使用技巧&#xff0c;了解如何在 Excel 中显示或隐藏图表图例。 可以显示或隐藏图表的图例。 显示图例可以向读者提供更多图表信息&#xff0c;而隐藏图例可以让图表拥有更简洁的外观。 单击要在…

Qt 绘制图表 - Qt Charts版

一、前言 自从 Qt 发布以来&#xff0c;给广大跨平台界面研发人员带来了无数的福利。但是Qt自己却一直没有提供自带的图表库&#xff0c;这就使得 QWT、QCustomPlot 等第三方图表库有了巨大的生存空间&#xff0c;为了降低开发成本&#xff0c;大家都涌向了这些第三方库。这种…

Highcharts 饼图数据是0的时候不显示

Highcharts 数据为0 时饼图的扇形不显示。 echarts 数据为0时会平分各项 Highcharts 平分的方法是当所有项的数据都为0时&#xff0c;把各项的值改为1这样就能平分&#xff0c;但是选中显示的数据还是0&#xff0c;解决的方法是加一个标志然后配置tooltip 参考Highcharts mak…

让v-charts中的图例显示在图表的下方以及解决title不生效问题

效果图&#xff1a; 1、让v-charts中的图例显示在图表的下方&#xff1a; 在 <ve-line :data"chartData" :legend"legend" ></ve-line>添加legend属性 并在data中加上this.legend { bottom: "0" };这样就完美解决了 2、解决title…

PPT 图表不显示对应类型的数据解决办法

晚上制表发现少了一行&#xff08;“10月”的一行&#xff09;&#xff0c;思来想去是这个原因&#xff1a; 记得在右键 “编辑数据” 时、在弹出的 excel 窗格中&#xff0c;首先拖动鼠标把紫色的框往下移&#xff0c;把 “10月” 的那一行也框进紫色的范围内。然后数据就正常…

moviepy音视频剪辑:视频剪辑基类VideoClip的属性及方法详解

☞ ░ 前往老猿Python博文目录 ░ 一、概述 在《moviepy音视频剪辑&#xff1a;moviepy中的剪辑基类Clip详解》和《moviepy音视频剪辑&#xff1a;moviepy中的剪辑基类Clip的属性和方法详解》介绍了剪辑相关类及类关系。可以看到视频剪辑类VideoClip是其中非常重要的一个剪辑…

一款非常实用的视频剪辑软件,它可以满足您进行视频制作的需要

剪映专业版是一款非常实用的视频剪辑软件&#xff0c;它可以满足您进行视频制作的需要&#xff0c;使用剪映mac版能够轻松对视频进行各种编辑&#xff0c;包括卡点、去水印&#xff0c;特效制作、倒放、变速等&#xff0c;还有专业风格滤镜&#xff0c;精选贴纸给你的视频加点乐…

Nature重磅!Google DeepMind推出AlphaDev,用AI打破十年算法封印!

来源 | 新智元 今天&#xff0c;「Alpha」家族再添一名新成员&#xff1a;AlphaDev。 整个计算生态系统的基础&#xff0c;或将被AI创造的新算法颠覆&#xff01; 谷歌大脑和DeepMind合体没多久&#xff0c;就带来这样一个惊世之作。 AlphaDev不仅可以将排序算法提速70&#x…

谷歌将发布全新搜索引擎,你期待吗?

Google一身自带AI属性的新搜索最首要的目标并非急于取代传统搜索引擎&#xff0c;或者说彻底打败ChatGPT&#xff0c;而是能够用全新的产品说服用户&#xff0c;变得与竞争对手同样“强大、能力出众以及顺应AI潮流”。 对于Google而言&#xff0c;搜索就是命脉。Google每年的收…

两分钟速览谷歌2023IO大会:AI军备竞争,全线出击

大家好&#xff0c;我是可夫小子&#xff0c;关注AIGC、读书和自媒体。解锁更多ChatGPT、AI绘画玩法。加&#xff1a;keeepdance&#xff0c;备注&#xff1a;chatgpt&#xff0c;拉你进群。 5月10日周三&#xff0c;谷歌举办了年度开发者大会Google I/O 2023&#xff0c;在会上…

终极合体!谷歌大脑DeepMind正式联姻,1+1>OpenAI?

【导读】陷入被动的谷歌做出了一个重大决定&#xff1a;谷歌大脑和DeepMind正式合并&#xff0c;强强联合能否打赢OpenAI&#xff1f; 今天&#xff0c;谷歌终于放大招了&#xff01; CEO劈柴正式宣布&#xff0c;Google DeepMind成立&#xff0c;谷歌大脑和DeepMind两个世界…

碾压GPT-4!谷歌DeepMind CEO自曝:下一代大模型将与AlphaGo合体

【新导读】谷歌DeepMind CEO Hassabis全新爆料&#xff1a;全新Gemini模型将结合进AlphaGo和大语言模型&#xff0c;成本预计是数千万美元&#xff0c;甚至数亿。 谷歌&#xff0c;是真的破釜沉舟了。 传说中合并了AlphaGo和类GPT-4大模型的Gemini&#xff0c;终于要来了吗&a…

重磅!谷歌官宣谷歌大脑与DeepMind合并

两大世界领先级团队强强联手&#xff0c;一场大战即将开幕。 作者 | 黄楠 编辑 | 陈彩娴 当地时间 4 月 20 日&#xff0c;谷歌母公司 Alphabet CEO Sundar Pichai &#xff08;皮猜&#xff09;在官网发文宣布&#xff0c;正式将谷歌大脑和 DeepMind 两大团队合并&#xff0c;…