Vue详解知识概括

  • Vue CLI
  • Vue-router
  • Promise
  • Vuex
  • axios
  • Vue开发总结

Vue CLI

什么是Vue CLI:

  • 如果你只是简单写几个Vue的Demo程序, 那么你不需要Vue CLI.
  • 如果你在开发大型项目, 那么你需要, 并且必然需要使用Vue CLI
    ①使用Vue.js开发大型应用时,我们需要考虑代码目录结构、项目结构和部署、热加载、代码单元测试等事情。
    ②如果每个项目都要手动完成这些工作,那无疑效率比较低效,所以通常我们会使用一些脚手架工具来帮助完成这些事情。
  • CLI是什么意思?
    ①CLI是Command-Line Interface, 翻译为命令行界面, 但是俗称脚手架.
    ②Vue CLI是一个官方发布 vue.js 项目脚手架
    ③使用 vue-cli 可以快速搭建Vue开发环境以及对应的webpack配置.

Vue CLI使用前提:

  • 安装NodeJS
    ①默认情况下自动安装Node和NPM
    ②NPM的全称是Node Package Manager
    ③是一个NodeJS包管理和分发工具,已经成为了非官方的发布Node模块(包)的标准。
  • Vue.js官方脚手架工具就使用了webpack模板
    ①对所有的资源会压缩等优化操作
    ②它在开发过程中提供了一套完整的功能,能够使得我们开发过程中变得高效。

Vue CLI的使用:

  • 安装Vue脚手架:npm install -g @vue/cli
    ①查看vue版本:vue –version
    ②注意:上面安装的是Vue CLI3的版本,如果需要想按照Vue CLI2的方式初始化项目时不可以的。
    ③拉取2.X模板(旧版本):npm install -g @vue/cli-init
  • Vue CLI2初始化项目:vue init webpack my-project
  • Vue CLI3初始化项目:vue create my-project

Vue CLI2详解:

  • 初始化命令使用:
  • 目录简介:
    ①build.js:构建入口
    ②index.js:变量,配置信息
    ③webpack.base.conf.js:公共webpack配置信息
    ④webpack.dev.conf.js:部署配置信息
    ⑤webpack.prod.conf.js:构建配置信息

(运行时+编译器)Runtime-Compiler和(只含有运行时版本)Runtime-only的区别:

  • 如果你需要在客户端编译模板(例如, 向template 选项传入一个字符串,或者需要将模 板中的非DOM的HTML挂载到一个元素),你需要带有编译器的版本,因而需要完整构建版本。
  • 在使用vue-loader或vueify 时,* . vue文件中的模板会在构建时(build time)预编译(pre-compile)为JavaScript.最终生成的bundle中你不再需要编译器(compiler),因此可以直接使用只含有运行时的构建版本(runtime- only)。
//这种情况需要编译器(compiler)new Vue({template: '<div>({ hi }}</div>')//这种情况不需要new Vue({render (h) {return h('div', this.h1)}})
  • 由于只含有运行时构建版本(runtime-only)比完整构建版本(ull-build)轻量大约30%,你应该尽可能使用只含有运行时的构建版本。如果你还是希望使用完整构建版本,则需要在打包器中配置别名。
  • 简单总结:
    ①如果在之后的开发中,你依然使用template,就需要选择Runtime-Compiler。
    ②如果你之后的开发中,使用的是.vue文件夹开发,那么可以选择Runtime-only。

render和template区别:

//Runtime-Compilernew Vue({el :'#app',components: { App },template: '<App/>'})//Runtime-onlynew Vue({el : '#app',render: h => h(App)})
  • 为什么存在这样的差异呢?
    ①我们需要先理解Vue应用程序是如何运行起来的。
    ②Vue中的模板如何最终渲染成真实DOM。
    ③我们来看下面的一幅图。

npm run build与npm run dev详解:

  • npm run build:
  • npm run dev:

webpack.base.conf.js起别名:

resolve: {extensions: ['.js', '.vue', '.json'],alias: {'@':resolve('src'),'pages': resolve('src/pages'),'common': resolve('src/common'),'components':resolve('src/components'),'network': resolve('src/network')}},

Vue CLI3详解:

  • vue-cli 3 与 2 版本有很大区别:
    ①vue-cli 3 是基于 webpack 4 打造,vue-cli 2 还是 webapck 3
    ②vue-cli 3 的设计原则是“0配置”,移除的配置文件根目录下的,build和config等目录
    ③vue-cli 3 提供了 vue ui 命令,提供了可视化配置,更加人性化
    ④移除了static文件夹,新增了public文件夹,并且index.html移动到public中
  • 初始化使用:
  • 目录结构详解:
  • 配置去哪里了:
    ①UI方面的配置:启动配置服务器:vue ui

    ②一大堆配置文件去哪里了?

Vue-router

什么是路由?

  • 路由(routing)就是通过互联的网络把信息从源地址传输到目的地址的活动
  • 路由器提供了两种机制: 路由和转送.
    ①路由是决定数据包从来源到目的地的路径.
    ②转送将输入端的数据转移到合适的输出端.
  • 路由中有一个非常重要的概念叫路由表。路由表本质上就是一个映射表, 决定了数据包的指向。

