p3-m3

news/2024/11/29 10:51:20/
  • 本阶段围绕当下国内最主流的前端核心框架 Vue.js 展开,深入框架内部,通过解读源码或者手写实现的方式,剖析 Vue.js 框架的内部实现原理,让你做到知其所以然。同时我们还会介绍 Vue.js 的进阶用法、周边生态以及性能优化,让你轻松应对更加复杂的项目业务需求。

模块三 Vuex 数据流管理及Vue.js 服务端渲染(SSR)

  • 本模块会介绍关于复杂项目中的状态管理方案 Vuex,以及自己来手写一个自己的 Vuex。Vue.js 中服务端渲染的使用尽在这里,本模块会先告诉你为什么要使用 SSR,紧接着带你使用 SSR 框架 Nuxt.js 快速开发一个服务端渲染的项目。

任务一:Vuex 状态管理

  1. 课程目标
  • Vue 组件间通信方式回顾
  • Vuex 核心概念和基本使用回顾
  • 购物车案例
  • 模拟实现 Vuex
  1. 组件内的状态管理流程
  • state 驱动应用的数据源
  • view 以声明方式将state映射到视图
  • actions 相应在view 上的用户输入导致的状态改变
  1. 组件间通信方式回顾-父组件给子组件传值
  • 父组件给子组件穿值
    • 子组件中通过props接收数据
    • 父组件中给子组件通过相应属性传值
  1. 组件间通信方式回顾-子组件给父组件传值

  2. 组件间通信方式回顾-不相关组件传值

// eventbus.js
import Vue from 'vue'
export default new Vue()import bus from './eventbus.js'
// bus.$emit() bus.$on()
  1. 组件间通信方式回顾-通过 ref 获取子组件
  • 其它常见方式
    • $root
    • $parent
    • $children
    • $refs
      • 在普通标签上使用ref,获取的是DOM
      • 在组件标签上使用ref,获取到的是组件实例
  1. 简易的状态管理方案
  • 问题
    • 多个视图依赖同一状态
    • 来自不同视图的行为需要变更同一状态
  1. Vuex 概念回顾
  • 什么是Vuex
    • Vuex 是专门为Vue.js设计的状态管理库
    • Vuex 采用集中式的方式存储需要共享的状态
    • Vuex 的作用是进行状态管理,解决复杂组件通信,数据共享
    • Vuex 集成到了 devtools 中,提供了time-travel时光旅行历史回滚功能
  • 什么情况下使用Vuex
    • 非必要的情况不要使用Vuex
    • 大型的单页应用程序
      • 多个视图依赖同一状态
      • 来自不同视图的行为需要变更同一状态
  1. Vuex 的核心概念

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TDQu1gVm-1627096149838)(./img/1626770990920.jpg)]

  • Store 每一个应用仅有一个Store,Store是一个容器,包含应用中的大部分状态,不能直接改变Store中的状态
  • State 就是单一状态树,所有的状态都保存在State,会让程序难以维护,可以通过模块解决该问题,这里的状态是响应式的
  • Getter 就像Vue中的计算属性,方便从一个属性派生出其它值,它内部可以对计算结果进行缓存,只有当依赖的状态发生改变才重新计算
  • Mutation 状态的变化必须提交Mutation完成
  • Action 和Mutation类似,不同的是,Action可以进行异步操作,内部改变状态的时候都需要提交 Mutation
  • Module 由于使用单一状态树,应该的状态会集中在一个对象上,当应用复杂时,Store对象就可以变得非常臃肿,为了解决这个问题,Vuex 允许我们将 Store 分为模块,每个模块拥有直接的State,Mutation,Action,Getter
  1. Vuex 的核心概念
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)export default new Vuex.Store({state: {},mutations: {},actions: {},modules: {}
})import store from './store'
new Vue({router,store,render: h => h(App)
}).$mount('#app')
  1. State

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BQy1pKew-1627096149839)(./img/1626772526939.jpg)]

  1. Getter
