vue3.0 学习使用记录

1|0vue学习


在最近的一次项目中,前端js框架里使用了vue。vue的编程思想比较新颖,用起来也感觉高效便捷。由于个人原因,做完这个项目之后可能就接触不到前端的内容了,所以记录这个项目中对vue的学习和理解。对自己的要求是可以不记得具体的技术,但是要记住这个框架的思想。

2|0vue简介


vue是一个JavaScript框架,最大的特点是响应式
响应式原理:意思就是在改变数据的时候,视图会跟着更新
对比jquery来说,jquery是通过语法操作html中的标签,从而改变标签的属性,值等。而vue是需要改变的html标签绑定一个变量,当变量发生变化时html中的标签的值也发生变化。

3|0vue3.0安装


3|11. 安装node


sudo tar xf node-v14.16.1-linux-x64.tar.xz -C /opt cd /opt/node-v14.16.1-linux-x64/bin sudo ln -s /opt/node-v14.16.1-linux-x64/bin/node /usr/local/bin/node sudo ln -s /opt/node-v14.16.1-linux-x64/bin/npm /usr/local/bin/npm # 验证版本 node -v npm -v

3|22. 装淘宝镜像


npm install -g cnpm --registry=https://registry.npm.taobao.org sudo ln -s /opt/node-v14.16.1-linux-x64/bin/cnpm /usr/local/bin/cnpm cnpm -v

3|33. vue环境安装


cnpm -g vue @vue/cli sudo ln -s /opt/node-v14.16.1-linux-x64/bin/vue /usr/local/bin/vue vue -V

vue3.0要求4.5以上的版本

3|44. 创建新项目


vue create todolist

启动项目

访问页面

4|0vue 项目架构


一个新建的vue项目架构如下:

assets: 存放静态资源、图标、图片
components:存放一般组件,公共组件,通用组件
router:配置路由。vue中实现页面跳转需要定义的路由
sotre: 配置状态管理
views:vue 主要业务实现的位置
App.vue:页面的入口文件,通常是入口页面。上面的首页就是该文件中的。

4|1组件


组件是vue功能的集合。可以把每一个.vue文件看成一个组件,包括App.vue也是一个组件,一个关于主页面的组件。组件的结构由三部分组成:

  1. template
  2. script
  3. style
<template> </template> <script> </script> <style scoped lang="scss"> </style>

4|2组件结构


一个组件包括很多内容,大体上可以分为:

  1. defineComponent 引入
  2. 子组件引入(可选)
  3. 组件定义
  • 组件名称
  • 接收父组件的数据(可选)
  • 定义子组件(可选)
  • setup 定义变量和函数

setup中定义变量和函数,最后都要通过return返回,只有return中返回的变量才能被页面上响应。

//------------------------数据的展示------------------------ <template> </template> //--------------------------数据的定义和返回--------------------- <script> // 所有的组件都需要从vue中定义 import {defineComponent} from 'vue' import NavHeader from '@/components/navHeader/NavHeader' // 调用defineComponent中的组件 export default defineComponent({ name: 'Home', // 组件名称 // 接收父组件的数据 props: { }, // 定义子组件 components:{ }, setup(props, ctx) { // 数字 let num = ref(10) return { num } } }) </script> <style scoped lang='scss'> </style>

4|3数据结构


vue中常见的数据结构包括:

  • 数字
  • 字符串
  • 字典
  • 数组

ref 用来定义响应式变量,只可以定义单个变量
reactive 用来打包定义变量,可以定义多个变量

数据定义 //------------------------数据的展示------------------------ <template> <div> <nav-header></nav-header> <nav-main></nav-main> <nav-footer></nav-footer> {{ data.num }} {{ data.name }} {{ data.arr.slice(0,2) }} {{ data.obj }} </div> </template> //--------------------------数据的定义和返回--------------------- <script> // 所有的组件都需要从vue中定义 import {defineComponent, ref reactive} from 'vue' // 调用defineComponent中的组件 export default defineComponent({ name: 'Home', // 组件名称 // 接收父组件的数据 props: { }, // 定义子组件 components:{ NavHeader, NavMain, NavFooter }, setup(props, ctx) { // 数字 let num = ref(10) // 字符串 let name = ref('jack') // 数组 let arr = ref(['a', 'b', 'c', 'd']) // 字典 let obj = ref({age: 20}) // reactive 方法 let data = reactive({ name: 'jack', age: 20, ojb: { price: 20 }, arr: ['a', 'b', 'c', 'd'] }) return { data } } }) </script> <style scoped lang='scss'> </style>

