SFC
Any top-level bindings (including variables, function declarations, and imports) declared inside <script setup> are directly usable in the template:
| 1
2
3
4
5
6
7
8
9
10
11
 | <template>
  <div @click="log"></div>
</template>
<script setup>
const msg = 'Hello!'
// functions
function log() {
  console.log(msg)
}
</script>
 | 
defineProps and defineEmits
defineProps and defineEmits are compiler macros
| 1
2
3
4
5
6
7
8
 | <script setup>
const props = defineProps({
  foo: String
})
const emit = defineEmits(['change', 'delete'])
// setup code
</script>
 | 
ES Lint Config:
| 1
2
3
4
5
6
7
8
9
 | module.exports = {
  // ...
  globals: {
    defineProps: "readonly",
    defineEmits: "readonly",
    defineExpose: "readonly",
    withDefaults: "readonly"
  }
}
 | 
Teleport
| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 | <button @click="modalOpen = true">
    Open full screen modal! (With teleport!)
</button>
<teleport to="body">
  <div v-if="modalOpen" class="modal">
    <div>
      I'm a teleported modal! 
      (My parent is "body")
      <button @click="modalOpen = false">
        Close
      </button>
    </div>
  </div>
</teleport>
 | 
| 1
2
3
4
5
6
 | // 传送至 body
import { createVNode, h, render, Teleport } from 'vue';
render(
  createVNode(h(Teleport, { to: 'body' }, ['hello'])),
  document.createDocumentFragment() as any
);
 | 
Functional
| 1
2
3
 | function MyComponent(props, context) {
  // ...
}
 | 
Reactivity
  - targetMap-- WeakMap- 
      - key: Reactive Object
- value: depMap
 
| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 | function reactive(target) {
  const handler = {
    get(target, key, receiver) {
      let result = Reflect.get(target, key, receiver);
      // track
      return result;
    },
    set(target, key, value, receiver) { // receiver ensures the proper value of `this`
      let oldValue = target[key];
      let result = Reflect.set(target, key, value, receiver);
      if (result && oldValue != value) {
        // trigger
      }
    }
    return new Proxy(target, handler);
  }
}
 | 
reactive()
The reactive conversion is “deep”: it affects all nested properties.
A reactive object also deeply unwraps any properties that are refs while maintaining reactivity.
| 1
2
3
4
 | // !! no ref unwrapping performed, also native collection type like `Map`.
const reactiveA = reactive([ref(1), ref(2)]);
 
console.log(reactiveA[0].value) // 1
 | 
Lifecycle
graph TD
  PBM --> CBM
  CM --> PM
  subgraph Child
  CBM(onBeforeMount)-->CM(onMounted)
  end
  subgraph Parent
  PBM(onBeforeMount)
  PM(onMounted)
  end
Debug
| 1
2
3
 | $vm0.setupState
$vm0.setupContext
 | 
Pinia
store is an object wrapped with reactive, can’t destructure!
| 1
2
3
 | import { storeToRefs } from 'pinia'
const { name, doubleCount } = storeToRefs(useCounterStore());
 | 
VueUse
Collection of Vue Composition Utilities
  https://vueuse.org
Most of the functions in VueUse returns an object of refs that you can use ES6’s object destructure syntax to take what you need.
| 1
2
 | // "x" and "y" are refs
const { x, y } = useMouse()
 | 
If you prefer to use them as object properties style, you can unwrap the refs by using reactive().
| 1
2
3
4
 | const mouse = reactive(useMouse())
// "x" and "y" will be auto unwrapped, no `.value` needed
console.log(mouse.x)
 | 
useMemoize