自定义创建项目

基于VueCli自定义创建项目

1.Eslint代码规范

代码规范:一套写代码的约定规则。 比如 赋值符号的左右是否需要空格 一句话结束是否要加;

正规的团队 需要统一的编码风格

https://standardjs.com/rules-zhcn.html

规则查找 https://zh-hans.eslint.org/docs/latest/rules

eslint插件
安装ESLintPrettier ESLint
setting.json中配置

{
    "editor.tabSize": 2,
    "editor.linkedEditing": true,
    "security.workspace.trust.untrustedFiles": "open",
    "git.autofetch": true,
    "workbench.editor.untitled.hint": "hidden",
    "emmet.includeLanguages": {
        "editor.formatOnType": "true",
        "editor.formatOnSave": "true"
    },
    "editor.formatOnType": true,
    "editor.formatOnPaste": true,
    "git.openRepositoryInParentFolders": "never",
    "cssrem.rootFontSize": 75,
    "[vue]": {
        "editor.defaultFormatter": "Vue.volar"
    },
    "vetur.validation.template": false,
    // 保存时,eslint自动帮我们修复错误
    "editor.codeActionsOnSave": {
        "source.fixAll": true
    },
    "files.autoSave": "afterDelay",
    // 保存代码,自动格式化
    "editor.formatOnSave": true,
    "[jsonc]": {
        "editor.defaultFormatter": "vscode.json-language-features"
    },
    "[javascript]": {
        "editor.defaultFormatter": "rvest.vs-code-prettier-eslint"
    },
    "[html]": {
        "editor.defaultFormatter": "rvest.vs-code-prettier-eslint"
    }
}

2.调整初始化目录

  • 删除多余的文件
  • 修改路由配置和App.vue
  • 新增两个目录 api / utils
    • api 接口模块 发送ajax请求的接口模块
    • utils工具模块 自己封装的一些工具方法模块

3.vant组件库 ui

组件库:第三方封装好了很多很多的组件,整合到一起就是一个组件库

https://vant-contrib.gitee.io/vant/v2/#/zh-CN/

其他vue组件库

pc端: element-ui(element-plus) ant-design-vue

移动端: vant-ui , Mint UI(饿了么) ,Cube UI(滴滴)

Vant使用

1.按需导入

自动按需导入

# 安装插件
npm i babel-plugin-import -D
// 对于使用 babel7 的用户,可以在 babel.config.js 中配置
module.exports = {
  plugins: [
    ['import', {
      libraryName: 'vant',
      libraryDirectory: 'es',
      style: true
    }, 'vant']
  ]
};
// 接着你可以在代码中直接引入 Vant 组件
// 插件会自动将代码转化为方式二中的按需引入形式
import { Button } from 'vant';

手动按需导入
在不使用插件的情况下,可以手动引入需要的组件。

import Button from 'vant/lib/button';
import 'vant/lib/button/style';

2.全部导入

import Vue from 'vue';
import Vant from 'vant';
import 'vant/lib/index.css';

Vue.use(Vant);

3.定制主题色

1.按需引入
babel.config.js中配置

 module.exports = {
  plugins: [
    [
      'import',
      {
        libraryName: 'vant',
        libraryDirectory: 'es',
        // 指定样式路径
        style: (name) => `${name}/style/less`,
      },
      'vant',
    ],
  ],
};

2.修改样式变量
vue.config.js 中进行配置

// vue.config.js
module.exports = {
  css: {
    loaderOptions: {
      less: {
        // 若 less-loader 版本小于 6.0,请移除 lessOptions 这一级,直接配置选项。
        lessOptions: {
          modifyVars: {
            // 直接覆盖变量
            'blue: 'orange',
          },
        },
      },
    },
  },
};

4.项目中的vw适配

基于postcss插件 实现项目vw适配

  • 安装插件

    yarn add postcss-px-to-viewport@1.1.1
    
  • 根目录新建postcss.config.js文件

    // postcss.config.js
    module.exports = {
      plugins: {
        'postcss-px-to-viewport': {
          viewportWidth: 375,
        },
      },
    };
    

5.二级路由配置

在这里插入图片描述

6.axios封装

使用axios来请求后端接口,会对axios进行一些配置,(配置基础地址,请求响应拦截器等)
项目开发中,会对axios进行二次封装,单独封装到一个request模块中,便于维护使用
安装axios-------新建request模块(utils/request.js)------创建实例,自定义配置,导出实例-----------使用

