Äú¿ÉÒÔ¾èÖú£¬Ö§³ÖÎÒÃǵĹ«ÒæÊÂÒµ¡£

1Ôª 10Ôª 50Ôª





ÈÏÖ¤Â룺  ÑéÖ¤Âë,¿´²»Çå³þ?Çëµã»÷Ë¢ÐÂÑéÖ¤Âë ±ØÌî



  ÇóÖª ÎÄÕ ÎÄ¿â Lib ÊÓÆµ iPerson ¿Î³Ì ÈÏÖ¤ ×Éѯ ¹¤¾ß ½²×ù Model Center   Code  
»áÔ±   
   
 
     
   
 ¶©ÔÄ
  ¾èÖú
×îÈ«µÄVue3.0Éý¼¶Ö¸ÄÏ
 
×÷ÕߣºÂÀСÃù
  2306  次浏览      28
 2021-3-10 
 
±à¼­ÍƼö:
±¾ÎĽ«»áÈ«·½Î»µÄ½éÉÜVue3µÄй¦ÄÜ£¬ÐÂÓÅ»¯£¬ÐÂÌØÐÔ£¬ÒÔ¼°Éý¼¶Ö¸ÄÏ¡£
±¾ÎÄÀ´×ÔÓÚĽ¿Î,ÓÉ»ðÁú¹ûÈí¼þAnna±à¼­ÍƼö¡£

Vue3»á´øÀ´Ð©Ê²Ã´£¿

¸ü¿ì

¸üС

¸üÒ×ÓÚά»¤

й¦ÄܺÍÌØÐÔ

¸ü¿ì

ÖØ¹¹ÁËVirtual DOM

Vue3ÖØÐ´ÁËÐéÄâDOMµÄʵÏÖ·½·¨£¬³õʼäÖȾ/¸üпÉÒÔÌáËÙ´ï100%¡£

¶ÔÓÚVue2.x°æ±¾µÄÐéÄâDOMÀ´Ëµ£¬Vue»á±éÀú<template>Ä£°åÖеÄËùÓÐÄÚÈÝ£¬²¢¸ù¾ÝÕâЩ±êÇ©Éú³É¶ÔÓ¦µÄÐéÄâDOM£¨ÐéÄâDOMÒ»°ãÖ¸²ÉÓÃkey/value¶ÔÏóÀ´±£´æ±êÇ©ÔªËØµÄÊôÐÔºÍÄÚÈÝ£©£¬µ±ÓÐÄÚÈݸıäʱ£¬±éÀúÐéÄâDOMÀ´diffÕÒµ½¶ÔÓ¦µÄ±êÇ©ÔªËØËù¶ÔÓ¦µÄDOM½Úµã£¬²¢¸Ä±äÆäÄÚÈÝ¡£ÀýÈçÏÂÃæÕâ¶ÎÄÚÈÝ£º

<template>
<div class="content">
<p>number1</p>
<p>number2</p>
<p>number3</p>
<p>{{count}}</p>
</div>
</template>

µ±´¥·¢Ë«Ïò°ó¶¨Ê±£¬±éÀúËùÓеÄ<div>±êÇ©ºÍ<p>±êÇ©£¬ÕÒµ½{{count}}±äÁ¿¶ÔÓ¦µÄ<p>µÄDOM½Úµã£¬²¢¸Ä±äÆäÄÚÈÝ¡£Õâ¶ÔÓÚÄÇЩ´¿¾²Ì¬<p>µÄ½Úµã½øÐÐdiffÆäʵÊDZȽÏÀË·Ñ×ÊÔ´µÄ£¬µ±½ÚµãµÄÊýÁ¿ºÜÉÙʱ£¬±íÏÖ²¢²»Ã÷ÏÔ£¬µ«ÊÇÒ»µ©½ÚµãµÄÊýÁ¿¹ý´ó£¬ÔÚÐÔÄÜÉϾͻáÂýºÜ¶à¡£¶Ô´Ë£¬Vue3Ôٴλù´¡ÉϽøÐÐÁËÓÅ»¯Ö÷ÒªÓУº

±ê¼Ç¾²Ì¬ÄÚÈÝ£¬²¢Çø·Ö¶¯Ì¬ÄÚÈÝ¡£

¸üÐÂʱֻdiff¶¯Ì¬µÄ²¿·Ö¡£

Õë¶ÔÉÏÃæµÄ´úÂ룬Vue3ÖÐÊ×ÏÈ»áÇø·Ö³ö{{count}}Õⲿ·Ö¶¯Ì¬µÄ½Úµã£¬ÔÚ½øÐÐdiffʱ£¬Ö»Õë¶ÔÕâЩ½Úµã½øÐУ¬´Ó¶ø¼õÉÙ×ÊÔ´ÀË·Ñ£¬ÌáÉýÐÔÄÜ£¬¾ßÌåÕⲿ·ÖÂß¼­¿ÉÒԲο¼Ô´Âë¡£

ʼþ»º´æ

ÎÒÃÇÖªµÀÔÚvue2ÖУ¬Õë¶Ô½Úµã°ó¶¨µÄʼþ£¬Ã¿´Î´¥·¢¶¼ÒªÖØÐÂÉú³ÉȫеÄfunctionÈ¥¸üС£ÔÚVue3ÖУ¬ÌṩÁËʼþ»º´æ¶ÔÏócacheHandlers£¬µ±cacheHandlers¿ªÆôµÄʱºò£¬±àÒë»á×Ô¶¯Éú³ÉÒ»¸öÄÚÁªº¯Êý£¬½«Æä±ä³ÉÒ»¸ö¾²Ì¬½Úµã£¬ÕâÑùµ±Ê¼þÔٴδ¥·¢Ê±£¬¾ÍÎÞÐèÖØÐ´´½¨º¯ÊýÖ±½Óµ÷Óûº´æµÄʼþ»Øµ÷·½·¨¼´¿É¡£

¿ªÆôcacheHandlers£º

import { createVNode as _createVNode, toDisplayString as _toDisplayString, openBlock as _openBlock, createBlock as _createBlock } from "vue"

const _hoisted_1 = { id: "app" }
export function render(_ctx, _cache) {
return (_openBlock(), _createBlock("div", _hoisted_1, [
_createVNode("button", {
onClick: _cache[1] || (_cache[1] = $event => (_ctx.confirmHandler($event)))
}, "È·ÈÏ"),
_createVNode ("span", null, _toDisplayString (_ctx.vue3), 1 /* TEXT */)
]))
}

¹Ø±ÕcacheHandlers£º

import { createVNode as _createVNode, toDisplayString as _toDisplayString, openBlock as _openBlock, createBlock as _createBlock } from "vue"