后端路由阶段:

  • 早期的网站开发整个HTML页面是由服务器来渲染的:
    ①服务器直接生产渲染好对应的HTML页面, 返回给客户端进行展示.
  • 但是一个网站, 这么多页面服务器如何处理呢” />执行:location.hash = ‘/foo’返回:”/foo”执行:location. href返回:”http: //192.168.1.101: 8000/examples/urlChange/#/foo”

    HTML5的history模式:

    • history接口是HTML5新增的, 它有五种模式改变URL而不刷新页面。
    • history接口底层的数据结构是栈。
    • 函数:
      ①history.pushState():插入锚点,改变url,支持前进后退。
      ②history.replaceState():插入锚点,改变url,不支持前进后退。
      ③history.go()
    • 补充说明:
      ①上面只演示了三个方法
      ②因为 history.back() 等价于 history.go(-1)
      ③history.forward() 则等价于 history.go(1)
      ④这三个接口等同于浏览器界面的前进后退
    • 与URL的hash相比,没有了#符号

    vue-router认识:

    • 目前前端流行的三大框架, 都有自己的路由实现:
      ①Angular的ngRouter
      ②React的ReactRouter
      ③Vue的vue-router
    • 当然, 我们的重点是vue-router,vue-router是Vue.js官方的路由插件,它和vue.js是深度集成的,适合用于构建单页面应用。
    • vue-router是基于路由和组件的:
      ①路由用于设定访问路径, 将路径和组件映射起来.
      ②在vue-router的单页面应用中, 页面的路径的改变就是组件的切换.

    安装和使用vue-router:

    • 安装vue-router:npm install vue-router –save
    • 在模块化工程中使用它(因为是一个插件, 所以可以通过Vue.use()来安装路由功能)
      ①导入路由对象,并且调用 Vue.use(VueRouter)
      ②创建路由实例,并且传入路由映射配置
      ③在Vue实例中挂载创建的路由实例
    • 使用vue-router的步骤:
      ①创建路由组件
      ②配置路由映射: 组件和路径映射关系
      ③使用路由: 通过和
    • 路由标签详解:
      ①: 该标签是一个vue-router中已经内置的组件, 它会被渲染成一个标签.
      ②: 该标签会根据当前的路径, 动态渲染出不同的组件。
      ③网页的其他内容, 比如顶部的标题/导航,或者底部的一些版权信息等会和处于同一个等级。
      ④在路由切换时, 切换的是挂载的组件,其他内容不会发生改变。
    ----创建router文件夹,然后创建index.js文件,创建router实例,配置组件和路径的映射关系:----import Vue from 'vue'import VueRouter from 'vue-router'// 1.注入插件Vue.use(VueRouter)// 2.定义路由const routes = [{path: '/home',component: Home}{path: '/about', component: About}]// 3.创建router实例const router = new VueRouter({routes})// 4.导出router实例export default router----main.js文件中挂载到Vue实例中:----import Vuefrom 'vue'import App from './App'import router from './router'new Vue({el: '#app',router,render: h => h(App)})----创建About和Home路由组件--------使用路由:----<template><div id="app"><h1>我是网站的标题<router-link to="/home">首页</router-link><router-link to="/about">关于</router-link><router-view></router-view><h2>我是APP中一些底部版权信息</h2></div></template>----最终效果如下:----一、当路径是根路径时,router-view没有渲染试图二、点击首页,路径切换,router-view渲染home组件伞、点击关于,路径切换,router-view渲染about组件

    vue-router细节处理:

    • 路由的默认路径:
      ①默认情况下, 进入网站的首页, 我们希望渲染首页的内容,但是我们的实现中, 默认没有显示首页组件, 必须让用户点击才可以。
      ②如何可以让路径默认跳到到首页, 并且渲染首页组件呢,非常简单, 我们只需要配置多配置一个映射就可以了。
      ③我们在routes中又配置了一个映射,path配置的是根路径: /,redirect是重定向, 也就是我们将根路径重定向到/home的路径下, 这样就可以得到我们想要的结果了。
    const routes =[{path: '/'redirect: '/home'}]
    • HTML5的History模式:
      ①我们前面说过改变路径的方式有两种:URL的hash,HTML5的history。默认情况下, 路径的改变使用的URL的hash,如果希望使用HTML5的history模式, 非常简单, 进行如下配置即可:
    const router =new VueRouter({routes,mode: 'history'})
    • router-link补充:
      ①在前面的中, 我们只是使用了一个属性: to, 用于指定跳转的路径。
      ②还有一些其他属性:
      tag: tag可以指定之后渲染成什么组件, 比如上面的代码会被渲染成一个
    • 元素, 而不是。
      replace: replace不会留下history记录, 所以指定replace的情况下, 后退键返回不能返回到上一个页面中。
      active-class: 当对应的路由匹配成功时, 会自动给当前元素设置一个router-link-active的class, 设置active-class可以修改默认的名称。在进行高亮显示的导航菜单或者底部tabbar时, 会使用到该类。但是通常不会修改类的属性, 会直接使用默认的router-link-active即可。
    • 修改linkActiveClass:
      ①该class具体的名称也可以通过router实例的属性进行修改。
    const router = new VueRouter({routes,mode: 'history',linkActiveClass:'active'})
    • 路由代码跳转:
      ①有时候, 页面的跳转可能需要执行对应的JavaScript代码, 这个时候, 就可以使用第二种跳转方式了。
    <template><div id="app"><h1>我是网站的标题<button @click="li nkToHomel">首页</button><button @click="l inkToAbout">关于</button><router-view></router-view><h2>我是APP中一些底部版权信息</h2></div><template><script>export default{name:'App',methods: {linkToHome() {this.$router.push('/home')}linkToAbout() {this.$router.push('/about')}}</script>
    • 动态路由:
      ①在某些情况下,一个页面的path路径可能是不确定的,比如我们进入用户界面时,希望是如下的路径:/user/aaaa或/user/bbbb。除了有前面的/user之外,后面还跟上了用户的ID。这种path和Component的匹配关系,我们称之为动态路由(也是路由传递数据的一种方式)。
    -----路由配置页面---{path: '/user/:id',component: User}----使用页面----<div> <h2>{{$route.params.id}}</h2> </div>----组件页面----<router-link to="/user/123">用户</router-link>

    路由懒加载:

    • 官方给出了解释:当打包构建应用时,Javascript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了
    • 官方在说什么呢?首先, 我们知道路由中通常会定义很多不同的页面.这个页面最后被打包在哪里呢? 一般情况下, 是放在一个js文件中.但是, 页面这么多放在一个js文件中, 必然会造成这个页面非常的大.如果我们一次性从服务器请求下来这个页面, 可能需要花费一定的时间, 甚至用户的电脑上还出现了短暂空白的情况.
    • 如何避免这种情况呢? 使用路由懒加载就可以了.路由懒加载做了什么?路由懒加载的主要作用就是将路由对应的组件打包成一个个的js代码块.只有在这个路由被访问到的时候, 才加载对应的组件。
    • 懒加载的方式:
    方式一: 结合Vue的异步组件和Webpack的代码分析.const Home = resolve => { require.ensure(['../components/Home.vue'], () => { resolve(require('../components/Home.vue')) })};方式二: AMD写法const About = resolve => require(['../components/About.vue'], resolve);方式三: 在ES6中, 我们可以有更加简单的写法来组织Vue异步组件和Webpack的代码分割.const Home = () => import('../components/Home.vue')
    //使用懒加载const routes =[{path: '/home', component: () => import(' ../components/Home')},path: '/about', component: () => import('../components/About')},];

    路由嵌套:

    • 嵌套路由是一个很常见的功能。比如在home页面中, 我们希望通过/home/news和/home/message访问一些内容。一个路径映射一个组件, 访问这两个路径也会分别渲染两个组件。路径和组件的关系如下:
    /home --------> Home/home/news --------> News/home/message --------> Message/about --------> About
    • 实现嵌套路由有两个步骤:
      ①创建对应的子组件, 并且在路由映射中配置对应的子路由。
      ②在组件内部使用标签。
    -----一、定义两个组件----------二、配置嵌套路由映射-----import Vue from 'vue'import VueRouter from 'vue-router'const Home = () => import('../components /Home')const Message = () => import('../components/message')const News = () => import('../components/news')const About = ( ) => import('../components/About')// 1.注入插件Vue.use (VueRouter)// 2.定义路由const routes = [{path: '/home',component: Home,children: [{path: 'message'component: Message},{path: 'news',component: News}]}]-----三、在父组件模板中使用-----<template><div id="home"><h2>我是首页标题</h2><router-link to="/home/message">消息</router-link><router-link to="/home/news">新闻<router-view></router-view></div></template>
    • 嵌套路由也可以配置默认的路径, 配置方式如下:
    {path: '',redirect:'message'}

    路由传递参数:

    • 传递参数主要有两种类型: params和query
    • params的类型:
      ①配置路由格式: /router/:id
      ②传递的方式: 在path后面跟上对应的值
      ③传递后形成的路径: /router/123, /router/abc
    • query的类型:
      ①配置路由格式: /router, 也就是普通配置
      ②传递的方式: 对象中使用query的key作为传递方式
      ③传递后形成的路径: /router?id=123, /router?id=abc
    • 如何使用它们呢? 也有两种方式: 的方式和JavaScript代码方式
    ----传递参数方式一: <router-link>:----<router-link :to="{path: '/profile/' + 123,query: { name:'why',age: 18}}">档案</router-link>----传递参数方式二: JavaScript代码:----export default {name:'App',methods: {toProfile() {this.$router.push({path: '/profile/' + 123,query: {name: 'why',age: 18}})}}}
    • 获取参数:
      ①获取参数通过$route对象获取的,在使用了vue-router 的应用中,路由对象会被注入每个组件中,赋值为 this.$route,并且当路由切换时,路由对象会被更新。
      ②通过$route获取传递的信息如下:
    <p>params: {{ $route.params}}</p><p>query: {{$route.query}}</p>
    • $route和$router是有区别的:
      ①$router为VueRouter实例,想要导航到不同URL,则使用$router.push方法
      ②$route为当前router跳转对象里面可以获取name、path、query、params等

    路由导航守卫:

    • 我们来考虑一个需求: 在一个SPA应用中, 如何改变网页的标题呢?
      ①网页标题是通过来显示的, 但是SPA只有一个固定的HTML, 切换不同的页面时, 标题并不会改变.<br /> ②但是我们可以通过JavaScript来修改<title>的内容.window.document.title = ‘新的标题’.<br /> ③那么在Vue项目中, 在哪里修改? 什么时候修改比较合适呢?</li><li>普通的修改方式:<br /> ①我们比较容易想到的修改标题的位置是每一个路由对应的组件.vue文件中.<br /> ②通过mounted声明周期函数, 执行对应的代码进行修改即可.<br /> ③但是当页面比较多时, 这种方式不容易维护(因为需要在多个页面执行类似的代码).</li><li>有没有更好的办法呢? 使用导航守卫即可,什么是导航守卫?<br /> ①vue-router提供的导航守卫主要用来监听监听路由的进入和离开的.<br /> ②vue-router提供了beforeEach和afterEach的钩子函数, 它们会在路由即将改变前和改变后触发.</li><li>详解:<br /> ①我们可以在钩子当中定义一些标题, 可以利用meta来定义。<br /> ②导航钩子的三个参数解析:<br /> to: 即将要进入的目标的路由对象.<br /> from: 当前导航即将要离开的路由对象.<br /> next: 调用该方法后, 才能进入下一个钩子</li></ul><pre><code class="prism language-xml">// 定义路由const routes =[{path:"/home',component: Home,children: [...],meta:{title:'首页'}},{path: '/about',component: About,meta: {title:'关于'}},{path: '/profile/:id',component: Profile ,meta: {title:'档案'}}]//配置路由const router = new VueRouter ({routes,mode: 'history',linkActiveClass: 'active',})router.beforeEach( (to, from, next) => {window.document.title = to.meta.titlenext()})</code></pre><ul><li>补充:<br /> ①如果是后置钩子, 也就是afterEach, 不需要主动调用next()函数.<br /> ②上面我们使用的导航守卫, 被称之为全局守卫.<br /> 路由独享的守卫.<br /> 组件内的守卫.</li></ul><p><strong>路由keep-alive:</strong></p><ul><li>keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。它们有两个非常重要的属性:<br /> ①include – 字符串或正则表达,只有匹配的组件会被缓存<br /> ②exclude – 字符串或正则表达式,任何匹配的组件都不会被缓存</li><li>router-view 也是一个组件,如果直接被包在 keep-alive 里面,所有路径匹配到的视图组件都会被缓存:</li></ul><pre><code class="prism language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>keep-alive</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>router-view</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>!--所有路径匹配到的视图组件都会被缓存!</span> <span class="token attr-name">-</span> <span class="token attr-name">-</span> <span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>router-view</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>keep-alive</span><span class="token punctuation">></span></span></code></pre><ul><li>通过create声明周期函数来验证</li></ul><h1>Promise</h1><p><strong>什么是Promise呢?</strong></p><ul><li>Promise到底是做什么的呢?<br /> ①Promise是异步编程的一种解决方案。</li><li>那什么时候我们会来处理异步事件呢?<br /> ①一种很常见的场景应该就是网络请求了。<br /> ②我们封装一个网络请求的函数,因为不能立即拿到结果,所以不能像简单的3+4=7一样将结果返回。<br /> ③所以往往我们会传入另外一个函数,在数据请求成功时,将数据通过传入的函数回调出去。<br /> ④如果只是一个简单的网络请求,那么这种方案不会给我们带来很大的麻烦。</li><li>但是当网络请求非常复杂时就会出现回调地狱。</li><li>我们更加期望的是一种更加优雅的方式来进行这种异步操作。Promise可以以一种非常优雅的方式来解决这个问题。</li></ul><p><strong>Promise基本使用:</strong></p><ul><li>new Promise很明显是创建一个Promise对象。小括号中((resolve, reject) => {})也很明显就是一个函数,而且我们这里用的是之前刚刚学习过的箭头函数。但是resolve, reject它们是什么呢?</li><li>我们先知道一个事实:在创建Promise时,传入的这个箭头函数是固定的(一般我们都会这样写)<br /> resolve和reject它们两个也是函数,通常情况下,我们会根据请求数据的成功和失败来决定调用哪一个。</li><li>成功还是失败?<br /> ①如果是成功的,那么通常我们会调用resolve(messsage),这个时候,我们后续的then会被回调。<br /> ②如果是失败的,那么通常我们会调用reject(error),这个时候,我们后续的catch会被回调。</li></ul><pre><code class="prism language-xml">//普通方式setTimeout( function () {let data = 'Hello World'console. log (content) ;}, 1000)//Promise方式new Promise((resolve, reject) => {setTimeout( function () {resolve( 'Hello World')reject( 'Error Data')}, 1000)}).then(data => {console. log(data);}).catch(error => { console. log(error);})</code></pre><p><strong>Promise三种状态:</strong></p><ul><li>当我们开发中有异步操作时, 就可以给异步操作包装一个Promise 异步操作之后会有三种状态<br /> ①pending:等待状态,比如正在进行网络请求,或者定时器没有到时间。<br /> ②fulfill:满足状态,当我们主动回调了resolve时,就处于该状态,并且会回调.then()<br /> ③reject:拒绝状态,当我们主动回调了reject时,就处于该状态,并且会回调.catch()<br /> <noscript><img decoding="async" class="aligncenter" src="https://img.maxssl.com/uploads/?url=https://img-blog.csdnimg.cn/b7863f27ed834e29a4cd4964f6fd9f56.png" /></noscript><img decoding="async" class="lazyload aligncenter" src='data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%20210%20140%22%3E%3C/svg%3E' data-src="https://img.maxssl.com/uploads/?url=https://img-blog.csdnimg.cn/b7863f27ed834e29a4cd4964f6fd9f56.png" /></li></ul><p><strong>Promise链式调用:</strong></p><ul><li>我们在看Promise的流程图时,发现无论是then还是catch都可以返回一个Promise对象。所以,我们的代码其实是可以进行链式调用的:<br /> ①这里我们直接通过Promise包装了一下新的数据,将Promise对象返回了<br /> Promise.resovle():将数据包装成Promise对象,并且在内部回调resolve()函数<br /> Promise.reject():将数据包装成Promise对象,并且在内部回调reject()函数</li></ul><pre><code class="prism language-xml">//链式调用的代码new Promise((resolve, reject) => {setTimeout(function () {resolve('Hello World')},1000 )}). then(data => {console. log(data); // => Hello Worldreturn Promise. resolve(data + '111')}). then(data => {console. log(data); // => Hello World111return Promise. resolve(data + '222')}). then(data => {console. log(data); // => Hello World111222return Promise.reject(data + 'error')}). then(data => {console. log(data); //这里没有输出,这部分代码不会执行return Promise. resolve(data + '333')}).catch(data => {console. log(data); // => Hello World111222errorreturn Promise. resolve(data + '444')}).then(data => {console. log(data); // => Hello World111222error444})</code></pre><ul><li>简化版代码:如果我们希望数据直接包装成Promise.resolve,那么在then中可以直接返回数据<br /> 注意下面的代码中,我将return Promise.resovle(data)改成了return data。结果依然是一样的。</li></ul><pre><code class="prism language-xml">//链式调用的简便写法new Promise((resolve, reject) => {setTimeout(function () {resolve( 'Hello World')},1000)}). then(data => {console. log(data); // => Hello Worldreturn data + '111 '}). then(data => {console. log(data); // => Hello World111return data + '222'}). then(data => {console. log(data); // => Hello World111222return Promise. reject(data + 'error')}). then(data => console. log(data); //这里没有输出,这部分代码不会执行return data + ' 333}).catch(data => {console. log(data); // => Hello World111222errorreturn data + ' 444}). then(data => {console. log(data); // => Hello World111222error444 })</code></pre><ul><li><code>如果希望返回的是reject方法,可以直接throw "字符串"。</code></li></ul><h1>Vuex</h1><p><strong>Vuex是做什么的” /></li><li>多界面状态管理:<br /> ①对于某些状态(状态1/状态2/状态3)来说只属于我们某一个试图,但是也有一些状态(状态a/状态b/状态c)属于多个试图共同想要维护的<br /> 状态1/状态2/状态3你放在自己的房间中,你自己管理自己用,没问题。<br /> 但是状态a/状态b/状态c我们希望交给一个大管家来统一帮助我们管理!!!<br /> 没错,Vuex就是为我们提供这个大管家的工具。<br /> ②全局单例模式(大管家)<br /> 我们现在要做的就是将共享的状态抽取出来,交给我们的大管家,统一进行管理。<br /> 之后,你们每个试图,按照我规定好的规定,进行访问和修改等操作。<br /> 这就是Vuex背后的基本思想。<br /> <noscript><img decoding="async" class="aligncenter" src="https://img.maxssl.com/uploads/?url=https://img-blog.csdnimg.cn/3a9d7184a8164a1e9ea50eee55d4250d.png" /></noscript><img decoding="async" class="lazyload aligncenter" src='data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%20210%20140%22%3E%3C/svg%3E' data-src="https://img.maxssl.com/uploads/?url=https://img-blog.csdnimg.cn/3a9d7184a8164a1e9ea50eee55d4250d.png" /></li></ul><p><strong>Vuex基本使用:</strong></p><ul><li>首先,我们需要在某个地方存放我们的Vuex代码: 这里,我们先创建一个文件夹store,并且在其中创建一个index.js文件,在index.js文件中写入如下代码:</li></ul><pre><code class="prism language-xml">import Vuex from 'vuex'import Vue from 'vue'Vue.use(Vuex)const store = new Vuex.Store({state: {count: 0},mutations: {increment(state) {state.count++},decrement(state) {state.count--}}})export default store</code></pre><ul><li>其次,我们让所有的Vue组件都可以使用这个store对象 来到main.js文件,导入store对象,并且放在new Vue中这样,在其他Vue组件中,我们就可以通过this.$store的方式,获取到这个store对象了</li></ul><pre><code class="prism language-xml">import Vue from 'vue'import App from './App'import store from './store'new Vue({el: '#app',store,render: h => h(App) })</code></pre><ul><li>使用Vuex的count:</li></ul><pre><code class="prism language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>template</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>app<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>{{count}}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span> <span class="token attr-name">@click</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>increment<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>+1<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span> <span class="token attr-name">@click</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>decrement<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>-1<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>template</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>script</span><span class="token punctuation">></span></span><span class="token script"><span class="token language-javascript"><span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span><span class="token literal-property property">name</span><span class="token operator">:</span>" App'<span class="token punctuation">,</span><span class="token literal-property property">components</span><span class="token operator">:</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token literal-property property">computed</span><span class="token operator">:</span> <span class="token punctuation">{</span><span class="token function-variable function">count</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span> Sstore<span class="token punctuation">.</span>state<span class="token punctuation">.</span>count<span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token literal-property property">methods</span><span class="token operator">:</span> <span class="token punctuation">{</span><span class="token function-variable function">increment</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>$store<span class="token punctuation">.</span><span class="token function">commit</span><span class="token punctuation">(</span><span class="token string">'increment'</span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token function-variable function">decrement</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>$store<span class="token punctuation">.</span><span class="token function">commit</span><span class="token punctuation">(</span><span class="token string">'decrement'</span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">}</span></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>script</span><span class="token punctuation">></span></span></code></pre><ul><li>总结:<br /> ①小结:<br /> 提取出一个公共的store对象,用于保存在多个组件中共享的状态<br /> 将store对象放置在new Vue对象中,这样可以保证在所有的组件中都可以使用到<br /> 在其他组件中使用store对象中保存的状态即可<br /> 1、通过this.$store.state.属性的方式来访问状态<br /> 2、通过this.$store.commit(‘mutation中方法’)来修改状态<br /> ②注意事项:<br /> 我们通过提交mutation的方式,而非直接改变store.state.count。<br /> 这是因为Vuex可以更明确的追踪状态的变化,所以不要直接改变store.state.count的值。</li></ul><p><strong>Vuex核心概念:</strong></p><ul><li>Vuex有几个比较核心的概念:<br /> ①State<br /> ②Getters<br /> ③Mutation<br /> ④Action<br /> ⑤Module</li></ul><p><strong>State简介:</strong></p><ul><li>Vuex提出使用单一状态树, 什么是单一状态树呢?英文名称是Single Source of Truth,也可以翻译成单一数据源。</li><li>这个和我们在应用开发中比较类似:<br /> ①如果你的状态信息是保存到多个Store对象中的,那么之后的管理和维护等等都会变得特别困难。所以Vuex也使用了单一状态树来管理应用层级的全部状态。<br /> ②单一状态树能够让我们最直接的方式找到某个状态的片段,而且在之后的维护和调试过程中,也可以非常方便的管理和维护。</li></ul><p><strong>Getters简介:</strong></p><ul><li>有时候,我们需要从store中获取一些state变异后的状态,我们可以在Store中定义getters。</li><li>getters默认是不能传递参数的, 如果希望传递参数, 那么只能让getters本身返回另一个函数。</li><li><code>Getters类似计算属性。</code></li></ul><pre><code class="prism language-xml">getters: {//直接获取store数据greaterAgesStus: state => {return state.students.filter(s => s.age >= 20)},//获取getters数据greaterAgesCount: (state, getters) => {return getters.greaterAgesstus.length},stuByID: state => {return id => {return state.students.find(s => s.id === id)}}}</code></pre><p><strong>Mutation简介:</strong></p><ul><li>Vuex的store状态的更新唯一方式:提交Mutation</li><li>Mutation主要包括两部分:<br /> ①字符串的事件类型(type)<br /> ②一个回调函数(handler),该回调函数的第一个参数就是state。</li></ul><pre><code class="prism language-xml">//multation的定义方式:mutations: {increment(state) {state.count++}}//通过mutation更新:increment: function () {this.$store.commit('increment')}</code></pre><ul><li>在通过mutation更新数据的时候, 有可能我们希望携带一些额外的参数:参数被称为是mutation的载荷(Payload)。</li></ul><pre><code class="prism language-xml">------单参数:-------//multation的定义方式:decrement(state,n) {state.count -= n}//通过mutation更新:decrement: function () {this.Sstore.commit('decrement',2)}------对象:-------//multation的定义方式:changeCount (state,payload) {state.count = payload.count}//通过mutation更新:changeCount: function () {this.$store.commit('changeCount', {count: 0})}</code></pre><ul><li>Mutation提交风格:<br /> ①上面的通过commit进行提交是一种普通的方式。<br /> ②Vue还提供了另外一种风格, 它是一个包含type属性的对象:</li></ul><pre><code class="prism language-xml">//通过mutation更新:this.$store.commit ({type:'changeCount'count: 100})//Mutation中的处理方式是将整个commit的对象作为payload使用, 所以代码没有改变, 依然如下:changeCount (state,pay1oad) {state.count = payload.count}</code></pre><ul><li>Mutation响应规则:<br /> ①Vuex的store中的state是响应式的, 当state中的数据发生改变时, Vue组件会自动更新.<br /> ②这就要求我们必须遵守一些Vuex对应的规则:<br /> 提前在store中初始化好所需的属性.<br /> 当给state中的对象添加新属性时, 使用下面的方式:<br /> 方式一: 使用Vue.set(obj, ‘newProp’, 123)<br /> 方式二: 用心对象给旧对象重新赋值</li><li>Mutation常量类型:<br /> ①在mutation中, 我们定义了很多事件类型(也就是其中的方法名称),当我们的项目增大时, Vuex管理的状态越来越多, 需要更新状态的情况越来越多, 那么意味着Mutation中的方法越来越多,方法过多, 使用者需要花费大量的经历去记住这些方法, 甚至是多个文件间来回切换, 查看方法名称, 甚至如果不是复制的时候, 可能还会出现写错的情况。<br /> ②在各种Flux实现中, 一种很常见的方案就是使用常量替代Mutation事件的类型,我们可以将这些常量放在一个单独的文件中, 方便管理以及让整个app所有的事件类型一目了然。<br /> ③我们可以创建一个文件: mutation-types.js, 并且在其中定义我们的常量,定义常量时, 我们可以使用ES2015中的风格, 使用一个常量来作为函数的名称。</li></ul><pre><code class="prism language-xml">文件名:mutation-typesjs代码:export const UPDATE_ INFO = 'UPDATE_INFO'</code></pre><ul><li>Mutation同步函数:<br /> ①通常情况下, Vuex要求我们Mutation中的方法必须是同步方法,主要的原因是当我们使用devtools时, 可以devtools可以帮助我们捕捉mutation的快照。<br /> ②但是如果是异步操作, 那么devtools将不能很好的追踪这个操作什么时候会被完成。所以通常情况下, 不要再mutation中进行异步的操作。</li></ul><p><strong>Action简介:</strong></p><ul><li>我们强调, 不要再Mutation中进行异步操作. 但是某些情况, 我们确实希望在Vuex中进行一些异步操作, 比如网络请求,必然是异步的. 这个时候怎么处理呢” />\\定义:const store = new Vuex.Store({state: {count: 0},mutations: {increment(state) {state.count++}},actions: {increment (context) {context.commit(‘increment’)}}})\\使用:methods: {increment() {this.$store.dispatch(‘increment’) }}</code><p><strong>Module简介:</strong></p><ul><li>Module是模块的意思, 为什么在Vuex中我们要使用模块呢?<br /> ①Vue使用单一状态树,那么也意味着很多状态都会交给Vuex来管理,当应用变得非常复杂时,store对象就有可能变得相当臃肿。<br /> ②<code>为了解决这个问题, Vuex允许我们将store分割成模块(Module), 而每个模块拥有自己的state、mutation、action、getters等。</code></li><li>注意:<br /> ①虽然, 我们的<code>getters</code>和<code>mutation</code>都是定义在对象内部的,但是在调用的时候, 依然是通过this.$store来直接调用的。<br /> ②actions:<br /> <code>局部状态通过 context.state 暴露出来,根节点状态则为 context.rootState</code><br /> 如果getters中也需要使用全局的状态, 可以接受更多的参数</li></ul><pre><code class="prism language-xml">const moduleA = {//...actions: {incrementIfoddonRootSum ({state,commit,rootState}) {if ((state.count + rootState.count) %2 ===1) {commit('increment')}}}}</code></pre><ul><li>代码结构:</li></ul><pre><code class="prism language-xml">const moduleA = {state: { ... },mutations: { ... },actions: { ... },getters: { ... }}const moduleB = {state: { ... },mutations: { ... },actions: { ... }}const store = new Vuex.Store({modules: {a: modu1eA,b: modu1eB}})store.state.a // -> moduleA的状态store.state.b // -> moduleB的状态</code></pre><p><strong>项目结构:</strong></p><ul><li>当我们的Vuex帮助我们管理过多的内容时, 好的项目结构可以让我们的代码更加清晰:<br /> <noscript><img decoding="async" class="aligncenter" src="https://img.maxssl.com/uploads/?url=https://img-blog.csdnimg.cn/af372030a77746c894e3829c402814dd.png" /></noscript><img decoding="async" class="lazyload aligncenter" src='data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%20210%20140%22%3E%3C/svg%3E' data-src="https://img.maxssl.com/uploads/?url=https://img-blog.csdnimg.cn/af372030a77746c894e3829c402814dd.png" /></li></ul><h1>axios</h1><p><strong>选择什么网络模块” /></li></ul><p><strong>为什么选择axios?</strong></p><ul><li>功能特点:<br /> ①在浏览器中发送 XMLHttpRequests 请求<br /> ②在 node.js 中发送 http请求<br /> ③支持 Promise API<br /> ④拦截请求和响应<br /> ⑤转换请求和响应数据</li></ul><p><strong>axiox请求方式:</strong></p><ul><li>支持多种请求方式:<br /> ①axios(config)<br /> ②axios.request(config)<br /> ③axios.get(url[, config])<br /> ④axios.delete(url[, config])<br /> ⑤axios.head(url[, config])<br /> ⑥axios.post(url[, data[, config]])<br /> ⑦axios.put(url[, data[, config]])<br /> ⑧axios.patch(url[, data[, config]])</li><li>发送get请求演示:</li></ul><pre><code class="prism language-xml">import axios from 'axios'export default {name : 'app',created() {//提问:为什么我这里没有跨域的问题?//1.没有请求参数axios.get( 'http://123.207.32.32:8000/category').then(res => {console.log(res);}).catch(err =>{console.log(err);})//2.有请求参数axios.get( 'http:/ /123.207.32.32:8000/home/data',{params: itype: 'sell', page: 1}}).then(res => {console.log ( res);}).catch(err => {console.log(err);})}}</code></pre><ul><li>发送并发请求:<br /> ①有时候, 我们可能需求同时发送两个请求<br /> ②使用axios.all, 可以放入多个请求的数组.<br /> ③axios.all([]) 返回的结果是一个数组,使用 axios.spread 可将数组 [res1,res2] 展开为 res1, res2</li></ul><pre><code class="prism language-xml">import axios from 'axios'export default {name : 'app',created () {[//发送并发请求axios.all([axios.get('http://123.207.32.32:8000/category'),axios.get('http://123.207.32.32:8000/home/data',{params : {type: 'sell', page: 1}})]).then(axios.spread((res1,res2) => {console.log(res1);console.log(res2);}))}</code></pre><p><strong>全局配置:</strong></p><ul><li>在上面的示例中, 我们的BaseURL是固定的<br /> ①事实上, 在开发中可能很多参数都是固定的.<br /> ②这个时候我们可以进行一些抽取, 也可以利用axiox的全局配置</li></ul><pre><code class="prism language-xml">created( {//提取全局的配置axios.defaults.baseURL = 'http://123.207.32.32:8000'//发送并发请求axios.all([axios.get('/category'),axios.get('/home/data',{params: {type: 'sell', page:1}})]).then(axios.spread((res1,res2) =>{console.log (res1);console.log(res2);}))}</code></pre><ul><li>常见的配置选项:</li></ul><pre><code class="prism language-xml">请求地址url: '/user',请求类型method: 'get',请根路径baseURL: 'http://www.mt.com/api',请求前的数据处理transformRequest:[function(data){}],请求后的数据处理transformResponse: [function(data){}],自定义的请求头headers:{'x-Requested-With':'XMLHttpRequest'},URL查询对象params:{ id: 12 },查询对象序列化函数paramsSerializer: function(params){ }request bodydata: { key: 'aa'},超时设置stimeout: 1000,跨域是否带TokenwithCredentials: false,自定义请求处理adapter: function(resolve, reject, config){},身份验证信息auth: { uname: '', pwd: '12'},响应的数据格式 json / blob /document /arraybuffer / text / streamresponseType: 'json',</code></pre><p><strong>axios的实例:</strong></p><ul><li>为什么要创建axios的实例呢?<br /> ①当我们从axios模块中导入对象时, 使用的实例是默认的实例.<br /> ②当给该实例设置一些默认配置时, 这些配置就被固定下来了.<br /> ③但是后续开发中, 某些配置可能会不太一样.<br /> ④比如某些请求需要使用特定的baseURL或者timeout或者content-Type等.<br /> ⑤这个时候, 我们就可以创建新的实例, 并且传入属于该实例的配置信息.</li></ul><pre><code class="prism language-xml">//创建新的实例const axiosInstance = axios.create({baseURL: 'http:/ /123.207.32.32:8000',timeout: 5000,headers: {'Content-Type' : 'application/x-www-form-urlencoded '}})//发送网络请求axiosInstance({url: '/category',method: 'get'}).then(res => {console. log(res);}).catch(err => {console. log(err);})</code></pre><ul><li>axios封装:</li></ul><pre><code class="prism language-xml">import originAxios from 'axios'export default function axios(option) {return new Promise((resolve, reject) =>{//1.创建axios的实例const instance = originAxios.create({baseURL: '/api',timeout: 5000,headers:''});//2.传入对象进行网络请求instance(option).then(res => {resolve(res)}).catch(err => {reject(err)})})}</code></pre><p><strong>axios拦截器:</strong></p><ul><li>axios提供了拦截器,用于我们在发送每次请求或者得到相应后,进行对应的处理。</li><li>如何使用拦截器呢?</li></ul><pre><code class="prism language-xml">//配置请求和响应拦截instance.interceptors.request.use(config =>{console.log('来到了request拦截success中');return config}, err => {console.log('来到了request拦截failure中');return err}instance.interceptors.response.use(response =>{console.log('来到了response拦截success中');return response.data}, err =>{console.log('来到了response拦截failure中');return err})</code></pre><ul><li>拦截器中都做什么呢?<br /> ①请求拦截中错误拦截较少,通常都是配置相关的拦截。可能的错误比如请求超时,可以将页面跳转到一个错误页面中。<br /> ②响应拦截中完成的事情:<br /> 响应的成功拦截中,主要是对数据进行过滤。<br /> 响应的失败拦截中,可以根据status判断报错的错误码,跳转到不同的错误提示页面。</li></ul><pre><code class="prism language-xml">//请求拦截instance.interceptors.request.use(config =>{console.log('来到了request拦截success中');//1.当发送网络请求时,在页面中添加一个loading组件,作为动画//2.某些请求要求用户必须登录,判断用户是否有token,如果没有token跳转到login页面//3.对请求的参数进行序列化config.data = qs.stringify (config.data)console.log(config);//4.等等return config})//响应的成功拦截instance.interceptors.response.use(response => {console.log('来到了response拦截success中');return response.data})//响应的失败拦截},err =>{console.log('来到了response拦截failure中');if (err && err.response) {switch (err.response.status) {case 400:err.message ='请求错误'breakcase 401:err.message ='未授权的访问'break}}return err</code></pre><h1>Vue开发总结</h1><p><strong>VSCode开发简介:</strong></p><ul><li>我们在html文件上输入【!】叹号(在英文状态下),然后按键盘的【Tab】键,只有在这种情况下按住Tab键可以快速创建一个html模板。</li><li>代码缩进时只缩进两个空格。</li><li>开发快捷键:<br /> ①Ctrl + p:查找文件<br /> ②Ctrl + shift + f:全局搜索字符串<br /> ③Ctrl+j:切换终端<br /> ④Ctrl + b:显示/隐藏左侧目录栏<br /> ⑤Ctrl + shift + p,F1:显示所有命令<br /> ⑥拆分当前编辑窗口:Ctrl + \ ,Ctrl +1 2 3 4 等 在编辑窗口间切换<br /> ⑦选中方法名->Shift + F12,选中方法名->鼠标右键:显示引用 Show References</li><li>链接:VSCode Vue开发推荐插件和VSCode快捷键(小结)</li><li>插件:<br /> ①Volar 是一个 vscode 的插件,volar提供了非常卧槽的功能。</li></ul><p><strong>Vue开发简介:</strong></p><ul><li>src目录分析:<br /> ①apis:请求后台接口文件<br /> ②assets:资源文件,比如存放 css,图片等资源。<br /> ③component​:组件文件夹,用来存放 vue 的公共组件(注册于全局,在整个项目中通过关键词便可直接输出)<br /> ④router​:用来存放 ​index.js​,这个 js 用来配置路由<br /> ⑤views​:用来放主体页面,虽然和组件文件夹都是 vue 文件,但 views 下的 vue 文件是可以用来充当路由 view 的。<br /> ⑥store:Vuex状态管理文件<br /> ⑦tool​/utils:用来存放工具类 js,将 js 代码封装好放入这个文件夹可以全局调用(比如常见的​ api.js​,​http.js​ 是对 http 方法和 api 方法的封装)。<br /> ⑧request:http工具类,可以放在tool/utils中,也可以自定义一个文件夹。</li></ul></article></div><div class="related-posts"><h2 class="related-posts-title"><i class="fab fa-hive me-1"></i>相关文章</h2><div class="row g-2 g-md-3 row-cols-2 row-cols-md-3 row-cols-lg-4"><div class="col"><article class="post-item item-grid"><div class="tips-badge position-absolute top-0 start-0 z-1 m-2"></div><div class="entry-media ratio ratio-3x2"> <a target="" class="media-img lazy bg-cover bg-center" href="https://www.maxssl.com/article/3239/" title="mybaits-plus lambdaQuery() 和 lambdaUpdate() 比较常见的使用方法" data-bg="https://img.maxssl.com/uploads/?url=https://img-blog.csdnimg.cn/b91a797f6d49473d99a8ebbd8beba514.png"> </a></div><div class="entry-wrapper"><h2 class="entry-title"> <a target="" href="https://www.maxssl.com/article/3239/" title="mybaits-plus lambdaQuery() 和 lambdaUpdate() 比较常见的使用方法">mybaits-plus lambdaQuery() 和 lambdaUpdate() 比较常见的使用方法</a></h2></div></article></div><div class="col"><article class="post-item item-grid"><div class="tips-badge position-absolute top-0 start-0 z-1 m-2"></div><div class="entry-media ratio ratio-3x2"> <a target="" class="media-img lazy bg-cover bg-center" href="https://www.maxssl.com/article/42836/" title="蓝桥杯python比赛历届真题99道经典练习题 (89-99)" data-bg="/wp-content/themes/ripro-v5/assets/img/thumb.jpg"> </a></div><div class="entry-wrapper"><h2 class="entry-title"> <a target="" href="https://www.maxssl.com/article/42836/" title="蓝桥杯python比赛历届真题99道经典练习题 (89-99)">蓝桥杯python比赛历届真题99道经典练习题 (89-99)</a></h2></div></article></div><div class="col"><article class="post-item item-grid"><div class="tips-badge position-absolute top-0 start-0 z-1 m-2"></div><div class="entry-media ratio ratio-3x2"> <a target="" class="media-img lazy bg-cover bg-center" href="https://www.maxssl.com/article/17961/" title="【数字图像处理】实验二 图像增强(MATLAB实现)" data-bg="https://img.maxssl.com/uploads/?url=https://img-blog.csdnimg.cn/06039ecb63e241b2a5114789908420ca.png"> </a></div><div class="entry-wrapper"><h2 class="entry-title"> <a target="" href="https://www.maxssl.com/article/17961/" title="【数字图像处理】实验二 图像增强(MATLAB实现)">【数字图像处理】实验二 图像增强(MATLAB实现)</a></h2></div></article></div><div class="col"><article class="post-item item-grid"><div class="tips-badge position-absolute top-0 start-0 z-1 m-2"></div><div class="entry-media ratio ratio-3x2"> <a target="" class="media-img lazy bg-cover bg-center" href="https://www.maxssl.com/article/52512/" title="牛客AI面试重磅上新“外语测评”能力,5大亮点高效招聘英语岗位!" data-bg="https://img.maxssl.com/uploads/?url=https://img-blog.csdnimg.cn/direct/bb85f29830604c2ab57a609334e5d610.png"> </a></div><div class="entry-wrapper"><h2 class="entry-title"> <a target="" href="https://www.maxssl.com/article/52512/" title="牛客AI面试重磅上新“外语测评”能力,5大亮点高效招聘英语岗位!">牛客AI面试重磅上新“外语测评”能力,5大亮点高效招聘英语岗位!</a></h2></div></article></div><div class="col"><article class="post-item item-grid"><div class="tips-badge position-absolute top-0 start-0 z-1 m-2"></div><div class="entry-media ratio ratio-3x2"> <a target="" class="media-img lazy bg-cover bg-center" href="https://www.maxssl.com/article/54221/" title="《技术成长密码》:技术一号位的方法论 — 如何构建个人成长路线图?" data-bg="https://img.maxssl.com/uploads/?url=https://img-blog.csdnimg.cn/7eefe5553bef4ea38c63c908aa2258e9.png"> </a></div><div class="entry-wrapper"><h2 class="entry-title"> <a target="" href="https://www.maxssl.com/article/54221/" title="《技术成长密码》:技术一号位的方法论 — 如何构建个人成长路线图?">《技术成长密码》:技术一号位的方法论 — 如何构建个人成长路线图?</a></h2></div></article></div><div class="col"><article class="post-item item-grid"><div class="tips-badge position-absolute top-0 start-0 z-1 m-2"></div><div class="entry-media ratio ratio-3x2"> <a target="" class="media-img lazy bg-cover bg-center" href="https://www.maxssl.com/article/17018/" title="js判断两个字符串是否相等的两种方法" data-bg="/wp-content/themes/ripro-v5/assets/img/thumb.jpg"> </a></div><div class="entry-wrapper"><h2 class="entry-title"> <a target="" href="https://www.maxssl.com/article/17018/" title="js判断两个字符串是否相等的两种方法">js判断两个字符串是否相等的两种方法</a></h2></div></article></div><div class="col"><article class="post-item item-grid"><div class="tips-badge position-absolute top-0 start-0 z-1 m-2"></div><div class="entry-media ratio ratio-3x2"> <a target="" class="media-img lazy bg-cover bg-center" href="https://www.maxssl.com/article/34336/" title="SQL INSERT以及批量几种方式" data-bg="/wp-content/themes/ripro-v5/assets/img/thumb.jpg"> </a></div><div class="entry-wrapper"><h2 class="entry-title"> <a target="" href="https://www.maxssl.com/article/34336/" title="SQL INSERT以及批量几种方式">SQL INSERT以及批量几种方式</a></h2></div></article></div><div class="col"><article class="post-item item-grid"><div class="tips-badge position-absolute top-0 start-0 z-1 m-2"></div><div class="entry-media ratio ratio-3x2"> <a target="" class="media-img lazy bg-cover bg-center" href="https://www.maxssl.com/article/26055/" title="数据结构——栈(C语言)" data-bg="https://img.maxssl.com/uploads/?url=https://img-blog.csdnimg.cn/8d1f86bb5f9c4ec687c039aba9508c10.png"> </a></div><div class="entry-wrapper"><h2 class="entry-title"> <a target="" href="https://www.maxssl.com/article/26055/" title="数据结构——栈(C语言)">数据结构——栈(C语言)</a></h2></div></article></div></div></div></div><div class="sidebar-wrapper col-md-12 col-lg-3 h-100" data-sticky><div class="sidebar"><div id="recent-posts-4" class="widget widget_recent_entries"><h5 class="widget-title">最新关注</h5><ul><li> <a href="https://www.maxssl.com/article/57859/">【MySQL】InnoDB存储引擎</a></li><li> <a href="https://www.maxssl.com/article/57858/">DB-GPT:强强联合Langchain-Vicuna的应用实战开源项目,彻底改变与数据库的交互方式</a></li><li> <a href="https://www.maxssl.com/article/57857/">TigerBeetle:世界上最快的会计数据库</a></li><li> <a href="https://www.maxssl.com/article/57856/">【SQL server】玩转SQL server数据库:第三章 关系数据库标准语言SQL(二)数据查询</a></li><li> <a href="https://www.maxssl.com/article/57855/">马斯克400条聊天记录被法院公开,原来推特收购是在短信上谈崩的</a></li><li> <a href="https://www.maxssl.com/article/57854/">戏精摩根大通:从唱空比特币到牵手贝莱德</a></li></ul></div><div id="ri_sidebar_posts_widget-2" class="widget sidebar-posts-list"><h5 class="widget-title">热文推荐</h5><div class="row g-3 row-cols-1"><div class="col"><article class="post-item item-list"><div class="entry-media ratio ratio-3x2 col-auto"> <a target="" class="media-img lazy" href="https://www.maxssl.com/article/8718/" title="pycharm怎么改成中文(汉化插件 pycharm自带)" data-bg="https://img.maxssl.com/uploads/?url=https://img-blog.csdnimg.cn/e900ab9ad5364d9593904c989cf1861c.png"></a></div><div class="entry-wrapper"><div class="entry-body"><h2 class="entry-title"> <a target="" href="https://www.maxssl.com/article/8718/" title="pycharm怎么改成中文(汉化插件 pycharm自带)">pycharm怎么改成中文(汉化插件 pycharm自带)</a></h2></div></div></article></div><div class="col"><article class="post-item item-list"><div class="entry-media ratio ratio-3x2 col-auto"> <a target="" class="media-img lazy" href="https://www.maxssl.com/article/23903/" title="【C语言】深入解密C语言组包与解包的用法、应用以及const的详细解说" data-bg="https://img.maxssl.com/uploads/?url=https://img-blog.csdnimg.cn/c1ec28ae114048d2beebf6446f1e06ea.png"></a></div><div class="entry-wrapper"><div class="entry-body"><h2 class="entry-title"> <a target="" href="https://www.maxssl.com/article/23903/" title="【C语言】深入解密C语言组包与解包的用法、应用以及const的详细解说">【C语言】深入解密C语言组包与解包的用法、应用以及const的详细解说</a></h2></div></div></article></div><div class="col"><article class="post-item item-list"><div class="entry-media ratio ratio-3x2 col-auto"> <a target="" class="media-img lazy" href="https://www.maxssl.com/article/49324/" title="【开发】后端框架——微服务" data-bg="https://img.maxssl.com/uploads/?url=https://img-blog.csdnimg.cn/5441bcc196984c7d8c26e24dd6bcb074.png"></a></div><div class="entry-wrapper"><div class="entry-body"><h2 class="entry-title"> <a target="" href="https://www.maxssl.com/article/49324/" title="【开发】后端框架——微服务">【开发】后端框架——微服务</a></h2></div></div></article></div><div class="col"><article class="post-item item-list"><div class="entry-media ratio ratio-3x2 col-auto"> <a target="" class="media-img lazy" href="https://www.maxssl.com/article/53618/" title="供应链领域数据中台架构建设(上)" data-bg="https://img.maxssl.com/uploads/?url=https://img-blog.csdnimg.cn/img_convert/5362bdfc9db5d98a19e58dad179c90b3.png"></a></div><div class="entry-wrapper"><div class="entry-body"><h2 class="entry-title"> <a target="" href="https://www.maxssl.com/article/53618/" title="供应链领域数据中台架构建设(上)">供应链领域数据中台架构建设(上)</a></h2></div></div></article></div><div class="col"><article class="post-item item-list"><div class="entry-media ratio ratio-3x2 col-auto"> <a target="" class="media-img lazy" href="https://www.maxssl.com/article/28259/" title="程序启动报错org.springframework.context.ApplicationContextException: Unable to start web server" data-bg="/wp-content/themes/ripro-v5/assets/img/thumb.jpg"></a></div><div class="entry-wrapper"><div class="entry-body"><h2 class="entry-title"> <a target="" href="https://www.maxssl.com/article/28259/" title="程序启动报错org.springframework.context.ApplicationContextException: Unable to start web server">程序启动报错org.springframework.context.ApplicationContextException: Unable to start web server</a></h2></div></div></article></div><div class="col"><article class="post-item item-list"><div class="entry-media ratio ratio-3x2 col-auto"> <a target="" class="media-img lazy" href="https://www.maxssl.com/article/28990/" title="oracle 表分区详解" data-bg="/wp-content/themes/ripro-v5/assets/img/thumb.jpg"></a></div><div class="entry-wrapper"><div class="entry-body"><h2 class="entry-title"> <a target="" href="https://www.maxssl.com/article/28990/" title="oracle 表分区详解">oracle 表分区详解</a></h2></div></div></article></div></div></div></div></div></div></div></main><footer class="site-footer py-md-4 py-2 mt-2 mt-md-4"><div class="container"><div class="text-center small w-100"><div>Copyright © <script>today=new Date();document.write(today.getFullYear());</script> maxssl.com 版权所有 <a href="https://beian.miit.gov.cn/" target="_blank" rel="nofollow noopener">浙ICP备2022011180号</a></div><div class=""><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-7656930379472324" crossorigin="anonymous"></script></div></div></div></footer><div class="rollbar"><ul class="actions"><li><a target="" href="https://www.maxssl.com/" rel="nofollow noopener noreferrer"><i class="fas fa-home"></i><span></span></a></li><li><a target="" href="http://wpa.qq.com/msgrd?v=3&uin=6666666&site=qq&menu=yes" rel="nofollow noopener noreferrer"><i class="fab fa-qq"></i><span></span></a></li></ul></div><div class="back-top"><i class="fas fa-caret-up"></i></div><div class="dimmer"></div><div class="off-canvas"><div class="canvas-close"><i class="fas fa-times"></i></div><div class="logo-wrapper"> <a class="logo text" href="https://www.maxssl.com/">MaxSSL</a></div><div class="mobile-menu d-block d-lg-none"></div></div> <script></script><noscript><style>.lazyload{display:none}</style></noscript><script data-noptimize="1">window.lazySizesConfig=window.lazySizesConfig||{};window.lazySizesConfig.loadMode=1;</script><script async data-noptimize="1" src='https://www.maxssl.com/wp-content/plugins/autoptimize/classes/external/js/lazysizes.min.js'></script><script src='//cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js' id='jquery-js'></script> <script src='//cdn.bootcdn.net/ajax/libs/highlight.js/11.7.0/highlight.min.js' id='highlight-js'></script> <script src='https://www.maxssl.com/wp-content/themes/ripro-v5/assets/js/vendor.min.js' id='vendor-js'></script> <script id='main-js-extra'>var zb={"home_url":"https:\/\/www.maxssl.com","ajax_url":"https:\/\/www.maxssl.com\/wp-admin\/admin-ajax.php","theme_url":"https:\/\/www.maxssl.com\/wp-content\/themes\/ripro-v5","singular_id":"1234","post_content_nav":"0","site_notify_auto":"0","current_user_id":"0","ajax_nonce":"53e964f340","gettext":{"__copypwd":"\u5bc6\u7801\u5df2\u590d\u5236\u526a\u8d34\u677f","__copybtn":"\u590d\u5236","__copy_succes":"\u590d\u5236\u6210\u529f","__comment_be":"\u63d0\u4ea4\u4e2d...","__comment_succes":"\u8bc4\u8bba\u6210\u529f","__comment_succes_n":"\u8bc4\u8bba\u6210\u529f\uff0c\u5373\u5c06\u5237\u65b0\u9875\u9762","__buy_be_n":"\u8bf7\u6c42\u652f\u4ed8\u4e2d\u00b7\u00b7\u00b7","__buy_no_n":"\u652f\u4ed8\u5df2\u53d6\u6d88","__is_delete_n":"\u786e\u5b9a\u5220\u9664\u6b64\u8bb0\u5f55\uff1f"}};</script> <script src='https://www.maxssl.com/wp-content/themes/ripro-v5/assets/js/main.min.js' id='main-js'></script> </body></html>