6.1请求封装成方法,统一存到api模块,与页面分离

以前
在这里插入图片描述
现在进行了封装,实现了复用

  • 请求和页面逻辑分离
  • 相同的请求可以直接复用
  • 请求进行了统一管理
    在这里插入图片描述
    api/user.js
import request from '../utils/request'

export const registerFn = (data) => {
  return request.post('/user/register', data)
}

export const loginFn = (data) => {
  return request.post('/user/login', data)
}

使用
Login.vue Register.vue类似

<script>
import { loginFn } from '@/api/user'
// import request from '../utils/request'
export default {
  name: 'MyLogin',
  methods: {
    async onSubmit(values) {
      try {
        console.log('submit', values)
        // const res = await request.post('/user/login', values)
        // console.log(res)
        const res = await loginFn(values)
        console.log(res)
        this.$toast('登录成功')
      } catch (err) {
        console.log(err)
      }
    }
  }
}

6.2响应拦截中统一处理错误

问题:每次请求,都会又可能会错误,就需要错误提示

每次try catch很麻烦,能不能统一处理呢?

// 添加响应拦截器
instance.interceptors.response.use(
  function (response) {
    // 2xx 范围内的状态码都会触发该函数。
    // 对响应数据做点什么
    console.log(response)
    return response
  },
  function (error) {
    console.log(error, 0)
    // 超出 2xx 范围的状态码都会触发该函数。
    // 有错误响应 后台会正常返回错误信息
    if (error.response) {
      Toast(error.response.data.message)
    }
    // 对响应错误做点什么
    return Promise.reject(error)
  }
)

6.3注册功能

在这里插入图片描述

<script>
/*
  /user/register   post请求
   username  password
*/
import { registerFn } from '../api/user'
export default {
  name: 'RegisterName',
  methods: {
    async onSubmit(values) {
      console.log(values)
      await registerFn(values)
      // toast已经被挂载到了原型上  通过this.$toast直接调用
      this.$toast.success('注册成功')
      console.log('注册成功了啦啦啦啦啦')
      this.$router.push('/login')
      this.$toast.fail('注册失败')
    }
  }
}
</script>

6.4本地存储封装

本地存入token,为了防止重名,起的名字很长,方便使用—local模块(getToken,setToken,delToken)

utils/storage.js

// 定义常量
const KEY = 'vant-mobile-token'

export const getToken = () => {
  return localStorage.getItem(KEY)
}

export const setToken = (token) => {
  localStorage.setItem(KEY, token)
}

export const sdelToken = () => {
  localStorage.removeItem(KEY)
}

问题
在这里插入图片描述
在这里插入图片描述

6.5登录功能

封装请求api----登录操作—跳转首页

<script>
import { loginFn } from '@/api/user'
import { setToken } from '@/api/storage'
export default {
  name: 'MyLogin',
  methods: {
    async onSubmit(values) {
      const { data } = await loginFn(values)
      // 登录成功提示
      this.$toast('登录成功')
      // 本地存储token
      setToken(data.data.token)
      // 跳转主页
      this.$router.push('/')
    }
  }
}
</script>

小问题
登录接口报错
在这里插入图片描述
解决方法
在这里插入图片描述

6.6页面访问拦截(全局前置守卫)

基于全局前置守卫,进行页面访问拦截处理

项目中,只能登录用户开放,如果未登录,一律拦截到登录

路由导航守卫----全局前置守卫

  • 所有的路由一旦被匹配到,都会先经过全局前置守卫

  • 只有全局前置守卫放行,才会真正解析渲染组件,才能看到页面内容

    拦截或放行的关键点?------>用户是否有登录权证 token
    在这里插入图片描述

// 放行白名单
const whiteList = ['/login', '/register']
router.beforeEach((to, from, next) => {
  // console.log(to, from, next)
  const token = getToken()
  console.log(token)
  if (token) {
    // 有token就直接放行
    next()
  } else {
    // 没有token看是否在白名单中
    if (whiteList.includes(to.path)) {
      // 在白名单中就放行
      next()
    } else {
      // 不在白名单中就拦截到登录页
      next('/login')
    }
  }
})

7.首页

7.1基本布局

7.2获取面经列表


文本标签过滤
在这里插入图片描述
用正则清除标记符号
在这里插入图片描述

7.3请求拦截器统一携带token

每次请求自己携带token,太麻烦,通过请求拦截器统一携带token 更方便