const _hoisted_1 = { id: "app" }
export function render(_ctx, _cache) {
return (_openBlock(), _createBlock("div", _hoisted_1, [
_createVNode("button", { onClick: _ctx.confirmHandler }, "È·ÈÏ", 8 /* PROPS */, ["onClick"]),
_createVNode("span", null, _toDisplayString(_ctx.vue3), 1 /* TEXT */)
]))
}

»ùÓÚProxyµÄÏìӦʽ¶ÔÏó

Proxy API¶ÔÓ¦µÄProxy¶ÔÏóÊÇES2015¾ÍÒÑÒýÈëµÄÒ»¸öÔ­Éú¶ÔÏó£¬ÓÃÓÚ¶¨Òå»ù±¾²Ù×÷µÄ×Ô¶¨ÒåÐÐΪ£¨ÈçÊôÐÔ²éÕÒ¡¢¸³Öµ¡¢Ã¶¾Ù¡¢º¯Êýµ÷Óõȣ©¡£

´Ó×ÖÃæÒâ˼À´Àí½â£¬Proxy¶ÔÏóÊÇÄ¿±ê¶ÔÏóµÄÒ»¸ö´úÀíÆ÷£¬ÈκζÔÄ¿±ê¶ÔÏóµÄ²Ù×÷£¨ÊµÀý»¯£¬Ìí¼Ó/ɾ³ý/ÐÞ¸ÄÊôÐԵȵȣ©£¬¶¼±ØÐëͨ¹ý¸Ã´úÀíÆ÷¡£Òò´ËÎÒÃÇ¿ÉÒÔ°ÑÀ´×ÔÍâ½çµÄËùÓвÙ×÷½øÐÐÀ¹½ØºÍ¹ýÂË»òÕßÐ޸ĵȲÙ×÷¡£ÀýÈçÏÂÃæµÄʾÀý£º

let foo = {
a:1,
b:2
}
let handler = {
set:(obj,key,value)=>{
console.log('set')
obj[key] = value
return true
}
}

let p = new Proxy(foo,handler)
p.a = 3 // ´òÓ¡³öconsole.log('set')

ÔÚVue2.xÖУ¬Ê¹ÓÃObject.defineProperty()À´ÊµÏÖÏìӦʽ¶ÔÏ󣬶ÔÓÚһЩ¸´ÔӵĶÔÏ󣬻¹ÐèҪѭ»·µÝ¹éµÄ¸øÃ¿¸öÊôÐÔÔö¼ÓÉÏgetter/setter¼àÌýÆ÷£¬ÕâʹµÃ×é¼þµÄ³õʼ»¯·Ç³£ºÄʱ£¬¶øVue3ÖУ¬composition-apiÌṩÁËÒ»ÖÖ´´½¨ÏìӦʽ¶ÔÏóµÄ·½·¨reactive£¬ÆäÄÚ²¿¾ÍÊÇÀûÓÃÁËProxy APIÀ´ÊµÏֵģ¬ÕâÑù¾Í¿ÉÒÔ²»ÓÃÕë¶Ôÿ¸öÊôÐÔÀ´Ò»Ò»½øÐÐÌí¼Ó£¬¼õÉÙ¿ªÏúÌáÉýÐÔÄÜ¡£

¸üС

Tree shakingÖ§³Ö

Tree shakingÊÇÒ»¸öÊõÓͨ³£ÓÃÓÚÃèÊöÒÆ³ýJavaScriptÉÏÏÂÎÄÖеÄδÒýÓôúÂë(dead-code)£¬¾ÍÏñÒ»¿Ã´óÊ÷£¬½«ÄÇЩÎÞÓõÄÒ¶×Ó¶¼Ò¡µô¡£ËüÒÀÀµÓÚ ES2015 Ä£¿éÓï·¨µÄ ¾²Ì¬½á¹¹ ÌØÐÔ£¬ÀýÈç import ºÍ export¡£Õâ¸öÊõÓïºÍ¸ÅÄîÔÚ´ò°ü¹¤¾ßrollupºÍwepackÖÐÆÕ¼°¿ªÀ´¡£

import {get} from './api.js'

let doSome = ()=>{
get()
}
doSome()

api.js´úÂ룺

let post = ()=>{
console.log('post')
}

export post
let get = ()=>{
console.log('get')
}
export get
 

export get

ÉÏÃæ´úÂëÖУ¬api.js´úÂëÖеÄpost·½·¨Ïà¹ØÄÚÈÝÊÇûÓб»ÒýÈëºÍʹÓõģ¬ÓÐÁËTree shakingÖ®ºó£¬Õⲿ·ÖÄÚÈÝÊDz»»á±»´ò°üµÄ£¬Õâ¾ÍÔÚÒ»¶¨³Ì¶ÈÉϼõÉÙÁË×ÊÔ´µÄ´óС¡£Ê¹ÓÃTree shakingµÄÔ­ÀíÊÇES6µÄÄ£¿é¾²Ì¬·ÖÎöÒýÈ룬Õâ¾Í¿ÉÒÔÔÚ±àÒëʱÕýÈ·Åжϵ½µ×¼ÓÔØÁËʲô´úÂ룬µ«ÊÇҪעÒâimport ºÍ exportÊÇES6Ô­ÉúµÄ¶ø²»ÊÇͨ¹ýbabel»òÕßwebpackת»¯µÄ¡£

ÔÚVue3ÖУ¬¶Ô´úÂë½á¹¹½øÐÐÁËÓÅ»¯£¬ÈÃÆä¸ü¼Ó·ûºÏTree shakingµÄ½á¹¹£¬ÕâÑùʹÓÃÏà¹ØµÄapiʱ£¬²»»á°ÑËùÓеͼ´ò°ü½øÀ´£¬Ö»»á´ò°üÄãÓõ½µÄapi£¬ÀýÈ磺

<!-- vue 2.x -->
import Vue from 'vue'
new Vue()
Vue.nextTick(() => {})
const obj = Vue.observable({})
<!-- vue 3.x -->
import { nextTick, observable,createApp } from 'vue'

nextTick(() => {})
const obj = observable({})
createApp({})

ͬʱ£¬ÀýÈç<keep-alive>ºÍ<transition>,<teleport>µÈÄÚÖÃ×é¼þ£¬Èç¹ûûÓÐʹÓÃÒ²²»»á±»´ò°üµ½×ÊÔ´Àï¡£

¸üÒ×ÓÚά»¤

Vue3´ÓFlowÇ¨ÒÆµ½TypeScript

ÔÚVue3µÄÔ´Âë½á¹¹²ãÃæ£¬´ÓFlow¸Ä³ÉÁËTypeScriptÀ´±àд£¬Ò»°ãÀ´Ëµ¶ÔÓÚJavaScriptÔ´Âë¿ò¼ÜÀ´ËµÒýÈëÀàÐͼì²âÊǷdz£ÖØÒªµÄ£¬²»½ö¿ÉÒÔ¼õÉÙbugµÄ²úÉú£¬»¹¿ÉÒԹ淶һЩ½Ó¿ÚµÄ¶¨Ò壬Flowfacebook