<!-- {{ $store.getters.reverseMsg }} -->
{{reverseMsg}}
export default new Vuex.Store({state: {msg: 'abc'},mutations: {},getters: {reverseMsg(state) {return state.msg.split('').reverse().join('')}},actions: {},modules: {}
})import { mapGetters } from 'vuex'
export default {computed: {...mapGetters(['reverseMsg'])}
}
  1. Mutation
<!-- <button @click="$store.commit('increate', 2)"></button> -->
<!-- <button @click="increate(2)"></button> --><!-- <button @click="$store.dispatch('increateAsync', 5)"></button> --><button @click="increateAsync(6)">Action</button>
export default new Vuex.Store({state: {count: 0,msg: 'abc'},mutations: {increate(state, payload) {state.count += payload}},getters: {reverseMsg(state) {return state.msg.split('').reverse().join('')}},actions: {increateAsync(context, payload) {setTimeout(() => {context.commit('increate', payload)}, 2000)}},modules: {}
})import { mapMutations } from 'vuex'
export default {methods: {...mapMutations(['increate']),...mapActions(['increateAsync'])}
}
  1. Action

  2. Module

```html
<!-- {{ $store.state.cart.cart }} -->
{{ cart }}
```
```js
// cart.js
const state = {}
const getters = {}export default {namespaced: true, // 开启命名空间state: {cart: 2},getters
}// index.js
import cart from './cart.js'export default new Vuex.Store({strict: true, // 开启严格模式state: {},mutations: {},getters: {},actions: {},modules: {cart}
})import { mapState } from 'vuex'
export default {computed: {...mapState('cart', ['cart'])}
}
```
  1. 严格模式
  • 如果修改state没有通过mutations,那么devtools就不能跟踪到,这是一种约定
  • 严格模式,直接修改state状态,会抛出错误,但数据会被修改。
  • 不要在生成环境开启严格模式,严格模式会深度检查状态树,来检查不合规的状态改变,会影响性能
  • strict: process.env.NODE_ENV !== ‘production’ 只在生产环境不开启严格模式。开发环境开启
  1. 购物车案例-演示

  2. 购物车案例 - 模板

  • 模版地址
    • https://github.com/goddlts/vuex-cart-demo-template.git
  1. 购物车案例 - 商品列表

  2. 购物车案例 - 添加购物车

  3. 购物车案例 - 我的购物车 - 列表

  4. 购物车案例 - 我的购物车 - 统计

  5. 购物车案例 - 我的购物车 - 删除

  6. 购物车案例 - 购物车组件 - 购物车列表

  7. 购物车案例 - 购物车组件 - 全选

  8. 购物车案例 - 购物车组件 - 数字文本框

  9. 购物车案例 - 购物车组件 - 统计

  10. 购物车案例-本地存储

  • Vuex 插件介绍
    • Vuex 的插件就是一个函数
    • 这个函数接收一个store的参数
    const myPlugin = store => {// 当 stroe 初始化后调用store.subscribe((mutation, state) => {//每次 mutation之后调用// mutatuin 的格式为 { type, payload }})
    }export default new Vuex.Store({state: {msg: 'abc'},mutations: {},getters: {reverseMsg(state) {return state.msg.split('').reverse().join('')}},actions: {},modules: {},plugins: [myPlugin]
    })
    
  1. 模拟 Vuex - 基本结构

  2. 模拟 Vuex - install

  3. 模拟 Vuex - Store 类

let _Vue = null
class Store {constructor(options) {const {state = {},getters = {},mutations = {},actions = {}} = optionsthis.state = _Vue.observable(state)this.getters = Object.create(null)Object.keys(getters).forEach(key => {Object.defineProperty(this, key, {get() => getters[key](state)})})this._nutations = mutationsthis._actions = actions}commit(type, payload) {this._nutations[type](this.state, payload)}dispatch(type, payload) {this._actions[type](this, payload)}
}
function install (Vue) {_Vue = VueVue.mixin({beforeCreate() {if (this.$options.store) {_Vue.prototype.$store = this.$options.store}}})
}
export default {Store,install
}