// 添加请求拦截器--请求头统一携带token
instance.interceptors.request.use(function (config) {
  // 在发送请求之前做些什么
  const token = getToken()
  if (token) {
    config.headers.Authorization = `Bearer ${token}`
  }
  return config
}, function (error) {
  // 对请求错误做些什么
  return Promise.reject(error)
})

7.4响应拦截器–处理token过期

token是由过期的时间的(2h) 一旦过期 或失效 就无法正确获取到数据—401

过期token进行请求-----------后台返回401 ---------跳转到登录页

// 添加响应拦截器
instance.interceptors.response.use(function (response) {
  // 2xx 范围内的状态码都会触发该函数。
  // 对响应数据做点什么
  return response
}, function (error) {
//   console.log(error, 0)
  //   有错误响应 后台正常返回了错误信息
  if (error.response) {
    if (error.response.status === 401) {
      // 清除掉无效的token
      delToken()
      // 拦截到登录
      router.push('/login')
    } else {
      // 有错误响应 提示错误信息
      Toast(error.response.data.message)
    }
  }
  // 超出 2xx 范围的状态码都会触发该函数。
  // 对响应错误做点什么
  return Promise.reject(error)
})

7.5动态渲染文章列表

7.6响应拦截器–简化响应

在这里插入图片描述

7.7分页渲染–list组件

首页获取了第一页数据,但显然不够,滑倒底部加载下一页的数据
在这里插入图片描述

// 触底触发事件
    async onLoad () {
      const res = await getArticles({
        current: this.current,
        sorter: this.sorter
      })
      // 需要在this.list基础上 累加res.data.rows
      // this.list = res.data.rows
      this.list.push(...res.data.rows)
      console.log(this.list)
      // console.log('可以请求更多数据')
      // 如果数据已经请求完毕  将loading改成false  才能加载下一页的数据
      // 一旦loading 改为ifalse load事件可以再次触发
      this.loading = false
      this.current++ // 当前页+1
      // 没有更多数据的处理
      if (this.current > res.data.pageTotal) {
        this.finished = true
      }
    }

7.8点击推荐 或 最新

  • 点击事件 传递不同值 推荐 weight_desc 最新 null

  • 重置数据,根据新条件,重新请求第一页数据

    this.current = 1
    this.list = []
    this.finished = false

  • 处理导航高亮

changeSorter (value) {
      // 修改排序规则(推荐/更新)
      this.sorter = value
      // 重置数据
      this.current = 1
      this.list = []
      this.finished = false
      //  标记需要开始加载了  因为我们是手动调用加载更多
      // 所以loading需要自己改为true 避免重复触发
      this.loading = true
      // 根据最新的条件重新渲染
      this.onLoad()
    }

7.9动态路由传参-跳转详情

配置动态路由----添加跳转–获取params参数----请求渲染详情

详情页结构

<template>
    <div class="detail-page">
      <van-nav-bar
        title="面经详情"
        left-text="返回"
        left-arrow
        @click-left="$router.back()"
      />
      <header class="header">
        <h1>大标题</h1>
        <p>
          2050-04-06 | 300 浏览量 | 222 点赞数
        </p>
        <p>
          <img src="头像" alt="" />
          <span>作者</span>
        </p>
      </header>
      <main class="body">
        <p>我是内容</p>
        <p>我是内容</p>
        <p>我是内容</p>
        <p>我是内容</p>
      </main>
      <div class="opt">
        <van-icon class="active" name="like-o"/>
        <van-icon name="star-o"/>
      </div>
    </div>
</template>

<script>
export default {
  name: 'RegisterName',
  created () {
    console.log(this.$route.params.id)
  }
}
</script>

<style lang="less" scoped>
.detail-page {
  overflow: hidden;
  padding: 0 15px;
  .header {
    h1 {
      font-size: 24px;
    }
    p {
      color: #999;
      font-size: 12px;
      display: flex;
      align-items: center;
    }
    img {
      width: 40px;
      height: 40px;
      border-radius: 50%;
      overflow: hidden;
    }
  }
  .opt {
    position: fixed;
    bottom: 100px;
    right: 0;
    > .van-icon {
      margin-right: 20px;
      background: #fff;
      width: 40px;
      height: 40px;
      line-height: 40px;
      text-align: center;
      border-radius: 50%;
      box-shadow: 2px 2px 10px #ccc;
      font-size: 18px;
      &.active {
        background: #FEC635;
        color: #fff;
      }
    }
  }
}
</style>

7.10点赞和收藏