³öÆ·£¬ÊÇÒ»¸ö¾²Ì¬ÀàÐͼì²âÆ÷£¬ÓÐÁËËü¾Í¿ÉÒÔÔÚJavaScriptÔËÐÐǰÕÒ³ö³£¼ûµÄ bug£¬°üÀ¨£º

×Ô¶¯ÀàÐÍת»»

null ÒýÓÃ

¿ÉÅ嵀 undefined is not a function

ÀýÈ磺

// @flow
function foo(x: number): number {
return x + 10
}
foo('hi') // ²ÎÊýxÐèҪΪnumberÀàÐÍ£¬·ñÔò¾Í»á±¨´í
message: '[flow] string (This type is incompatible with number See also: function call)'

ÕâÐ©ÌØÐÔºÍtypescript·Ç³£ÎǺϣ¬ËùÒÔÔÚVue3ÖÐÖ±½Ó²ÉÓÃÁËtypescriptÀ´½øÐÐÖØÐ´£¬´ÓÔ´Âë²ãÃæÀ´ÌáÉýÏîÄ¿µÄ¿Éά»¤ÐÔ¡£

´úÂëĿ¼½á¹¹×ñÑ­monorepo

monorepoÊÇÒ»ÖÖ¹ÜÀí´úÂëµÄ·½Ê½£¬ËüµÄºËÐĹ۵ãÊÇËùÓеÄÏîÄ¿ÔÚÒ»¸ö´úÂë²Ö¿âÖУ¬µ«ÊÇ´úÂë·Ö¸îµ½Ò»¸ö¸öСµÄÄ£¿éÖУ¬¶ø²»ÊǶ¼·ÅÔÚsrcÕâ¸öĿ¼ÏÂÃæ¡£ÕâÑùµÄ·Ö¸î£¬Ã¿¸ö¿ª·¢Õߴ󲿷ÖʱֻÊǹ¤×÷ÔÚÉÙÊýµÄ¼¸¸öÎļþ¼ÐÒÔÄڵ쬲¢ÇÒÒ²Ö»»á±àÒë×Ô¼º¸ºÔðµÄÄ£¿é£¬¶øÇÒ²»»áµ¼ÖÂÒ»¸ö IDE ´ò²»¿ªÌ«´óµÄÏîĿ֮ÀàµÄÊÂÇ飬ÕâÑùºÜ¶àÊÂÇé¾Í¼òµ¥Á˺ܶࡣÈçÏÂͼ£º

ĿǰÖîÈç Babel, React, Angular, Ember, Meteor, Jest µÈµÈ¶¼²ÉÓÃÁË Monorepo ÕâÖÖ·½Ê½À´½øÐÐÔ´ÂëµÄ¹ÜÀí¡£

Vue2.xµÄĿ¼½á¹¹£º

Vue3µÄĿ¼½á¹¹£º

й¦ÄܺÍÌØÐÔ

Composition API

ÔÚVue2.xÖУ¬×é¼þµÄÖ÷ÒªÂß¼­ÊÇͨ¹ýһЩÅäÖÃÏîÀ´±àд£¬°üÀ¨Ò»Ð©ÄÚÖõÄÉúÃüÖÜÆÚ·½·¨»òÕß×é¼þ·½·¨£¬ÀýÈçÏÂÃæµÄ´úÂ룺

export default {
name: 'test',
components: {},
props: {},
data () {
return {}
},
created(){},
mounted () {},
watch:{},
methods: {}
}

ÕâÖлùÓÚÅäÖõÄ×é¼þд·¨³ÉΪOptions API£¨ÅäÖÃʽAPI£©£¬Vue3µÄÒ»´óºËÐÄÌØÐÔÊÇÒýÈëÁËComposition API£¨×éºÏʽAPI£©,ÕâʹµÃ×é¼þµÄ´ó²¿·ÖÄÚÈݶ¼¿ÉÒÔͨ¹ýsetup()·½·¨½øÐÐÅäÖã¬Í¬Ê±Composition APIÔÚVue2.xÒ²¿ÉÒÔʹÓã¬ÐèҪͨ¹ý°²×°@vue/composition-apiÀ´Ê¹Ó㬴úÂëÈçÏ£º

npm install @vue/composition-api
...
import VueCompositionApi from '@vue/composition-api';
Vue.use(VueCompositionApi);

ÏÂÃæ¾ÍÁоÙһЩʹÓÃComposition APIµÄÀý×Ó£º

ref»òÕßreactive´úÌædataÖеıäÁ¿:

ÔÚVue2.xÖÐͨ¹ý×é¼þdataµÄ·½·¨À´¶¨ÒåһЩµ±Ç°×é¼þµÄÊý¾Ý£º

...
data() {
return {
name: 'test',
list: [],
}
},
...

ÔÚVue3ÖÐͨ¹ýref»òÕßreactive´´½¨ÏìӦʽ¶ÔÏó£º

import {ref,reactive} from 'vue'
...
setup(){
const name = ref('test')
const state = reactive({
list: []
})
return {
name,
state
}
}
...

ref½«¸ø¶¨µÄÖµ´´½¨Ò»¸öÏìӦʽµÄÊý¾Ý¶ÔÏ󲢸³Öµ³õʼֵ£¨int»òÕßstring£©£¬reactive¿ÉÒÔÖ±½Ó¶¨Ò帴ÔÓÏìӦʽ¶ÔÏó¡£

methodsÖж¨ÒåµÄ·½·¨Ò²¿ÉÒÔдÔÚsetup()ÖÐ:

ÔÚVue2.xÖÐmethodsÀ´¶¨ÒåһЩµ±Ç°×é¼þÄÚ²¿·½·¨£º

...
methods: {
fetchData() {

},
}
...

ÔÚVue3ÖÐÖ±½ÓÔÚsetup·½·¨Öж¨Òå²¢return£º

...
setup(){
const fetchData = ()=>{
console.log('fetchData')
}
return {
fetchData
}
}
...

setup()ÖÐʹÓÃpropsºÍthis:

ÔÚVue2.xÖУ¬×é¼þµÄ·½·¨ÖпÉÒÔͨ¹ýthis»ñÈ¡µ½µ±Ç°×é¼þµÄʵÀý£¬²¢Ö´ÐÐdata±äÁ¿µÄÐ޸쬷½·¨µÄµ÷Óã¬×é¼þµÄͨÐŵȵȣ¬µ«ÊÇÔÚVue3ÖУ¬setup()ÔÚbeforeCreateºÍcreatedʱ»ú¾ÍÒѵ÷Óã¬ÎÞ·¨Ê¹ÓúÍVue2.xÒ»ÑùµÄthis£¬µ«ÊÇ¿ÉÒÔͨ¹ý½ÓÊÕsetup(props,ctx)µÄ·½·¨£¬»ñÈ¡µ½µ±Ç°×é¼þµÄʵÀýºÍprops£º