任务二:服务端渲染基础

  1. 概述
  • SPA 单页面应用
    • 优点 用户体验好 开发效率高 渲染性能好 可维护性好
    • 缺点 首屏渲染时间长 不利于SEO
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AkeNHqgJ-1627096149840)(./img/1626854774759.jpg)]
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nSC1lmGn-1627096149842)(./img/1626854851027.jpg)]
  • 同构应用
    • 通过服务端渲染首屏直出,解决SPA应用首屏渲染慢以及不利于SEO问题
    • 通过客户端渲染接管页面内容交互得到更好的用户体验
    • 这种方式通常称之为现代化的服务端渲染,也叫同构渲染
    • 这种方式构建的应用称之为服务端渲染应用或者是同构应用
  1. 什么是渲染
  • 渲染:把 数据 + 模版 拼接到一起
  1. 传统的服务端渲染
  • nodemon 文件名 对比node,修改js文件后自动重启
  • 网页越来越复杂的情况下,存在很多不足
    • 前后端代码完全耦合在一起,不利于开发和维护
    • 前端没有足够发挥空间
    • 服务端压力大
    • 用户体验一般
      • 只有经过刷新,才能看到一个新的页面
  1. 客户端渲染

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sR3NaEyK-1627096149843)(./img/1626856803366.jpg)]

  • 前端 更为独立,不再受限制于 后端
  • 不足之处
    • 首屏渲染慢
    • 不利于SEO
  1. 为什么客户端渲染首屏渲染慢
  • 服务端渲染页面直出
  • 客户端渲染先加载模版页,再加载js,最后通过ajax加载数据。3批串行的网络请求,如果客户端网络不好,更加显慢。
  1. 为什么客户端渲染不利于 SEO
  • SEO 搜索引擎排名,搜索引擎会去爬取网站进行分析,收录
  • 搜索引擎不是浏览器,不会去执行js,拿到的只是html静态页面(当成字符串解析)
  • 单页面程序seo基本为0
  1. 现代化的服务端渲染 同构渲染
  • 同构渲染 = 后端渲染 + 前端渲染
  • 基于 React、 Vue 等框架,客户端渲染和服务器渲染的结合
    • 在服务器端执行一次,用于实现服务器端渲染(首屏直出)
    • 在客户端再执行一次,用于接管页面交互
  • 核心解决SEO和首屏渲染慢的问题
  • 拥有传统服务端渲染的优点,也有客户端渲染的优点
  • 如何实现同构渲染
    • 使用 Vue、React等框架的官方解决方案
      • 优点:有助于理解原理
      • 缺点:需要搭建环境,比较麻烦
    • 使用第三方解决方案
      • React 生态的 Next.js
      • Vue 生态的 Nuxt.js
  1. 通过 Nuxt 体验同构渲染
  • yarn add nuxt
  • “scripts”: { “dev”: “nuxt” }
  • asyncData
  • 首屏是通过服务端渲染出来的
  1. 同构渲染的 SPA 应用

  2. 同构渲染的问题

  • 开发条件受限
    • 浏览器特定的代码只能在某些生命周期钩子函数中使用
    • 一些外部扩展库可能需要特殊处理才能在服务端渲染应用中运行
    • 不能在服务端渲染期间操作DOM
    • 某些代码操作需要区分运行环境
  • 涉及构建和部署的要求更多
    •           构建                 部署
      
    • 客户端渲染 仅构建客户端应用即可 可以部署在任意web服务器中
    • 同构渲染 需要构建两个端 只能部署在 Node.js Server
  • 更多的服务端负载
    • 在 Node 中渲染完整的应用程序,相比仅仅提供静态文件的服务器 需要大量占用CPU资源
    • 如果应用在高流量环境下使用,需要准备相应的服务器负载
    • 需要更多的服务端渲染优化工作处理
  • 服务端渲染使用建议
    • 首屏渲染速度是否真的重要?
    • 是否真的需要SEO?