封装接口------注册事件------调用接口请求------修改状态,修改文本,提示消息
article.js中封装接口

// 点赞&收藏
export const changeArticleOpt = (data) => {
  request.post('/interview/opt', {
    id: data.id,
    optType: data.optType
  })
}

articleDetail.vue详情页中创建点击事件

    <div class="opt">
      <van-icon :class="{ active: article.likeFlag }" name="like-o" @click="changeOpt(1)"></van-icon>
      <van-icon :class="{ active: article.collectFlag }" name="star-o" @click="changeOpt(2)"></van-icon>
    </div>
methods: {
    async changeOpt(val) {
      await changeArticleOpt({ id: this.article.id, optType: val })
      if (val === 1) {
        this.article.likeFlag = !this.article.likeFlag // 点赞状态取反
        console.log(this.article.likeFlag)
        if (this.article.likeFlag) {
          this.article.likeCount++
          this.$toast('点赞成功')
        } else {
          this.article.likeCount--
          this.$toast('取消点赞')
        }
      } else {
        this.article.collectFlag = !this.article.collectFlag // 收藏状态取反
        console.log(this.article.collectFlag)
        if (this.article.collectFlag) {
          this.$toast('收藏成功')
        } else {
          this.$toast('取消收藏')
        }
      }
    }
  }

7.11我的收藏

article.js中封装收藏接口方法

// 收藏列表
export const getCollection = (data) => {
  return request.get('/interview/opt/list', {
    params: {
      page: data.page || 1,
      pageSize: data.pageSize || 5,
      optType: 2
    }
  })
}

我的收藏页面collect.vue

<template>
  <div>
    <van-nav-bar title="我的收藏" />
    <van-list v-model="loading" :finished="finished" finished-text="没有更多了" @load="onLoad">
      <ArticleItem v-for="item in list" :key="item.id" :item=item></ArticleItem>
    </van-list>
  </div>
</template>

<script>
import { getCollection } from '@/api/article'
export default {
  name: 'MyCollect',
  data() {
    return {
      loading: false,
      finished: false,
      list: [],
      page: 1
    }
  },
  methods: {
    async onLoad() {
      const { data } = await getCollection({ page: this.page })
      this.list.push(...data.rows)
      this.loading = false
      console.log(data)
      this.page++
      console.log(this.page)
      console.log(data.pageTotal)
      if (this.page > data.pageTotal) {
        this.finished = true
      }
    }
  }
}
</script>

<style scoped lang="less">
.van-cell {
  .header {
    display: flex;
    height: 40px;
    align-items: center;

    .son {
      display: flex;
      flex-direction: column;
      font-size: 12px;

      p {
        line-height: 12px;
        margin: 2px 0;

        &.ut {
          color: #ccc;
        }
      }
    }

  }

  .content {
    color: gray;
    overflow: hidden;
    text-overflow: ellipsis;
    /* 弹性伸缩盒子模型显示 */
    display: -webkit-box;
    /* 限制在一个块元素显示的文本的行数 */
    -webkit-line-clamp: 2;
    /* 设置或检索伸缩盒对象的子元素的排列方式 */
    -webkit-box-orient: vertical;
  }
}
</style>

7.12喜欢

article.js接口中获取封装喜欢列表接口方法

// 喜欢列表
export const getLike = (data) => {
  return request.get('/interview/opt/list', {
    params: {
      page: data.page || 1,
      pageSize: data.pageSize || 5,
      optType: 1
    }
  })
}

like.vue喜欢列表页

<template>
  <div>
    <van-list>
      <ArticleItem v-for="item in list" :key="item.id" :item="item"></ArticleItem>
    </van-list>
  </div>
</template>

<script>
import { getLike } from '@/api/article'
export default {
  name: 'MyLike',
  data() {
    return {
      list: [],
      page: 1,
      pageType: 1,
      loading: false,
      finished: false
    }
  },
  async created() {
    const { data } = await getLike({ page: this.page })
    console.log(data)
    this.list.push(...data.rows)
  }
}
</script>

<style scoped></style>

7.13个人中心

  • 获取用户信息
  • 退出登录

user.js封装获取用户信息接口方法

// 用户信息获取
export const getUserInfo = () => {
  return request.get('/user/currentUser')
}

my.vue用户信息页面

<template>
  <div>
    <van-list>
      <ArticleItem v-for="item in list" :key="item.id" :item="item"></ArticleItem>
    </van-list>
  </div>