export default {
props: {
name: String,
},
setup(props,ctx) {
console.log(props.name)
ctx.emit('event')
},
}

×¢ÒâctxºÍ2.xÖÐthis²¢²»ÍêȫһÑù£¬¶øÊÇÑ¡ÔñÐԵر©Â¶ÁËһЩproperty£¬Ö÷ÒªÓÐ[attrs,emit,slots]¡£

watchÀ´¼àÌý¶ÔÏó¸Ä±ä

Vue2.xÖУ¬¿ÉÒÔ²ÉÓÃwatchÀ´¼àÌýÒ»¸ö¶ÔÏóÊôÐÔÊÇ·ñÓи͝£º

...
data(){
return {
name: 'a'
}
},
watch: {
name(val) {
console.log(val)
}
}
...

Vue3ÖУ¬ÔÚsetup()ÖУ¬¿ÉÒÔʹÓÃwatchÀ´¼àÌý£º

...
import {watch} from 'vue'
setup(){
let state = reactive({
name: 'a'
})
watch(
() => state.name,
(val, oldVal) => {
console.log(val)
}
)
state.name = 'b'
return {
state
}
}
...

ÔÚVue3ÖУ¬Èç¹ûwatchµÄÊÇÒ»¸öÊý×éarray¶ÔÏó£¬ÄÇôÈç¹ûµ÷ÓÃarray.push()·½·¨Ìí¼ÓÒ»ÌõÊý¾Ý£¬²¢²»»á´¥·¢watch·½·¨£¬±ØÐëÖØÐ¸øarray¸³Öµ£º

let state = reactive({
list: []
})
watch(
() => state.list,
(val, oldVal) => {
console.log(val)
}
)

state.list.push(1) // ²»»á´¥·¢watch

state.list = [1] // »á´¥·¢watch

´ËÎÊÌâ²»ÖªÊÇ·ñÊÇVue3.xÌØÒâ¼ÓÉϵģ¬ÓдýÕýʽ°æ³öÀ´ºóÔÚÑéÖ¤¡£

computed¼ÆËãÊôÐÔ£º

Vue2.xÖУº

...
computed: {
storeData () {
return this.$store.state.storeData
},
},
...

Vue3ÖУº

...
import {computed} from 'vue'
setup(){
const storeData = computed(() => store.state.storeData)
return {
storeData
}
}
...

µ±È»£¬¶ÔÓÚÍêÕûµÄVue Composition API£¬¸÷λͬѧ¿ÉÒԲο¼Îĵµ

<template>
<div>
<header>...</header>
<main>...</main>
<footer>...</footer>
</div>
</template>

Fragments

ÔÚVue2.xÖУ¬<template>ÖеÄÄÚÈݱØÐëÓÉÒ»¸ö×îÍâ²ãµÄ¸¸ÔªËذü¹ü£¬´úÂëÈçÏ£º

<template>
<div>
<header>...</header>
<main>...</main>
<footer>...</footer>
</div>
</template>

½á¹û·¢ÏÖReactÉçÇøÒ²Óöµ½ÁËͬÑùµÄÎÊÌâ¡£ËûÃÇÏë³öµÄ½â¾ö·½°¸ÊÇÒ»¸öÃûΪFragmentµÄÐéÄâÔªËØ£¬Ê¹Ó÷½·¨ÈçÏ£º

class Hello extends React.Component {
render() {
return (
<React.Fragment>
<header>...</header>
<main>...</main>
<footer>...</footer>
</React.Fragment>
);
}
}

¶øÔÚVue3ÖУ¬Ê¹Óøü¼Ó¼òµ¥£¬¿ÉÒÔÖ±½ÓÊ¡ÂÔ×îÍâ²ãµÄÔªËØ£¬Ð´·¨ÈçÏ£º

<template>
<header>...</header>
<main>...</main>
<footer>...</footer>
</template>

ÔÚVue3ÖУ¬<teleport>ÊÇÒ»¸öÄÚÖñêÇ©£¬Èç¹ûÄãÔø¾­´´½¨¹ýģ̬¹¦ÄÜ£¬Äã»áÖªµÀËüͨ³£±»·ÅÖÃÔڹرյÄ</body>±êǩ֮ǰ£¬ÈçÏ£º

<body>
<div>
<!--main page content here-->
</div>
<!--modal here-->
</body>

Èç¹û°´ÕÕÒÔÍùµÄ˼·£¬ÐèÒª½«Ä£Ì¬µÄUI´úÂë·ÅÔڵײ¿£¬ÈçÏ£º

<body>
<div id="app">
<h3>Tooltips with Vue 3 Teleport</h3>
</div>
<div>
<modal-button></modal-button>
</div>
</body>

ÕâÑù×öÊÇÒòΪģʽͨ³£¾ßÓи²¸ÇÒ³ÃæµÄ±³¾°£¬ÒªÊ¹ÓÃCSSÀ´ÊµÏÖ£¬Äú²»ÐèÒª´¦Àí¸¸ÔªËØ¶¨Î»ºÍz-index¶ÑÕ»ÉÏÏÂÎÄ£¬Òò´Ë×î¼òµ¥µÄ½â¾ö·½°¸Êǽ«Ä£Ê½·ÅÔÚÒ³ÃæµÄ×îµ×²¿¡£ÕâÑùµÄ»°Õⲿ·ÖÂß¼­¾ÍÍÑÀëÁËÕû¸öÏîÄ¿µÄ¸ú×é¼þAppµÄ¹ÜÀí£¬¾ÍÔì³ÉÖ±½Ó²ÉÓÃJavaScriptºÍCSSÀ´ÐÞ¸ÄUI£¬²¢²»ÊǺܹ淶¡£ÎªÁËÔÊÐí½«Ò»Ð©UIƬ¶Î¶ÎÒÆ¶¯µ½Ò³ÃæÖÐµÄÆäËûλÖã¬ÔÚVue3ÖÐÌí¼ÓÁËÒ»¸öеÄ<teleport>×é¼þ¡£

ҪʹÓÃ<teleport>£¬Ê×ÏÈÒªÔÚÒ³ÃæÉÏÌí¼ÓÒ»¸öÔªËØ£¬ÎÒÃÇÒª½«Ä£Ì¬ÄÚÈÝÒÆ¶¯µ½¸ÃÒ³Ãæ¡£´úÂëÈçÏ£º

app.component('modal-button', {
template: `
<button @click="modalOpen = true">
Open full screen modal! (With teleport!)
</button>
<teleport to="#endofbody">
<div v-if="modalOpen" class="modal">
...
</div>
</teleport>
`,
data() {
return {
modalOpen: false
}
}
})

 