在实际的编程过程中,似乎不需要用关键字refreactive。如在未来网络学院的开发过程中,一个vue文件定义的相应式变量如下:

return { tableConfig: { config: tableConfigBase(), tableData: [], selectedRows: [], }, createModal: { visible: false }, createForm: { dialog_title: '添加讲师', name: '', title: '', profile: '', img: [], }, searchForm: { keywords: '' }, createRules: { name: [ { required: true, message: '请输入名称', trigger: 'change' }, { min: 2, max: 20, message: '长度在 2~20 个字符内', trigger: 'change' }, {validator: nameUniqueAcq, trigger: 'blur'}, {validator: urlAcq, trigger: 'blur'}, ], title: [ { required: true, message:'请输入头衔', trigger: 'change' }, { min: 1, max: 500, message: '长度在 2~500 个字符内', trigger: 'change' }, ], profile: [ { required: false, message: '长度在 200 个字符内', trigger: 'change' }, ], img: [ { required: true, message: '请上传图片', trigger: 'change'} ], }, pager:{}, disabledDel: 'disabled', disableDis: 'disabled', disableEn: 'disabled', }

5|0vue基础语法


5|1指令


Vue.js的指令是以v-开头的,它们作用于HTML元素,指令提供了一些特殊的特性,将指令绑定在元素上时,指令会为绑定的目标元素添加一些特殊的行为,我们可以将指令看作特殊的HTML特性(attribute)。

作用
指令的作用是当表达式的值改变时,相应地将某些行为应用到 DOM 上。

v-if
v-if可以实现条件渲染,Vue会根据表达式的值的真假条件来渲染元素。

<a v-if="ok">yes</a>

如果属性值ok为true,则显示。否则,不会渲染这个元素。

v-else
v-else是搭配v-if使用的,它必须紧跟在v-if或者v-else-if后面,否则不起作用。

<div>ok的值为:{{ ok }}</div> <div v-if='ok'>如果值为true显示</div> <div v-else>如果值为false显示</div>

v-for
用v-for指令根据遍历数组来进行渲染

两种渲染方式

<div v-for="(item,index) in items"></div> //使用in,index是一个可选参数,表示当前项的索引 <div v-for="item of items"></div> //使用of
let list = ref([11,23,34,45,56]) <div v-for='(index, item) in list'> <span>{{ item }}--{{ index }}</span> </div>

v-model
这个指令用于在表单上创建双向数据绑定。限制在<input><select><textarea>components中使用

<input v-model='input_value' @keydown.enter="enter"/>
let input_value = ref('') let enter = () => { console.log(input_value.value) }

![image_1f5i6uiup1irig8hr8pdd4fr2q.png-21.3kB][15]

<1> lazy 默认情况下,v-model同步输入框的值和数据。可以通过这个修饰符,转变为在change事件再同步。

<input v-model.lazy="msg">

<2> number 自动将用户的输入值转化为数值类型

<input v-model.number="msg">

<3> trim:自动过滤用户输入的首尾空格

<input v-model.trim="msg">

v-on
v-on主要用来监听dom事件,以便执行一些代码块。表达式可以是一个方法名。
简写为:@

<button @click='change_ok'>点击按钮</button> let change_ok = () => { console.log('00000') ok.value = !ok.value }