</template>

<script>
import { getLike } from '@/api/article'
export default {
  name: 'MyLike',
  data() {
    return {
      list: [],
      page: 1,
      pageType: 1,
      loading: false,
      finished: false
    }
  },
  async created() {
    const { data } = await getLike({ page: this.page })
    console.log(data)
    this.list.push(...data.rows)
  }
}
</script>

<style scoped></style>

8.打包发布

vue脚手架只是在开发过程中,协助开发的工具,当真正开发完了===》脚手架不参与上线

打包后,可以生成,浏览器能够直接运行的网页 ===》就是需要上线的源码

作用:

  • 将多个文件压缩合并成一个文件
  • 语法降级
  • less sass ts 语法解析

在这里插入图片描述
vue脚手架工具提供了打包命令,直接使用 yarn build npm run build

在项目的根目录会自动创建一个文件夹 dist dist中的文件就是打包后的文件,只需要放到服务器中即可
vue.config.js中配置

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  // 将资源访问路径从 / 配置成  ./ 相对路径
  publicPath: './',
  css: {
    loaderOptions: {
      less: {
        // 若 less-loader 版本小于 6.0,请移除 lessOptions 这一级,直接配置选项。
        lessOptions: {
          modifyVars: {
            // 直接覆盖变量
            blue: 'orange'
          }
        }
      }
    }
  }
})

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

mysql:[Some non-transactional changed tables couldn‘t be rolled back]不支持事务

1. mysql创建表时默认引擎MyIsam&#xff0c;因此不支持事务的操作&#xff1b; 2. 修改mysql的默认引擎&#xff0c;可以使用show engine命令查看支持的引擎&#xff1a; 【my.conf详情说明】my.cnf配置文件注释详解_xiaolin01999的博客-CSDN博客 3. 原来使用MyIsam创建的表…

微信小程序开发教学系列(12)- 实战项目案例

十二、实战项目案例 本章将通过一个简单的实战项目案例来帮助读者巩固之前学习到的知识。我们将搭建一个名为“ToDoList”的微信小程序&#xff0c;实现一个简单的任务清单功能。 项目介绍 ToDoList是一个用于记录和管理任务的小程序。用户可以添加、编辑、完成和删除任务&a…

springboot web开发springmvc自动配置原理

前言 我们也知道springboot启用springmvc基本不用做什么配置可以很方便就使用了但是不了解原理,开发过程中遇到点问题估计就比较头疼,不管了解的深不深入,先巴拉一番再说… 下面我们先看看官网…我的版本是2.3.2版本,发现官网改动也比较大…不同版本自己巴拉下吧,结构虽然变化…

Lesson4-2:OpenCV图像特征提取与描述---Harris和Shi-Tomas算法

学习目标 理解Harris和Shi-Tomasi算法的原理能够利用Harris和Shi-Tomasi进行角点检测 1 Harris角点检测 1.1 原理 H a r r i s Harris Harris角点检测的思想是通过图像的局部的小窗口观察图像&#xff0c;角点的特征是窗口沿任意方向移动都会导致图像灰度的明显变化&#xff…

java实现粤语歌曲0243填词法

粤语歌曲填词法 一、前言 转化成数字歌。对每个音符&#xff0c;提供配合广东话声调的字&#xff0c;选出成为歌词。可以在网上创作&#xff0c;或下载到自己电脑中使用。 简谱 3656536&#xff0c;歌词 落花满天蔽月光。 唱起来配合乐曲音调。这叫做‘叶韵’&#xff0c;又叫…

UE4 植物生长

这个可以改变SplineMesh朝向

android 输入法demo

背景&#xff1a; 一个简单的android输入法demo&#xff0c;支持输入png、gif&#xff0c;jpeg、webp等格式。 此示例演示如何编写一个应用程序&#xff0c;该应用程序接受使用 Commit Content API 从键盘发送的丰富内容&#xff08;例如图像&#xff09;。 用户通常希望通过表…

推荐一本AI+医疗书:《机器学习和深度学习基础以及医学应用》,附21篇精选综述

当代医学仍然存在许多亟待解决的问题&#xff0c;比如日益增加的成本、医疗服务水平的下降...但近几年AI技术的发展却给医疗领域带来了革命性的变化&#xff0c;因此AI医疗迅速兴起。 从目前已知的成果来看&#xff0c;人工智能在医学领域的应用已经相当广泛&#xff0c;智能诊…

AJAX学习笔记1发送Get请求