<body>
<div id="app">
<h3>Tooltips with Vue 3 Teleport</h3>
</div>
<div id="endofbody"></div>
</body>

Æä#endofbody±íʾ´Ë²¿·ÖÄÚÈݽ«»áÌí¼Óµ½Ò³Ãæµ×²¿¡£

<Suspense>

<Suspense>ÊÇÒ»¸öÌØÊâµÄ×é¼þ£¬Ëü½«³ÊÏÖ»ØÍËÄÚÈÝ£¬¶ø²»ÊǶÔÓÚµÄ×é¼þ£¬Ö±µ½Âú×ãÌõ¼þΪֹ£¬ÕâÖÖÇé¿öͨ³£ÊÇ×é¼þsetup¹¦ÄÜÖз¢ÉúµÄÒì²½²Ù×÷»òÕßÊÇÒì²½×é¼þÖÐʹÓá£ÀýÈçÕâÀïÓÐÒ»¸ö³¡¾°£¬¸¸×é¼þչʾµÄÄÚÈݰüº¬Òì²½µÄ×Ó×é¼þ£¬Òì²½µÄ×Ó×é¼þÐèÒªÒ»¶¨µÄʱ¼ä²Å¿ÉÒÔ¼ÓÔØ²¢Õ¹Ê¾£¬Õâʱ¾ÍÐèÒªÒ»¸ö×é¼þ´¦ÀíһЩռλÂß¼­»òÕß¼ÓÔØÒì³£Âß¼­£¬ÒªÓõ½<Suspense>£¬ÀýÈ磺

<Suspense>
<template >
<Suspended-component />
</template>
<template #fallback>
Loading...
</template>
</Suspense>

ÉÏÃæ´úÂëÖУ¬¼ÙÉè<Suspended-component>ÊÇÒ»¸öÒì²½×é¼þ£¬Ö±µ½ËüÍêÈ«¼ÓÔØ²¢äÖȾǰ¶¼»áÏÔʾռλÄÚÈÝ£ºLoading£¬Õâ¾ÍÊÇ<Suspense>µÄ¼òµ¥Ó÷¨£¬¸ÃÌØÐÔºÍFragmentÒÔ¼°<teleport>Ò»Ñù£¬Áé¸ÐÀ´×ÔReact¡£

Vite

°éËæ×ÅVue3£¬VueÍŶÓÒ²ÍÆ³öÁË×Ô¼ºµÄ¿ª·¢¹¹½¨¹¤¾ßVite£¬¿ÉÒÔÔÚÒ»¶¨³Ì¶ÈÉÏÈ¡´úvue-cliºÍwebpack-dev-serverµÄ¹¦ÄÜ£¬»ùÓÚ´ËViteÖ÷ÒªÓÐÒÔÏÂÌØÐÔ£º

¿ìËÙµÄÀäÆô¶¯

¼´Ê±µÄÄ£¿éÈȸüÐÂ

ÕæÕýµÄ°´Ðè±àÒë

ViteÔÚ¿ª·¢»·¾³Ï»ùÓÚä¯ÀÀÆ÷Ô­Éú ES Modules ¿ª·¢£¬ÔÚÉú²ú»·¾³Ï»ùÓÚ Rollup ´ò°ü£¬ÎÒÃÇÏÈÀ´Á˽âÒ»ÏÂES Modules¡£

ES Modules

ES Modules¼ò³ÆESM£¬ÊÇ JavaScript ¹Ù·½µÄ±ê×¼»¯Ä£¿éϵͳ¡£Á˽â¹ýseaJSºÍrequireJS£¨ÒÔ¼°ºóÆÚµÄwebpackºÍbabel£©µÄ¶¼Ó¦¸ÃÖªµÀʲôÊÇ¡°Ä£¿é»¯¡±£¬ÔÚʹÓÃÕâÁ½¸ö¿âÊÇ£¬»áÓõ½require()·½·¨È¥¼ÓÔØÄ£¿é£¬Ê¹ÓÃdefine()·½·¨È¥¶¨ÒåÄ£¿é£¬ÕâЩ·½·¨¶¼ÊÇ¿âÌṩ¸øÎÒÃǵ쬶øä¯ÀÀÆ÷Ô­ÉúÊÇÎÞ·¨Ê¶±ðµÄ¡£¶øESMÊÇES6¸øÎÒÃÇÌṩµÄ±ê×¼API£¬ÔÚä¯ÀÀÆ÷Ö§³ÖµÄÇé¿öÏ£¬ÎÒÃÇ¿ÉÒÔʹÓÃimport()ÒÔ¼°export()À´ÊµÏÖ¡°Ä£¿é»¯¡±£¬Ê¹Ó÷½·¨ÈçÏ£º

µ¼³öÄ£¿é(a.js)£º

export const name = 'tenny';
export function get(num) {
return {
num: num+10
};
}

µ¼ÈëÄ£¿é(b.js)£º

import { name, get } from '/a.js';
import * as aModule from '/a.js';

ÔÚHTMLÖÐÒýÈëʹÓÃÁËESMµÄjsÎļþÐèÒªÔÚ<script>±êÇ©ÉÏÌí¼Ótype="module"£¬ÀýÈ磺

<script type="module" src="b.js"></script>

ÒÔÉϾÍÊǼòµ¥µÄES ModulesÓ÷¨£¬Vite»ùÓÚÕâÖÖд·¨¸ü·ûºÏTree ShakingµÄ½á¹¹¹æ·¶£¬Í¬Ê±Ìí¼ÓÁË×Ô¼ºµÄdev-serverºÍHMR(ÈȸüÐÂ)»úÖÆ£¬ÕâÑù¾Í¿ÉÒÔÂú×㿪·¢½×¶ÎµÄ¹¦ÄÜÌṩ¡£

Rollup

Rollup ÊÇÒ»¸ö JavaScript Ä£¿é´ò°üÆ÷£¬Ò²ÊÇ×îÏÈÌá³öTree Shaking¸ÅÄºÍWebpack»òÕßBrowserifyÓÐ×ÅͬÑùµÄÄ£¿é´ò°ü¹¦ÄÜ£¬ËüµÄ×î´óÌØµãÊÇ»ùÓÚES Modules½øÐдò°ü£¬²»ÐèҪͨ¹ýÀàËÆBabelת»¯µÄ·½°¸½«importת»¯³ÉCommonjsµÄrequire·½Ê½£¬¼«´óµØÀûÓÃä¯ÀÀÆ÷µÄÔ­ÉúÌØÐÔ¡£