任务三:NuxtJS基础

  1. NuxtJS介绍
  • 一个基于Vue.js生态的第三方开源服务端渲染应用框架
  • 它可以帮我们轻松的使用Vue.js技术栈构建同构应用
  • https://github.com/nuxt/nuxt.js
  1. 初始化NuxtJS项目
  • Nuxt.js的使用方式
    • 初始项目
    • 已有的Node.js服务端项目
      • 直接把Nuxt当作一个中间件集成到 Node Web Server 中
    • 现有的Vue.js项目
      • 非常熟悉 nuxt.js
      • 至少百分之10的代码改动
  • 官方文档 [https://zh.nuxtjs.org/docs/2.x/get-started/installation]
  • 根据官方文档
    • 方式一:使用 create-nuxt-app
    • 方式二:手动创建
  1. 案例代码分支说明
  • git branch 分支名称 创建分支
  • git branch 查看所有分支
  • git checkout 分支名称 切换分支
  1. 路由-基本路由

  2. 路由-路由导航

  • a 标签
    • 它会刷新整个页面,不用使用
  • nuxt-link 组件
  • 编程式导航 通过js跳转
  • 参考 router-link 就行了,基本一致 [https://router.vuejs.org]
  1. 路由-动态路由
  • _id.vue 动态路由,对应 vue-router /:id
  1. 路由-嵌套路由
  • router-link: template占位,children 配置嵌套路由地址
  • nuxt: users.vue 文件中占位,同名users/index.vue 文件夹出现的文件就是子路由文件
  1. 路由-自定义路由配置
  • nuxt.config.js 中配置路由规则
  1. 视图-模板

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-57euJ1gT-1627096149844)(./img/1626875411461.jpg)]

  • 最外层的 html 模版是看不到的,可以在src文件夹(默认项目根目录下)下创建 app.html
 <!-- 默认模版 -->
<!DOCTYPE html>
<html {{ HTML_ATTRS }}><head {{ HEAD_ATTRS }}>{{ HEAD }}</head><body {{ BODY_ATTRS }}><!-- 渲染的内容最终会注入到这里 -->{{ APP }}</body>
</html>
  1. 视图-布局
  • layouts/default.vue 第二层所有组件的默认父路由,默认布局组件
  • 页面出口,类似于子路由出口
  1. 异步数据-asyncData
  • 基本用法
    • 它会将asyncData返回的数据融合组件data方法返回数据一并给组件
    • 调用时机:服务端渲染期间和客户端路由更新之前
  • 注意事项
    • 只能在页面组件中使用
    • 没有this,因为它是在组件初始化之前被调用的
  • asyncdata 当想要动态页面内容有利于SEO或者是提升首屏渲染速度的时候,就在asyncData 中发请求拿数据
  • data 如果是非异步数据或者普通数据,则正常初始化到 data中即可
  1. 异步数据-上下文对象
  • asyncDate(context)