<!-- 阻止单击事件继续传播 --> <a v-on:click.stop="doThis"></a> <!-- 提交事件不再重载页面 --> <form v-on:submit.prevent="onSubmit"></form> <!-- 修饰符可以串联 --> <a v-on:click.stop.prevent="doThat"></a> <!-- 只有修饰符 --> <form v-on:submit.prevent></form> <!-- 添加事件监听器时使用事件捕获模式 --> <!-- 即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理 --> <div v-on:click.capture="doThis">...</div> <!-- 只当在 event.target 是当前元素自身时触发处理函数 --> <!-- 即事件不是从内部元素触发的 --> <div v-on:click.self="doThat">...</div> <!-- 点击事件将只会触发一次 --> <a v-on:click.once="doThis"></a> <!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 --> <!-- 而不会等待 `onScroll` 完成 --> <!-- 这其中包含 `event.preventDefault()` 的情况 --> <div v-on:scroll.passive="onScroll">...</div>

v-bind
v-bind用来动态的绑定一个或者多个特性。没有参数时,可以绑定到一个包含键值对的对象。常用于动态绑定class和style。以及href等。
简写为一个冒号

<a v-bind:href='herf'>百度</a>

<img :src='img_url' alt='leishen'> let img_url = ref('https://image-1300284638.cos.ap-nanjing.myqcloud.com/leishen.jpeg')

常用的v-bind标签

  • v-bind:style
  • v-bind:title
  • v-bind:src

v-html
双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML ,你需要使用 v-html 指令:

<div v-html="rawHtml"></div>

这个 div 的内容将会被替换成为属性值 rawHtml,直接作为 HTML——会忽略解析属性值中的数据绑定。

5|2动作监听


动作监听的流程:

  1. 标签上定义监听函数 @click='监听函数名'
  2. setup中实现监听函数
  3. setup中return监听函数