»ùÓÚTree ShakingÌØÐÔ£¬Rollup¿ÉÒÔ×î´ó»¯Ëü±£³Ö´ò°üºóµÄÎļþÌå»ý¸üС£¬ÕâÒ²ÊÇViteÔÚÉú²ú»·¾³Ï²ÉÓÃRollupµÄÖ÷ÒªÔ­Òò¡£

´´½¨Ò»¸öVite app

$ npm init vite-app <project-name>
$ cd <project-name>
$ npm install
$ npm run dev

²»Ö»ÏÞÓÚVue£¬ViteͬʱÌṩÁË´´½¨React appµÄÄÜÁ¦£¬¿ÉÒÔͨ¹ýÅäÖÃÄ£°åÀ´Éú³É£º

npm init vite-app --template react or --template preact

µ±È»£¬ViteÔÚʵ¼ÊÔËÓÃÖпÉÄܲ»µ¥µ¥ÊǼòµ¥´´½¨£¬ÆÚ¼ä»¹ÓÐһЩÅäÖÃÏÀýÈçVite+typescript£¬ÕâÀïÎÒÌṩ¼¸¸ö´´½¨ºÃµÄÄ£°åÏîÄ¿À´¹©²Î¿¼£º

vue3+typescript+vue -class-component+vite

vue3+typescript+vue-class-component+vuecli

Vue2.xÉý¼¶Ö¸ÄÏ

¶ÔÓÚÏÖÓеÄVue2.xÏîÄ¿£¬Èç¹ûÏëҪƽ»¬µÄÉý¼¶µ½Vue3£¬ÔÚ²»Ê¹ÓÃһЩÐÂÌØÐÔµÄÇé¿öÏ£¬¸Ä¶¯»¹²»ËãºÜ´ó£¬ÐèÒª¹Ø×¢ÒÔÏÂÎÊÌâ¡£

Vue3ÖÐÒÆ³ýµÄһЩAPIºÍ·½·¨

È¡ÏûKeyboardEvent.keyCode

ÔÚVue2.xÖУ¬°ó¶¨¼üÅÌʼþ»áÓõ½ÈçÏ´úÂ룺

<!-- keyCode version -->
<input v-on:keyup.13="submit" />
<!-- alias version -->
<input v-on:keyup.enter="submit" />

»òÕßÊÇ£º

Vue.config.keyCodes = {
f1: 112
}
<!-- keyCode version -->
<input v-on:keyup.112="showHelpText" />
<!-- custom alias version -->
<input v-on:keyup.f1="showHelpText" />

ÔÚʼþÖУ¬¸økeyupÅäÖÃÒ»¸öÖ¸¶¨°´Å¥µÄkeyCode(Êý×Ö)ÔÚVue3Öн«²»»áÉúЧ£¬µ«ÊÇÒÀÈ»¿ÉÒÔʹÓñðÃû£¬ÀýÈ磺

<input v-on:keyup.delete="confirmDelete" />

ÒÆ³ý$on, $off ºÍ $once·½·¨

ÔÚVue2.xÖпÉÒÔͨ¹ýEventBusµÄ·½·¨À´ÊµÏÖ×é¼þͨÐÅ£º

var EventBus = new Vue()
Vue.prototype.$EventBus = EventBus
...
this.$EventBus.$on() this.$EventBus.$emit()

ÕâÖÖÓ÷¨ÔÚVue3ÖоͲ»ÐÐÁË£¬ÔÚVue3ÖÐÒÆ³ýÁË$on, $offµÈ·½·¨£¨²Î¿¼rfc£©£¬¶øÊÇÍÆ¼öʹÓÃmitt·½°¸À´´úÌæ£º

import mitt from 'mitt'
const emitter = mitt()
// listen to an event
emitter.on('foo', e => console.log('foo', e) )
// fire an event
emitter.emit('foo', { a: 'b' })

ÒÆ³ýfilters

ÔÚVue3ÖУ¬ÒƳýÁË×é¼þµÄfiltersÏ¿ÉÒÔʹÓÃmethodsµÄ»òÕßcomputedÀ´½øÐÐÌæ´ú£º

<template>
<p>{{ accountBalance | currencyUSD }}</p>
</template>
<script>
export default {
filters: {
currencyUSD(value) {
return '$' + value
}
}
}
</script>

Ìæ»»Îª£º

<template>
<p>{{ accountInUSD }}</p>
</template>
<script>
export default {
props: {
accountBalance: {
type: Number,
required: true
}
},
computed: {
accountInUSD() {
return '$' + this.accountBalance
}
}
}
</script>

ÒÆ³ýinline-template

ÔÚVue2.xÖУ¬ÔÚ¸¸×é¼þÒýÈë×Ó×é¼þʱ£¬»áÓõ½inline-templateÀ´Ê¹×Ó×é¼þµÄÄÚÈÝÒ²µÃµ½Õ¹Ê¾£¬²Î¿¼ÕâÀÀýÈ磺

<my-component inline-template>
<div>
<p>These are compiled as the component's own template.</p>
<p>Not parent's transclusion content.</p>
</div>
</my-component>

ÔÚVue3ÖУ¬Õâ¸ö¹¦Äܽ«±»ÒƳý£¬Ä¿Ç°inline-templateʹÓõIJ¢²»¶à£¬ÕâÀï¾Í²»ÔÙ¹ý¶à½²½â¡£

Vue3ÖиıäµÄAPIºÍд·¨

¸ùʵÀý³õʼ»¯:

ÔÚ2.xÖÐͨ¹ýnew Vue()µÄ·½·¨À´³õʼ»¯£º

import App from './App.vue'
new Vue({
store,
render: h => h(App)
}).$mount('#app')

ÔÚ3.xÖÐVue²»ÔÙÊÇÒ»¸ö¹¹Ô캯Êý£¬Í¨¹ýcreateApp·½·¨³õʼ»¯£º

import App from './App.vue'
createApp(App).use(store).mount('#app')

È«¾ÖAPIµ÷Ó÷½Ê½¸Ä±ä

ÔÚVue2.xÖУ¬´ó²¿·ÖÈ«¾ÖAPI¶¼ÊÇͨ¹ýVue.xxx»òÕßVue.abc()·½Ê½µ÷Óã¬ÀýÈ磺

import Vue from 'vue'
Vue.mixin()
Vue.use()
...

¶øÔÚVue3ÖУ¬ÕâЩ·½Ê½½«»á¸Ä±ä£¬È¡¶ø´úÖ®µÄÊÇÈçÏ£º

import { createApp } from 'vue'
const app = createApp({})
app.mixin()
app.use()
...

ͬʱ£¬¿ÉÒÔÖ»ÒýÈëһЩÐèÒªµÄAPI£¬²»ÐèÒªµÄ²»ÓÃÒýÈ룬ÕâÑùÒ²·ûºÏThree ShakingµÄÒªÇó£¬ÀýÈ磺