传统请求有哪些方式,及缺点 传统请求有哪些? 1.直接在浏览器地址栏上输入URL. 2.点击超连接. <a href"/上下文/请求地址">超链接请求</a> ---->相对路径 <a href"http://www.baidu.com">超链接请求</a> ---->绝对路…

【Python】PySpark

前言 Apache Spark是用于大规模数据&#xff08;large-scala data&#xff09;处理的统一&#xff08;unified&#xff09;分析引擎。 简单来说&#xff0c;Spark是一款分布式的计算框架&#xff0c;用于调度成百上千的服务器集群&#xff0c;计算TB、PB乃至EB级别的海量数据…

知识图谱实战应用26-基于知识图谱构建《本草纲目》的中药查询与推荐项目应用

大家好,我是微学AI,今天给大家介绍一下知识图谱实战应用26-基于知识图谱构建《本草纲目》的中药查询与推荐项目应用,本文通过Py2neo连接到知识图谱数据库,系统实现了中药的快速查询、关系分析、智能推荐和知识展示等功能。用户可以输入中药的名称或特征进行查询,系统将从知…

分页功能实现

大家好 , 我是苏麟 , 今天聊一聊分页功能 . Page分页构造器是mybatisplus包中的一个分页类 . Page分页 引入依赖 <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.1</ver…

【LeetCode每日一题】——274.H指数

文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【题目提示】七【解题思路】八【时间频度】九【代码实现】十【提交结果】 一【题目类别】 排序 二【题目难度】 中等 三【题目编号】 274.H指数 四【题目描述】 给你一个整数数组 ci…

linux系统中串口驱动框架基本分析(经典)

第一&#xff1a;区分不同的终端类型 串行端口终端&#xff08;/dev/ttySn&#xff09; 串行端口终端&#xff08;Serial Port Terminal&#xff09;是使用计算机串行端口连接的终端设备。计算机把每个串行端口都看作是一个字符设备。 有段时间这些串行端口设备通常被称为终…

Python:列表推导式

相关阅读 Python专栏https://blog.csdn.net/weixin_45791458/category_12403403.html?spm1001.2014.3001.5482 列表推导式使得创建特定列表的方式更简洁。常见的用法为&#xff0c;对序列或可迭代对象中的每个元素应用某种操作&#xff0c;用生成的结果创建新的列表&#xff…

Python—匹配字段

1. 「概述」 在日常开发中&#xff0c;经常需要对数据中的某些字段进行匹配&#xff0c;但这些字段可能存在微小的差异。例如&#xff0c;同一个招聘岗位的数据中&#xff0c;省份字段可能有“广西”、“广西壮族自治区”和“广西省”等不同的写法。为了处理这些情况&#xff…

(数字图像处理MATLAB+Python)第十章图像分割-第四,五节:分水岭分割和综合案例

文章目录 一&#xff1a;分水岭分割&#xff08;1&#xff09;原理&#xff08;2&#xff09;程序 二&#xff1a;综合案例&#xff1a;答题卡图像分割&#xff08;1&#xff09;设计思路&#xff08;2&#xff09;各模块设计&#xff08;3&#xff09;代码 一&#xff1a;分水…

three.js(二):webpack + three.js + ts

用webpackts 开发 three.js 项目 webpack 依旧是主流的模块打包工具;ts和three.js 是绝配&#xff0c;three.js本身就是用ts写的&#xff0c;ts可以为three 项目提前做好规则约束&#xff0c;使项目的开发更加顺畅。 1.创建一个目录&#xff0c;初始化 npm mkdir demo cd de…

第五章 树与二叉树 二、二叉树的定义和常考考点,WPL的算法

一、定义 二叉树可以用以下方式详细定义&#xff1a; 二叉树是由节点构成的树形结构&#xff0c;每个节点最多可以有两个子节点。每个节点有以下几个属性&#xff1a; 值&#xff1a;存储该节点的数据。左子节点&#xff1a;有一个左子节点&#xff0c;如果没有则为空。右子节…

Visual Studio 2017安装和项目配置

目录 前言1. What、Why and How1.1 What1.2 Why1.3 How 2. 安装3. 创建新项目4. 配置OpenCV库4.1 下载opencv安装包4.2 配置系统环境变量4.3 VS项目环境配置4.4 总结 5. 已有项目添加6. Tips6.1 常用快捷键6.2 字体和颜色选择6.3 配置编译路径 结语下载链接参考 前言 最近因为项…