<template> <!-- <one></one> --> <button @click='alert_action'>点击事件</button> </template> <script> import {defineComponent, ref, reactive, computed} from 'vue' import one from '@/components/one/One' export default defineComponent({ name: 'Main', // 组件名称 components:{ one }, setup() { let alert_action = () => { alert('你点击了我') } return { alert_action } } }) </script> <style scoped lang="scss"> </style>

6|0vue全局使用


6|1引用组件


子组件可以定义在components中,而views中往往定义父组件。在父组件中使用子组件的流程为:

  1. 子组件定义
<template> <div>这是子组件</div> </template> <script> import {defineComponent, ref, reactive, computed} from 'vue' export default defineComponent({ name: 'One', // 组件名称 setup() { } }) </script> <style scoped lang="scss"> </style>
  1. 父组件定义
<template> <one></one> </template> <script> import {defineComponent, ref, reactive, computed} from 'vue' // 从components中的one文件夹下的One.vue中引入 import one from '@/components/one/One' export default defineComponent({ name: 'Main', // 组件名称 // 组件本地化 components:{ one }, setup() { } }) </script> <style scoped lang="scss"> </style>

6|2父子组件中传递数据


  1. 父组件传递给子组件

在父组件使用的子组件中加入参数传递:num='num'

<template> <one :num='num'></one> </template> <script> import {defineComponent, ref, reactive, computed} from 'vue' import one from '@/components/one/One' export default defineComponent({ name: 'Main', // 组件名称 components:{ one }, setup() { let alert_action = () => { alert('你点击了我') } let num = ref(100) return { alert_action, num } } }) </script> <style scoped lang="scss"> </style>

子组件中props用来接收父组件的传参,定义好变量,然后直接使用

<template> <div>这是子组件</div> <div>父组件传递过来的是: {{ num }}</div> </template> <script> import {defineComponent, ref, reactive, computed} from 'vue' export default defineComponent({ name: 'One', // 组件名称 props: { num:{ type: Number } }, setup(props) { } }) </script> <style scoped lang="scss"> </style>

  1. 子组件传递给父组件

子组件传值给父组件叫事件分发。通过ctx.emit分发事件

  1. 子组件
<template> <div>这是子组件</div> <div>父组件传递过来的是: {{ num }}</div> <button @click='send'>点击传递参数</button> </template> <script> import {defineComponent, ref, reactive, computed} from 'vue' export default defineComponent({ name: 'One', // 组件名称 props: { num:{ type: Number } }, setup(props, ctx) { let send = () => { // 使用事件分发 ctx.emit("send", 200) } return { send } } }) </script> <style scoped lang="scss"> </style>

父组件

<template> // 父组件接收send事件,将其在send_father函数中处理 <one :num='num' @send='send_father'></one> <div>父组件收到的子组件的传参: {{ recv_value }}</div> </template> <script> import {defineComponent, ref, reactive, computed} from 'vue' import one from '@/components/one/One' export default defineComponent({ name: 'Main', // 组件名称 components:{ one }, setup() { let alert_action = () => { alert('你点击了我') } let num = ref(100) let recv_value = ref(0) let send_father = (val) => { recv_value.value = val } return { alert_action, num, send_father, recv_value } } }) </script> <style scoped lang="scss"> </style>

7|0全局共享变量之状态管理


在store中的index.js中可以定义全局使用的变量和方法。全局使用指的是所有组件可以修改,共享使用。

使用这些变量或者函数的方法是:

import {useStore} from 'vuex' setup(props, ctx) { let store = useStore() // store.commit('addTodo',{ title: value.value, complete: false }

8|0路由


在router文件夹下存放着vue的路由信息

路由就是页面的静态路由。

根路由:每一个vue项目都有一个根路由,该路由的主要作用是页面的默认路由。

{ path: '/', name: 'Start', component: Start },

path: 路由路径
name:路由的名字
component: 该路由对应的组件。该组件必须先引入进来,并且是只需要显示引入的。其他组件由于不需要立刻显示,所以使用懒加载,即不立即加载到vue项目中。

其他路由的加载

{ path: '/home', name: 'Home', component: () => import('../views/Home.vue') },

路由的使用

import {useRouter} from 'vue-router'
setup(props, ctx) { // router是全局路由对象 let router = useRouter() let start = () =>{ // 使用push的方式,跳转路由 router.push({ // 路由的目的地可以用name:模块 name:'Home', // 也可以是path:路径。两者二选一 path: '/home' }) } }

8|1路由的传参


路由的传参有两种方式,分别是

  1. query 类似于get,显示传参,地址栏可以看到参数,刷新保存参数
  2. params 类似于post,地址栏看不到参数,刷新不保存参数

query

setup(props, ctx) { // router是全局路由对象 let router = useRouter() let start = () =>{ // 使用push的方式,跳转路由 router.push({ name:'Home', query:{ name: name.value, num: num.value, } }) } }

使用

import {useRouter, useRoute} from 'vue-router' // route是当前路由对象 let route = useRoute() console.log(route.query)

有一点需要注意数字类型的参数会变成字符串类型

params
params传参只能用name来路由

let start = () =>{ router.push({ name:'Home', params: { name: name.value, num: num.value, } }) }

接收参数:

import {useRouter, useRoute} from 'vue-router' // route是当前路由对象 let route = useRoute() console.log(route.params)

9|0插槽


定义
插槽就是子组件中的提供给父组件使用的一个占位符,用 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的标签。

https://www.cnblogs.com/mandy-dyf/p/11528505.html

10|0vue2 和vue3的区别


建立数据 data
这里就是Vue2与Vue3 最大的区别 — Vue2使用选项类型API(Options API)对比Vue3合成型API(Composition API)

选项类型
旧的选项型API在代码里分割了不同的属性(properties):data,computed属性,methods
合成类型
新的合成型API能让我们用方法(function)来分割,相比于旧的API使用属性来分组,这样代码会更加简便和整洁。

vue2

export default { props: { title: String }, data () { return { username: '', password: '' } }, methods: { login () { // 登陆方法 } } }

Vue2 的选项型API是把methods分割到独立的属性区域的。我们可以直接在这个属性里面添加方法来处理各种前端逻辑。

vue3

export default { props: { title: String }, setup () { const state = reactive({ username: '', password: '' }) const login = () => { // 登陆方法 } return { login, state } } }

Vue3 的合成型API里面的setup()方法也是可以用来操控methods的。创建声名方法其实和声名数据状态是一样的。— 我们需要先声名一个方法然后在setup()方法中返回(return), 这样我们的组件内就可以调用这个方法了。

11|0项目代码结构


所有的vue代码都写在views当中
公共组件存放在components中
有关网络请求的axios都存放在network中
页面跳转路由存放在router中

12|0vue在实际项目中的使用技巧


12|1vue与后端交互


vue通过 axios 与后端交互。通过引入axios中的各种方法,完成网络请求

import { fetch, post, del, postForm } from '../base/axios' const URL = { listUrl: '/page/list/', createUrl: '/page/create/', delUrl: '/page/delete/', disableUrl: '/page/disable/', enableUrl: '/page/enable/', pageStateChange: '/page/page_state_change/', getFiles: '/page/get_files/' } export function pageList (data) { return fetch(URL.listUrl, data) } export function pageCreate(form) { return postForm(URL.createUrl, form) } export function pageDelete(page_id) { return del(URL.delUrl + page_id + '/') } export function pageDisable(data) { return fetch(URL.disableUrl, data) } export function pageEnable(data) { return fetch(URL.enableUrl, data) } export function pageStateChange(data) { return fetch(URL.pageStateChange, data) } export function pageGetFiles(page_id) { return fetch(URL.getFiles + page_id + '/') }

普通post请求:

export function post (url, data = {}) { return new Promise((resolve, reject) => { // var qs = require('querystring') axios.create({ headers: {'X-CSRFToken': getCookie('csrftoken'), 'Content-Type': 'application/x-www-form-urlencoded'}, }).post(url, data).then(response => { resolve(response.data) }, err => { reject(err) }) }) }

form-data的请求

export function postForm (url, data= {}) { return new Promise((resolve, reject) => { axios.create({ withCredentials: true, headers: {'X-CSRFToken': getCookie('csrftoken'), 'Content-Type': "multipart/form-data"}, }).post(url, data).then(response => { resolve(response.data) }, err => { reject(err) }) }) }

在vue文件中的网络请求为:

import { pageList, pageDelete, pageDisable, pageEnable, pageCreate, pageStateChange, pageGetFiles } from 'api/page/index' pageList(data).then((res =>{ this.tableConfig.tableData = res.data; this.pager.total = res.total })).catch(err => { this.$alert(`${ err }`, '提示', { confirmButtonText: '确定', }); });

12|2vue 导入组件和方法


vue使用的过程中需要导入组件或者方法,方法如axios请求。导入的语法是:

  • 导入组件需要使用大括号
  • 导入方法需要用大括号包裹
import { useRouter } from 'vue-router' import { tableConfigBase } from 'utils/common.js' import { pageList, pageDelete, pageDisable, pageEnable, pageCreate, pageStateChange, pageGetFiles } from 'api/page/index' import { showConfirmMessageBox, showMessage } from 'api/base/message' import UploadFile from 'components/common/UploadFile' import Pagination from 'components/common/Pagination'

导入组件是从别的文件中导入组件,除需要使用大括号之外,还需要本地引入

export default { components: { UploadFile, Pagination }, ..... }

导入方法指的是从js文件中能够导入一个函数。如 showConfirmMessageBox,就是:

export function showConfirmMessageBox (message) { return ElMessageBox.confirm(message, '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning', center: true }) }

vue属于js的一个库,理所当然可以使用js。想要引用一个js,需要js的函数export

12|3vue异步变同步的方法


axios是异步请求,如果想要将异步变成同步,使用asyncawait两个关键字即可。
async 修饰 vue函数
await 修饰 axios请求方法

async editRow(index, row){ this.createForm.name = row.name this.createForm.desc = row.desc this.createForm.page_url = row.page_url this.createForm.edit = true this.createForm.page_id = row.id await pageGetFiles(row.id).then((res => { if (res.result == 0) { for (var i = 0; i < res.page_files.length; i++) { this.createForm.file.push({'page_file_id': res.page_files[i].id, 'name': res.page_files[i].name}) } } })) this.createModal.visible = true },

12|4vue中formdata的使用


formdata 用于有静态资源从vue传输到django中,如图片和文件等。使用如下:
创建: var data = new FormData()
添加:

data.append('name', this.createForm.name) data.append('desc', this.createForm.desc) data.append('page_url', this.createForm.page_url) data.append('edit', this.createForm.edit) data.append('page_id', this.createForm.page_id)

特别注意,如果添加文件也是使用中格式
data.append('new_files', file.raw)
如果添加多个文件,那么直接用同一个key,会被打包成列表
取值:data.get(key)
如果value是一个数组,取值方法: data.getAll(key)

vue代码

var data = new FormData(); data.append('name', this.createForm.name) data.append('desc', this.createForm.desc) data.append('page_url', this.createForm.page_url) data.append('edit', this.createForm.edit) data.append('page_id', this.createForm.page_id) this.createForm.file.forEach((file) => { if (file.raw) { data.append('new_files', file.raw) }else{ data.append('old_files', file.page_file_id) } })
export function postForm (url, data= {}) { return new Promise((resolve, reject) => { axios.create({ withCredentials: true, headers: {'X-CSRFToken': getCookie('csrftoken'), 'Content-Type': "multipart/form-data"}, }).post(url, data).then(response => { resolve(response.data) }, err => { reject(err) }) }) }
export function pageCreate(form) { return postForm(URL.createUrl, form) }
pageCreate(data)

django的接收:

# 接收到formdata的出文件之外的数据 data = request.POST # 接收文件,getlist是接收多个文件 get是接收单个文件 new_files = request.FILES.getlist('new_files')

12|5vue校验


在input输入框中需要一些校验,以下面的demo为例

<el-dialog title="添加页面" v-model="createModal.visible" width="800px" :before-close="closeDialog"> <div class="demo-dialog"> <el-form :model="createForm" :rules="createRules" ref="createForm" label-width="100px"> <el-form-item label="名称" prop="name"> <el-input v-model="createForm.name"></el-input> </el-form-item> <el-form-item label="描述" prop="desc"> <el-input v-model="createForm.desc"></el-input> </el-form-item> <el-form-item label="网址" prop="page_url"> <el-col> <el-input v-model="createForm.page_url" > <template #prepend>page/</template> </el-input> </el-col> </el-form-item> <el-form-item label="页面文件" prop="file"> <upload-file :allowed-type="['html']" v-model:file-list="createForm.file" :multiple="true">支持上传单个或多个html文件 </upload-file> </el-form-item> </el-form> </div> <template #footer> <span class="dialog-footer"> <el-button @click="submitCancel">取 消</el-button> <el-button type="primary" @click="submitForm('createForm')">确 定</el-button> </span> </template> </el-dialog>

校验规则

createRules: { position: [ { required: true, message: '请选择位置', trigger: 'change' }, ], name: [ { required: true, message: '请输入认证名称', trigger: 'change' }, { min: 2, max: 50, message: '长度在 2~50 个字符内', trigger: 'change' }, ], desc: [ { required: false, max: 200, message: '长度在 200 个字符内', trigger: 'change' }, ], page_url: [ { required: true, message: '请填写链接', trigger: 'change' }, { min: 1, max: 50, message: '长度在 1~50 个字符内', trigger: 'change' }, {validator: urlAcq, trigger: 'change'} ], file: [ { required: true, message: '请上传html文件', trigger: 'change' }, {validator: indexHtmlAcq, trigger: 'change'} ] },

自定义校验 上传文件包含index.html

const indexHtmlAcq = (rule, files, callback) => { let index_html_num = 0 files.forEach((file) =>{ if(file.name == 'index.html'){ index_html_num = index_html_num + 1 } }) if(index_html_num == 0){ callback(new Error('必须添加一个index.html文件')) }else if(index_html_num > 1){ callback(new Error('只能添加一个index.html文件')) } return callback() }

自定义校验 输入框中只允许输入数字字母-_

const urlAcq = (rule, str, callback) =>{ const reg =/^[-_a-zA-Z0-9]+$/; if(!reg.test(str)){ callback(new Error('url中包含特殊字符')) } return callback() }

12|6清空校验的红色提示


this.$nextTick(() => { this.$refs["createForm"].clearValidate() })

__EOF__

本文作者goldsunshine
本文链接https://www.cnblogs.com/goldsunshine/p/14892580.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   金色旭光  阅读(415)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示