import { nextTick,reactive,onMounted } from 'vue'
nextTick(() => {

})
onMounted(() => {

})

ÓÉÓÚVue3ÖÐÈ«¾ÖAPI¶¼»áͨ¹ýapp.xxxµÄ·½·¨µ÷Óã¬ËùÒÔ֮ǰͨ¹ýVue.prototype.xxx°ó¶¨µÄÈ«¾Ö·½·¨ºÍ±äÁ¿½«ÎÞ·¨Ê¹Ó㬿ÉÒÔ²ÉÓÃÈçÏ·½Ê½À´´úÌæ£º

//ÔÚmain.jsÖУº
app.config.globalProperties.http = function(){}
//ÔÚvue×é¼þÖУº
this.http()

render·½·¨ÐÞ¸Ä

ÔÚVue2.xÖУ¬ÓÐʱ»á×Ô¶¨Òårender·½·¨À´·µ»ØÄ£°åÄÚÈÝ£¬ÈçÏ£º

export default {
render(h) {
return h('div')
}
}

ÔÚVue3ÖУ¬hͨ¹ývueÀ´ÒýÈ룬ÈçÏ£º

import { h } from 'vue'
export default {
render() {
return h('div')
}
}

еÄÒì²½×é¼þ´´½¨·½Ê½

ÔÚVue2.xÖУ¬ÓÈÆäÊÇÔÚVue RouterÖУ¬»á¾­³£Ê¹Óõ½Òì²½×é¼þ£¬½èÖúwebpackµÄ´ò°ü·½Ê½£¬¿ÉÒÔ½«Ò»¸ö×é¼þµÄ´úÂë½øÐÐÒì²½»ñÈ¡£¬ÀýÈ磺

const asyncPage = () => import('./NextPage.vue')
const asyncPage = {
component: () => import('./NextPage.vue'),
delay: 200,
timeout: 3000,
error: ErrorComponent,
loading: LoadingComponent
}

ÔÚVue3ÖУ¬ÌṩÁËdefineAsyncComponent()·½·¨´´½¨Òì²½×é¼þ£¬Í¬Ê±¿ÉÒÔ·µ»ØÒ»¸öPromise¶ÔÏóÀ´×Ô¼º¿ØÖƼÓÔØÍê³Éʱ»ú£¬ÈçÏ£º

import { defineAsyncComponent } from 'vue'
const asyncPageWithOptions = defineAsyncComponent({
loader: () => import('./NextPage.vue'),
delay: 200,
timeout: 3000,
error: ErrorComponent,
loading: LoadingComponent
})
const asyncComponent = defineAsyncComponent(
() =>
new Promise((resolve, reject) => {
/* ... */
})
)

dataÊôÐÔÖ»Ö§³Öfunction

ÔÚVue2.xÖУ¬¸ù×é¼þµÄdata¿ÉÒÔÖ±½ÓÅäÖÃÒ»¸ö¶ÔÏó£¬×Ó×é¼þµÄdata¿ÉÒÔÅäÖÃfunction£¬È»ºó·µ»ØÒ»¸ö¶ÔÏó£¬ÈçÏ£º

<!-- Object Declaration -->
<script>
const app = new Vue({
data: {
apiKey: 'a1b2c3'
}
})
</script>
<!-- Function Declaration -->
<script>
const child = new Vue({
data() {
return {
apiKey: 'a1b2c3'
}
}
})
</script>

ÔÚVue3ÖУ¬ËùÓÐ×é¼þ¶¼Ö»Ö§³ÖÅäÖÃfunction·µ»ØÒ»¸ö¶ÔÏóµÄ·½Ê½£¬ÈçÏ£º

<script>
import { createApp } from 'vue'
createApp({
data() {
return {
apiKey: 'a1b2c3'
}
}
}).mount('#app')
</script>

ʹÓÃ×Ô¶¨Òå±êÇ©ºÍisÊôÐԸ͝

ÔÚVue2.xÖУ¬¿ÉÒÔʹÓÃһЩ·ÇHTML±ê×¼µÄ±êÇ©£¨ÀýÈçʹÓÃWeb Components£©£¬ÐèÒªÔÚVueÈ«¾ÖÅäÖÃÖÐÉùÃ÷ºöÂԸñêÇ©£¬ÀýÈ磺

<plastic-button></plastic-button>
Vue.config.ignoredElements = ['plastic-button']

ÔÚVue3ÖУ¬Í¬ÑùÖ§³Ö×Ô¶¨Òå±êÇ©£¬ÉùÃ÷ʱ¿ÉÒÔʹÓÃÈçÏ£º

const app = Vue.createApp({})
app.config.isCustomElement = tag => tag === 'plastic-button'

³ýÁË×Ô¶¨Òå±êÇ©µÄÐ޸ģ¬ÔÚVue2.xÖУ¬»áÓõ½¶¯Ì¬×é¼þis£¬ÀýÈ磺

<button is="plastic-button"> Click Me!</button>

ÓÉÓÚisµÄÌØÐÔ£¬ÕâÖÖд·¨ÔÚVue2.x×îÖջᱻäÖȾ³É<plastic-button>×é¼þ£¬µ«ÊÇÔÚVue3ÖУ¬Ö»»á°Ñisµ±×÷Ò»¸öÆÕͨµÄpropsÊôÐÔ£¬Èç¹ûÏëʵÏÖVue2.xÒ»ÑùµÄЧ¹û£¬¿ÉÒÔʹÓÃv-is£¬ÀýÈ磺

<button v-is="plastic-button">Click Me!</button>
//result£º
<plastic-button></plastic-button>

ÐèҪעÒâµÄÊÇÔÚÌØÊâÔªËØ<component>ÉÏÅäÖõÄisÊôÐÔÓ÷¨ÒÀÈ»ÉúЧ¡£

this.$scopedSlotsÌæ´úΪthis.$slots

ÔÚVue2.xµÄijЩ³¡¾°£¬ÌرðÊÇÓõ½×Ô¶¨Òårender·½·¨ºÍ²å²Ûʱ£¬»áÓõ½this.$scopedSlots»ñÈ¡Êý¾Ý£¬ÀýÈ磺

h(LayoutComponent, [
h('div', { slot: 'header' }, this.header),
h('div', { slot: 'content' }, this.content)
])
this.$scopedSlots.header

ÔÚVue3ÖУ¬this.$scopedSlots½«»á±»ÒƳý£¬Í³Ò»Ìæ´ú³Éthis.$slots£¬ÀýÈ磺

h(LayoutComponent, {}, {
header: () => h('div', this.header),
content: () => h('div', this.content)
})
this.$slots.header

×Ô¶¨ÒåÖ¸ÁîÉúÃüÖÜÆÚ·½·¨ÐÞ¸Ä