任务四:NuxtJS综合案例

  1. 案例介绍
  • 案例名称:realworld
  • 一个开源的学习项目,目的就是帮助开发者快速学习新技能
  • GitHub 仓库: https://github.com/gothinkster/realworld
  • 在线示例: https://demo.realworld.io/#/
  • 模版地址 https://github.com/gothinkster/realworld-starter-kit/blob/master/FRONTEND_INSTRUCTIONS.md
  • API 地址 https://github.com/gothinkster/realworld/tree/master/api
  • 学习收获
    • 掌握使用Nuxt.js开发同构渲染应用
    • 增强Vue.js实践能力
    • 掌握同构渲染应用中常见的功能处理
      • 用户状态管理
      • 页面访问权限处理
      • SEO 优化
    • 掌握同构渲染应用的发布于部署
  1. 项目初始化-创建项目
  • mkdir realworld-nuxtjs
  • npm init -y
  • npm i nuxt
  • 配置启动脚本 “scripts”: { “dev”: “nuxt” }
  • 创建pages目录,配置初始页面
  1. 项目初始化-导入样式资源
  • 导入样式资源
    • 模版地址 中的头部三个css文件
    • 创建 app.html 导入nuxt模版,引用这三个css文件
    • https://www.jsdelivr.com 这个可以找到资源在国内的cdn地址 如:ionicons
    • 第二个css文件,googleapis已经在国内有资源,可以不处理
    • 第三个css,直接下载下来,放在static 文件夹下。第一个css不这样做,是因为引用了一些字体,处理起来比较麻烦
  • 配置布局组件
  • 配置页面组件
  1. 项目初始化-布局组件
  • pages/layout/index.vue
    • 把模版的顶部和底部复制过来,中间放子路由
  • nuxt.config.js
    module.exports = {router: {// 自定义路由表规则extendRoutes(routes, resolve) {// 清除Nuxt.js基于pages目录默认生成的路由表规则routes.splice(0)routes.push(...[path: '/',component: resolve(__dirname, 'pages/layout/'),children: [{path: '', // 默认子路由name: 'home',component: resolve(__dirname, 'pages/home'),}]])}}
    }
    
  1. 项目初始化-导入登录注册页面
  • login/index.vue
  • 配置 Login/Register url
export default {computed: {// 处理 Login/Register 页面的不同isLogin() {return this.$route.name === 'login'}}
}
  1. 项目初始化-导入剩余页面

  2. 项目初始化-处理顶部导航链接

  3. 项目初始化-处理导航链接高亮

  • 配置在router中 linkActiveClass: ‘active’
  • 在nuxt-link 标签上写 exact 表示精确匹配(url)
  1. 项目初始化-封装请求模块
  • npm i axios
  1. 登录注册-实现基本登录功能
  • @submit.prevent = “” 表单阻止默认事件(只触发注册的事件)
  1. 登录注册-封装请求方法

  2. 登录注册-表单验证

  • 给input 标签加上 required 属性,原生的表单验证
  • 邮箱 type改成 email就会验证
  1. 登录注册-错误处理

  2. 登录注册-用户注册

  • minlength=8
  1. 登录注册-解析存储登录状态实现流程

  2. 登录注册-将登录状态存储到容器中

  3. 登录注册-登录状态持久化

  • npm i js-cookie
// 仅在客户端加载 js-cookie 包
const Cookie = process.client ? require('js-cookie') : undefined
// store/index.js
const cookieparser = process.server ? require('cookieparser') : undefined
// 在服务端渲染期间运行都是同一个示例
// 为了防止数据冲突,务必要把state 定义成一个函数,返回数据对象
export const state = () => {return {// 当前登陆用户的登陆状态user: null}
}
export const mutations = {setUser(state, data) {state.user = data}
}
export const actions = {// nuxtServerInit 是一个特殊的action 方法// 这个 action 会在服务端渲染期间自动调用// 作用:初始化容器数据,传递数据给客户端使用nuxtServerInit ({ commit }, { req }) {let user = nullif (req.headers.cookie) {const parsed = cookieparser.parse(req.headers.cookie)try {user = JSON.parse(parsed.user)} catch (error) {}}commit('setUser', user)}
}
  1. 登录注册-处理导航栏链接展示状态

  2. 登录注册-处理页面访问权限

  • middleware/auth.js
export default function ({store, redirect}) {if (!store.state.user) {return redirect('/login')}
}
// 在路由匹配组件渲染之前会先执行中间件处理
// middleware: 'auth'
  1. 首页-业务介绍

  2. 首页-展示公共文章列表

  3. 首页-列表分页-分页参数的使用

  4. 首页-列表分页-页码处理

  • watchQuery: [‘page’]
  1. 首页-列表分页-页码处理

  2. 首页-展示文章标签列表

  3. 首页-优化并行异步任务

  • Promise.all
  1. 首页-处理标签列表链接和数据

  2. 首页-处理导航栏-业务介绍

  3. 首页-处理导航栏-展示状态处理

  4. 首页-处理导航栏-标签高亮及链接

  5. 首页-处理导航栏-展示用户关注的文章列表

  6. 首页-统一设置用户Token

  • plugins/request.js
  • nuxt.config.js plugins: [’~/plugins/request.js’] 注册插件
import axios from "axios";
// 按需导出,因为默认导出被 plugin 占据了
export const request = axios.create({baseURL: 'https://conduit.productionready.io/'
})
export default ({ store }) => {// 添加请求拦截器request.interceptors.request.use(function (config) {// 在发送请求之前做些什么let { user } = store.stateif (user && user.token) config.headers.Authorization = `Token ${user.token}`// 返回config 配置对象return config;}, function (error) {// 对请求错误做些什么,这个是请求发送之前的异常return Promise.reject(error);});
}
  1. 首页-文章发布时间格式化处理
  • dayjs
  • npm install dayjs --save
  • vue.filter 注册插件
  1. 首页-文章点赞

  2. 文章详情-业务介绍

  3. 文章详情-展示基本信息

  4. 文章详情-把Markdown转为HTML

  • markdown-it
  1. 文章详情-展示文章作者相关信息

  2. 文章详情-设置页面meta优化SEO

  3. 文章评论-通过客户端渲染展示评论列表

  4. 发布部署-打包

  5. 发布部署-最简单的部署方式

  • 最简单的部署方式
    • 配置Host + Port

      • nuxt.config.js => server: {host: ‘0.0.0.0’, port: 3000}
    • 压缩发布包

      • .nuxt static nuxt.config.js package.json package-lock.json => realword-nuxtjs.zip
    • 把发布包传到服务端

      • ssh root@10.10.10.0 登陆服务器
      • mkdir realworld-nuxtjs
      • cd realworld-nuxtjs/
      • pwd
      • exit
      • scp ./realword-nuxtjs.zip root@10.10.10.0:/root/realworld-nuxtjs
      • ssh root@10.10.10.0 登陆服务器
      • cd realworld-nuxtjs/
      • unzip realword-nuxtjs.zip
      • ls -a 看隐藏文件
      • npm i
      • npm run start
    • 解压

    • 安装依赖

    • 启动服务

  1. 发布部署-使用PM2启动Node服务
- npm install --global pm2
- pm2 start 脚本路径
- pm2 start npm -- start
- pm2 stop id
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FXX1ZdK9-1627096149845)(./img/1627037127513.jpg)]
  1. 发布部署-自动化部署介绍
- 现代化的部署方式(CI/CD)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HmcXSRDi-1627096149846)(./img/1627037335411.jpg)]
  1. 发布部署-准备自动部署内容