ÔÚVue2.xÖУ¬ÓÐʱ»á×Ô¼º´´½¨×Ô¶¨ÒåÖ¸ÁÀýÈ磺

<p v-highlight="yellow"> Highlight this text bright yellow</p>

ÔÚ×Ô¶¨ÒåÖ¸ÁîÖУ¬¿ÉÒÔʹÓÃVueÌṩµÄһЩÉùÃ÷ÖÜÆÚ·½·¨£¬Íê³É¾ßÌåµÄÂß¼­£¬ÀýÈ磺

Vue.directive('highlight', {
bind(el, binding, vnode) {
el.style.background = binding.value
},
inserted(),
beforeUpdate(),
update(),
componentUpdated(),
beforeUnmount(),
unbind()
})

ÔÚVue3ÖУ¬Ö÷Òª¶ÔÕâЩÉúÃüÖÜÆÚ·½·¨½øÐÐÁ˵÷Õû£¬ÈçÏ£º

Vue.directive('highlight', {
beforeMount(el, binding, vnode) { // ¶ÔÓ¦bind
el.style.background = binding.value
},
mounted() {}, // ¶ÔÓ¦inserted
beforeUpdate() {}, // ÐÂÔö
updated() {}, // ¶ÔÓ¦update
beforeUnmount() {}, // ÐÂÔö
unmounted() {} // ¶ÔÓ¦unbind
})

watch·½·¨²»ÔÙÖ§³Ö"µã·Ö¸ô"д·¨

ÔÚVue2.xÖУ¬Ê¹ÓÃwatch·½·¨¼àÌý¶ÔÏó¸Ä±äʱ£¬Èç¹û¶ÔÏó²ã¼¶½ÏÉ¿ÉÒÔ²ÉÓá°µã·Ö¸î¡±µÄд·¨£¬ÀýÈ磺

var vm = new Vue({
data: {
e: {
f: {
g: 5
}
}
},
watch: {
// watch vm.e.f's value: {g: 5}
'e.f': function (val, oldVal) { /* ... */ }
}
})

ÕâÖÖд·¨ÔÚVue3Öн«²»ÔÚÖ§³Ö£¬°üÀ¨Ê¹ÓÃʵÀý·½·¨this.$watch¡£

IE¼æÈÝ

»ùÓÚÉÏÎÄÖÐÌáµ½µÄES6µÄProxyÌØÐÔ£¬¶ÔÓÚIE11¼æÈÝÐÔ²¢²»ÓѺ㬺ÃÔÚVueÍŶӻáÌṩ¼æÈÝIE11µÄ°æ±¾£¬µ«ÊÇijЩеÄÌØÐÔ¿ÉÄܾÍÎÞ·¨Ê¹ÓÃÁË¡£

×ܽá

Vue2»¹»áÌṩһ¸öÎȶ¨µÄ2.7°æ±¾£¬²¢½«»á³¤ÆÚά»¤£¬ËùÒÔ»¹Êǽ¨Ò飬Èç¹ûÄãµÄÏîÄ¿ºÜÎȶ¨£¬ÇÒ¶Ôй¦ÄÜÎÞ¹ý¶àµÄÒªÇó»òÕßÇ¨ÒÆ³É±¾¹ý¸ß£¬Ôò²»½¨ÒéÉý¼¶Vue3¡£

¸½ÉÏ»ùÓÚVue3¿ª·¢µÄToDoListÏîÄ¿´«ËÍÃÅ

 

 
   
2306 ´Îä¯ÀÀ       28
Ïà¹ØÎÄÕÂ

Éî¶È½âÎö£ºÇåÀíÀôúÂë
ÈçºÎ±àд³öÓµ±§±ä»¯µÄ´úÂë
ÖØ¹¹-ʹ´úÂë¸ü¼ò½àÓÅÃÀ
ÍŶÓÏîÄ¿¿ª·¢"±àÂë¹æ·¶"ϵÁÐÎÄÕÂ
Ïà¹ØÎĵµ

ÖØ¹¹-¸ÄÉÆ¼ÈÓдúÂëµÄÉè¼Æ
Èí¼þÖØ¹¹v2
´úÂëÕû½àÖ®µÀ
¸ßÖÊÁ¿±à³Ì¹æ·¶
Ïà¹Ø¿Î³Ì

»ùÓÚHTML5¿Í»§¶Ë¡¢Web¶ËµÄÓ¦Óÿª·¢
HTML 5+CSS ¿ª·¢
ǶÈëʽC¸ßÖÊÁ¿±à³Ì
C++¸ß¼¶±à³Ì
×îл¼Æ»®
DeepSeekÔÚÈí¼þ²âÊÔÓ¦ÓÃʵ¼ù 4-12[ÔÚÏß]
DeepSeek´óÄ£ÐÍÓ¦Óÿª·¢Êµ¼ù 4-19[ÔÚÏß]
UAF¼Ü¹¹ÌåϵÓëʵ¼ù 4-11[±±¾©]
AIÖÇÄÜ»¯Èí¼þ²âÊÔ·½·¨Óëʵ¼ù 5-23[ÉϺ£]
»ùÓÚ UML ºÍEA½øÐзÖÎöÉè¼Æ 4-26[±±¾©]
ÒµÎñ¼Ü¹¹Éè¼ÆÓ뽨ģ 4-18[±±¾©]
 
×îÐÂÎÄÕÂ
ÈçºÎÉè¼Æ¸ßÀ©Õ¹µÄÔÚÏßÍøÒ³ÖÆ×÷ƽ̨
electronÈëÃÅÐĵÃ
ʹÓà Electron ¹¹½¨×ÀÃæÓ¦ÓÃ
VUE.JS×é¼þ»¯¿ª·¢Êµ¼ù
ÉîÈëÀí½âJSCore
×îпγÌ
HTML 5 + CSS3 Ô­ÀíÓ뿪·¢Ó¦ÓÃ
Webǰ¶Ë¸ß¼¶¹¤³Ìʦ±Ø±¸¼¼ÄÜʵս
Vue´óÐÍÏîÄ¿¿ª·¢ÊµÕ½
ReactÔ­ÀíÓëʵ¼ù
Vue.js½ø½×Óë°¸Àýʵ¼ù
³É¹¦°¸Àý
Öн»¼¯ÍÅ ¹¹½¨Web×Ô¶¯»¯²âÊÔ¿ò¼Ü
ijָÃûµçÐŹ«Ë¾ Vue.js½ø½×Óë°¸Àý
¹úµçÍ¨ÍøÂç¼¼Êõ HTML5+CSS3 +webǰ¶Ë¿ò
ÒÆ¶¯Í¨ÐÅ ÒÆ¶¯»¥ÁªÍøÓ¦Óÿª·¢Ô­Àí
ijµçÁ¦ÐÐ android¿ª·¢Æ½Ì¨×î¼Ñ