- CI/CD 服务+ jenkins+ Gitlab CI+ GitHub Actions+ Travis CI+ Circle CI
- 环境准备+ Linux 服务器+ 把代码提交到GitHub 远程仓库
- 配置 GitHub Access Token+ 生成:https://github.com/settings/tokens+ 配置到项目的Secrets 中:https://github.com/lipengzhou/realworld-nuxtjs/settings/secrets+ 右上角用户》Settings > Developer settings > Personal access tokens > Generate new token > repo 勾选 > 最下方 Generate token- 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- 复制令牌- 打开远程仓库 》 Settings 》Secrets 》 new Secrets 》Name:TOKEN (脚本中要保持一致) Value 放令牌+ 配置GitHub Actios 执行脚本- 在项目根目录创建 .github/workflows 目录- 下载 main.yml到workflows目录中+ https://gist.github.com/lipengzhou/b92f80142afa37aea397da47366bd872- 修改配置- 配置PM2 配置文件+ pm2.config.json { "apps": [ { "name": "RealWorld", "script": "npm", "args": "start" } ] }+ 需要把 pm2.config.json加入到 main.yml 打包构建的文件中去+ 配置服务器信息,打开远程仓库:Settings 》Secrets 》 new Secrets 》- Name:USERNAME Value:root- Name:PORT Value:22- Name:HOST Value: 100.100.99.98- Name: PASSWORD Value:- 提交更新- 查看自动部署状态- 访问网站- 提交更新
  1. 发布部署-自动部署完成
  • git tag v0.1.0 在main.yml中以v开头才会集成
  • git tag
  • git push origin v0.1.0
  • 查看远程仓库 Actions 构建这一栏
  • Release 可以查看到构建完成的发布包
  • git add . gti commit ‘’ git push ,只是推送了本地的历史记录
  • git tag v0.1.1 只有生成一个新的标签并且推送才回构建

http://www.ppmy.cn/news/112824.html

相关文章

设计模式之创建型模式

1、单例模式&#xff08;Singleton Pattern&#xff09; Ensure a class only has one instance,and provide a global point of access to it. 保证一个类仅有一个实例&#xff0c;并提供一个访问它的全局访问点。 何时使用 当系统需要某个类只有一个实例的时候 优点 单例…

05#31

可是我都已经不爱了 夜深了 还在想你 我不能能够 就算你再次转身 我们已然擦身而过 可是 我的心里还是装着那个他 即使有人进有人出 我还是固执的保留着那个位置 你的专属 明天我就离开 离开这个有你记忆的地方 也许还会回来 但是我的心只为自己而忙碌 我希望我…

01-30

(1.1) MATLAB 与 Excel 的交互 (1.1.1) 在 Excel 中加载宏&#xff1a; (1) 在Excel中点击 文件-选项-加载项-转到-浏览-选中MATLAB&#xff08;安装目录&#xff09;/ toolbox / exlink。然后在Excel的 选项-自定义功能区-所有命令 中添加MATLAB图标的命令。 (1.1.2) 从 Exc…

EC35

35. 考虑virtual函数以外的其他选择 令客户通过public non-virtual成员函数间接调用private virtual函数。继承类可以重新定义继承而来的private virtual函数该条款主要介绍替代virtual函数的方法&#xff0c;主要有&#xff1a; 1&#xff09;用private virtual函数替代&…

React 使用recharts实现散点地图

一、前端框架reactant design UI二、首先安装recharts npm install recharts 或者 yarn add recharts 三、引入插件及chinaJSON.js&#xff08;里面有经纬度信息&#xff09;下载百度云网盘地址:chinaJSON.js 提取码&#xff1a;ep30由于项目需要我是全部存数据库的&#xff0c…

(BDCI-CCF)出租车发票识别

参考文章&#xff1a; ​​​​​​百度AI攻略&#xff1a;出租车票识别_才能我浪费的博客-CSDN博客 附完整python源码&#xff09;基于tensorflow、opencv的入门案例_发票识别一&#xff1a;关键区域定位_小白来搬家-CSDN博客_python发票识别 注&#xff1a;感谢一起完成项目…

2021-05-31

Linux DRM那些事-libdrm调试准备 本文主要介绍libdrm的代码下载、编译和调试前的准备工作。 一、代码下载 libdrm下载网址&#xff1a;https://dri.freedesktop.org/libdrm/libdrm-2.4.89.tar.bz2 解压命令&#xff1a;tar -jxvf libdrm-2.4.89.tar.bz2 在代码解压后&…

03

术语表 术语 定义 敏感数据 敏感数据的具体范围取决于产品具体的应用场景&#xff0c;产品应根据风险进行分析和判断。典型的敏感数据包括口令、银行帐号、大批量个人数据、用户通信内容和密钥等。一类如果丢失或者泄漏&#xff0c;会对数据的所有者造成负面影响的数据。 本…