Vue.js 3.x Composition APIs 及简单使用

这篇具有很好参考价值的文章主要介绍了Vue.js 3.x Composition APIs 及简单使用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Vue 3.0 和 2.x 的区别

  • 源码组织方式的变化
  • Composition API
  • 性能提升
  • Vite

源码全部采用 TS 重写,组织方式也发生变化,使用 Monorepo 的方式来组织项目的结构,把独立的功能模块都提取到不同的包中。

虽然重写,但是 90% 都兼容 2.x 的API,根据社区反馈,增加了 Composition API,组合式API,旨在解决开发超大型项目遇到超大组件使用Options API 不好拆分重用的问题。

性能方面,大幅度提升,使用 Proxy(代理对象) 重写了响应式代码,并且对编译器做了优化,重写了虚拟DOM,让渲染和update的性能有了大幅度的提升。另外,官方介绍,服务端渲染的性能也提升了 2-3 倍。

Vite 工具的发布,使开发阶段不需要打包直接运行项目,提升开发效率。

源码组织方式

Vue.js 3.x Composition APIs 及简单使用

packages 目录结构

Vue.js 3.x Composition APIs 及简单使用

不同构建版本

Vue3.0中不再构建 UMD 模块化的方式,因为冗余太多。
构建版本:4类
Vue.js 3.x Composition APIs 及简单使用
CommonJS:

  • cjs
    • vue.cjs.js
    • vue.cjs.prod.js

Global: 可以直接通过 script 标签直接导入

  • global
    • vue.global.js
    • vue.global.prod.js
    • vue.runtime.global.js
    • vue.runtime.global.prod.js

Browser: ESModule ,可以直接通过 script type=module 的方式导入

  • browser
    • vue.esm-browser.js
    • vue.esm-browser.prod.js
    • vue.runtime.esm-browser.js
    • vue.runtime.esm-browser.prod.js

Bundler: 需要配合打包工具来使用,ESM 方式

  • bundler
    • vue.esm-bundler.js
    • vue.runtime.esm-bundler.js

Composition API 设计动机

  • RFC(request for comments)
    • https://github.com/vuejs/rfc
  • Composition API RFC
    • https://composition-api.vuejs.org

设计动机

  • Options API

    • 包含一个描述组件选项(data.methods.props等)对象
    • Options API 开发复杂组件,同一个功能逻辑的代码被拆分到不同选项
  • Composition API

    • Vue.js 3.0 新增的一组 API
    • 一组基于函数的 API
    • 可以更灵活的组织组件的逻辑
Options API Demo:

Vue.js 3.x Composition APIs 及简单使用

Composition API Demo:

Vue.js 3.x Composition APIs 及简单使用

对比:

Vue.js 3.x Composition APIs 及简单使用

性能提升

  • 响应式系统升级
  • 编译优化
  • 源码体积的优化

响应式系统升级

Vue.js 3.x Composition APIs 及简单使用

编译优化

Vue.js 3.x Composition APIs 及简单使用

优化打包体积

Vue.js 3.x Composition APIs 及简单使用

Vite

Vite 来自于 法语,意思是 快。

ESModule

Vue.js 3.x Composition APIs 及简单使用

Vite as Vue-CLI

Vue.js 3.x Composition APIs 及简单使用
Vue.js 3.x Composition APIs 及简单使用

Vite 特点

Vue.js 3.x Composition APIs 及简单使用

Composition API

注意:Composition API 仅仅是 Vue3中新增的 API,我们依然可以使用 Options API。

Composition API

生命周期钩子函数

Vue.js 3.x Composition APIs 及简单使用

reactive|toRefs|ref

ref demo:

<body>
    <div id="app">
        <button @click="increase">加加</button>
        <span>{{count}}</span>
    </div>
    <script type="module">
        import { createApp, ref } from './node_modules/vue/dist/vue.esm-browser.js'
        function useCount(){
            const count = ref(0)
            return {
                count,
                increase:()=>{
                    count.value ++
                }
            }
        }
        const app = createApp({
            setup() {
                return {
                    ...useCount()
                }
            }
        })
        app.mount('#app')
    </script>
</body>

Composition API 生命周期 reactive toRefs ref demo:

<body>
    <div id="app">
        x: {{x}}<br />
        y: {{y}}
    </div>
    <script type="module">
        import { createApp, reactive, onMounted, onUnmounted, toRefs } from './node_modules/vue/dist/vue.esm-browser.js'
        function useMousePosition() {
            let position = reactive({
                x: 0,
                y: 0
            })
            const update = (e) => {
                position.x = e.pageX
                position.y = e.pageY
            }
            onMounted(() => {
                window.addEventListener('mousemove', update)
            })
            onUnmounted(() => {
                window.removeEventListener('mousemove', update)
            })
            return toRefs(position)
        }
        const app = createApp({
            setup() {
                // const position = useMousePosition()
                const { x, y } = useMousePosition()
                return { x, y }
            }
        })
        app.mount('#app')
    </script>
</body>

computed

<body>
    <div id="app">
        <button @click="push">按钮</button>
        未完成:{{activeCount}}
    </div>
    <script type="module">
        import { createApp, reactive, computed } from './node_modules/vue/dist/vue.esm-browser.js'
        const data = [
            { text: '看书', completed: false },
            { text: '敲代码', completed: false },
            { text: '约会', completed: true }
        ]
        const app = createApp({
            setup() {
                const todos = reactive(data)
                const activeCount = computed(() => {
                    return todos.filter((item) => !item.completed).length
                })
                return {
                    activeCount,
                    push:()=>{
                        todos.push({
                            text: '看电视',
                            completed: false
                        })
                    }
                }
            }
        })
        app.mount('#app')
    </script>
</body>

watch

Vue.js 3.x Composition APIs 及简单使用

<body>
    <div id="app">
        <p>
            请问一个 yes/no 的问题:
            <input v-model="question">
        </p>
        <p>
            {{answer}}
            <img :src="img">
        </p>
    </div>
    <script type="module">
        // https://www.yesno.wtf/api
        import { createApp, ref, watch } from './node_modules/vue/dist/vue.esm-browser.js'
        const app = createApp({
            setup() {
                const question = ref('')
                const answer = ref('')
                const img = ref('')
                watch(question, async (newValue, oldValue)=>{
                    console.log()
                    const response = await fetch('https://www.yesno.wtf/api')
                    const {answer: as, image: src} = await response.json()
                    answer.value = as
                    img.value = src
                })
                return {
                    question,
                    answer,
                    img
                }
            }
        })
        app.mount('#app')
    </script>
</body>

watchEffect

Vue.js 3.x Composition APIs 及简单使用

<body>
    <div id="app">
        <button @click="increase">increase</button>
        <button @click="stop">stop</button>
        <br>
        {{count}}
    </div>
    <script type="module">
        // https://www.yesno.wtf/api
        import { createApp, ref, watchEffect } from './node_modules/vue/dist/vue.esm-browser.js'
        const app = createApp({
            setup() {
                const count = ref(0)
                const stop = watchEffect(()=>{
                    console.log(count.value)
                })
                return {
                    count,
                    stop,
                    increase:()=>{
                        count.value ++
                    }
                }
            }
        })
        app.mount('#app')
    </script>
</body>

todoList

todoList - 功能演示

Vue.js 3.x Composition APIs 及简单使用
Vue.js 3.x Composition APIs 及简单使用

todoList - demo

vue 代码:

<template>
  <section id="app" class="todoapp">
    <header class="header">
      <h1>todos</h1>
      <input
        class="new-todo"
        placeholder="请输入代办项目"
        autocomplete="off"
        autofocus
        v-model="input"
        @keyup.enter="addTodo"
      />
    </header>
    <section class="main" v-show="count">
      <input id="toggle-all" class="toggle-all" type="checkbox" v-model="allDone"/>
      <label for="toggle-all">Mark all as complete</label>
      <ul class="todo-list">
        <li
          v-for="todo in filteredTodos"
          :key="todo"
          :class="{ editing: todo === editingTodo, completed: todo.completed }"
        >
          <div class="view">
            <input class="toggle" type="checkbox" v-model="todo.completed"/>
            <label @dblclick="editTodo(todo)">{{ todo.text }}</label>
            <button class="destroy" @click="remove(todo)"></button>
          </div>
          <input
            class="edit"
            type="text"
            v-editing-focus="todo === editingTodo"
            v-model="todo.text"
            @keyup.enter="doneEdit(todo)"
            @blur="doneEdit(todo)"
            @keyup.esc="cancelEdit(todo)"
          />
        </li>
      </ul>
    </section>
    <footer class="footer" v-show="count">
      <span class="todo-count"> <strong>{{remainingCount}}</strong> {{remainingCount > 1 ? 'items' : 'item'}} left(剩余) </span>
      <ul class="filters">
        <li><a href="#/all">全部</a></li>
        <li><a href="#/active">待完成</a></li>
        <li><a href="#/completed">已完成</a></li>
      </ul>
      <button class="clear-completed" @click="removeCompleted" v-show="count > remainingCount">Clear completed</button>
    </footer>
  </section>
  <footer class="info">
    <p>双击编辑单个项目</p>
    <!-- Remove the below line ↓ -->
    <p>Template by <a href="http://sindresorhus.com">Sindre Sorhus</a></p>
    <!-- Change this out with your name and url ↓ -->
    <p>Created by <a href="https://www.lagou.com">教瘦</a></p>
    <p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
  </footer>
</template>
<script>
import "@/assets/index.css";
import useLocalStorage from "./utils/useLocalStorage";
import { computed, onMounted, onUnmounted, ref, watchEffect } from "vue";
const storage = useLocalStorage()
// 添加代办事项
const useAdd = (todos) => {
  const input = ref("");
  const addTodo = () => {
    const text = input.value && input.value.trim();
    if (text.length === 0) return;
    todos.value.unshift({
      text,
      completed: false,
    });
    input.value = "";
  };
  return {
    input,
    addTodo,
  };
};
// 删除代办事项
const useRemove = (todos) => {
  const remove = (todo) => {
    const index = todos.value.indexOf(todo);
    todos.value.splice(index, 1);
  };
  const removeCompleted = ()=>{
    todos.value = todos.value.filter(todo=>!todo.completed)
  }
  return { remove, removeCompleted };
};
// 编辑代办事项
const useEdit = (remove) => {
  // 1、双击待办事项,展示文本框
  // 2、按回车或者编辑文本框失去焦点,修改数据
  // 3、按ESC取消编辑
  // 4、把编辑文本框清空,按回车,删除这一项
  // 5、显示编辑文本框的时候,获取焦点
  let beforeEditingText = ""; // 编辑之前的数据
  const editingTodo = ref(null); // 正在编辑的对象,标识编辑的状态
  const editTodo = (todo) => {
    beforeEditingText = todo.text;
    editingTodo.value = todo;
  };
  const doneEdit = (todo) => {
    if (!editingTodo.value) return;
    todo.text = todo.text.trim();
    todo.text || remove(todo);
    editingTodo.value = null;
  };
  const cancelEdit = (todo) => {
    editingTodo.value = null;
    todo.text = beforeEditingText;
  };
  return {
    editingTodo,
    editTodo,
    doneEdit,
    cancelEdit,
  };
};
/**
 * 切换代办项完成状态
 * 1、点击 checkbox 改变所有代办项状态
 * 2、All/Active/Completed
 * 3、其他
 * 3-1、显示未完成代办项个数
 * 3-2、移除所有已完成项目
 * 3-3、如果没有代办项,隐藏 main 和 footer
 */
const useFilter = todos => {
  const allDone = computed({
    get(){
      return !todos.value.filter(todo=>!todo.completed).length
    },
    set(value){
      todos.value.forEach(todo=>{
        todo.completed = value
      })
    }
  })

  const filter = {
    all: list => list,
    active: list=>list.filter(todo=>!todo.completed),
    completed: list=>list.filter(todo=>todo.completed)
  }
  const type = ref('all')
  const filteredTodos = computed(()=>filter[type.value](todos.value))
  const remainingCount = computed(()=>filter.active(todos.value).length)
  const count = computed(()=>todos.value.length)
  const onHashChange = ()=>{
    const hash = window.location.hash.replace('#/','')
    if(filter[hash]){
      type.value = hash
    } else {
      type.value = 'all'
      window.location.hash = ''
    }
  }
  onMounted(()=>{
    window.addEventListener('hashchange',onHashChange)
    onHashChange()
  })
  onUnmounted(()=>{
    window.removeEventListener('hashchange', onHashChange)
  })
  return {
    count,
    allDone,
    filteredTodos,
    remainingCount
  }
}

// 存储待办事项
const useStorage = ()=>{
  const KEY = 'TODOKEYS'
  const todos = ref(storage.getItem(KEY) || [])
  watchEffect(()=>{
    storage.setItem(KEY, todos.value)
  })
  return todos
}

export default {
  name: "App",
  setup() {
    // const todos = ref([]);
    const todos = useStorage();
    const { remove, ...removes } = useRemove(todos);
    return {
      todos,
      remove,
      ...removes,
      ...useAdd(todos),
      ...useEdit(remove),
      ...useFilter(todos)
    };
  },
  directives: {
    editingFocus: (el, binding)=>{
      binding.value && el.focus()
    }
  }
};
</script>
<style scoped>
</style>

index.css

html,
body {
	margin: 0;
	padding: 0;
}

button {
	margin: 0;
	padding: 0;
	border: 0;
	background: none;
	font-size: 100%;
	vertical-align: baseline;
	font-family: inherit;
	font-weight: inherit;
	color: inherit;
	-webkit-appearance: none;
	appearance: none;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
}

body {
	font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
	line-height: 1.4em;
	background: #f5f5f5;
	color: #111111;
	min-width: 230px;
	max-width: 550px;
	margin: 0 auto;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	font-weight: 300;
}

:focus {
	outline: 0;
}

.hidden {
	display: none;
}

.todoapp {
	background: #fff;
	margin: 130px 0 40px 0;
	position: relative;
	box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),
	            0 25px 50px 0 rgba(0, 0, 0, 0.1);
}

.todoapp input::-webkit-input-placeholder {
	font-style: italic;
	font-weight: 300;
	color: rgba(0, 0, 0, 0.4);
}

.todoapp input::-moz-placeholder {
	font-style: italic;
	font-weight: 300;
	color: rgba(0, 0, 0, 0.4);
}

.todoapp input::input-placeholder {
	font-style: italic;
	font-weight: 300;
	color: rgba(0, 0, 0, 0.4);
}

.todoapp h1 {
	position: absolute;
	top: -140px;
	width: 100%;
	font-size: 80px;
	font-weight: 200;
	text-align: center;
	color: #b83f45;
	-webkit-text-rendering: optimizeLegibility;
	-moz-text-rendering: optimizeLegibility;
	text-rendering: optimizeLegibility;
}

.new-todo,
.edit {
	position: relative;
	margin: 0;
	width: 100%;
	font-size: 24px;
	font-family: inherit;
	font-weight: inherit;
	line-height: 1.4em;
	color: inherit;
	padding: 6px;
	border: 1px solid #999;
	box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
	box-sizing: border-box;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
}

.new-todo {
	padding: 16px 16px 16px 60px;
	border: none;
	background: rgba(0, 0, 0, 0.003);
	box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03);
}

.main {
	position: relative;
	z-index: 2;
	border-top: 1px solid #e6e6e6;
}

.toggle-all {
	width: 1px;
	height: 1px;
	border: none; /* Mobile Safari */
	opacity: 0;
	position: absolute;
	right: 100%;
	bottom: 100%;
}

.toggle-all + label {
	width: 60px;
	height: 34px;
	font-size: 0;
	position: absolute;
	top: -52px;
	left: -13px;
	-webkit-transform: rotate(90deg);
	transform: rotate(90deg);
}

.toggle-all + label:before {
	content: '❯';
	font-size: 22px;
	color: #e6e6e6;
	padding: 10px 27px 10px 27px;
}

.toggle-all:checked + label:before {
	color: #737373;
}

.todo-list {
	margin: 0;
	padding: 0;
	list-style: none;
}

.todo-list li {
	position: relative;
	font-size: 24px;
	border-bottom: 1px solid #ededed;
}

.todo-list li:last-child {
	border-bottom: none;
}

.todo-list li.editing {
	border-bottom: none;
	padding: 0;
}

.todo-list li.editing .edit {
	display: block;
	width: calc(100% - 43px);
	padding: 12px 16px;
	margin: 0 0 0 43px;
}

.todo-list li.editing .view {
	display: none;
}

.todo-list li .toggle {
	text-align: center;
	width: 40px;
	/* auto, since non-WebKit browsers doesn't support input styling */
	height: auto;
	position: absolute;
	top: 0;
	bottom: 0;
	margin: auto 0;
	border: none; /* Mobile Safari */
	-webkit-appearance: none;
	appearance: none;
}

.todo-list li .toggle {
	opacity: 0;
}

.todo-list li .toggle + label {
	/*
		Firefox requires `#` to be escaped - https://bugzilla.mozilla.org/show_bug.cgi?id=922433
		IE and Edge requires *everything* to be escaped to render, so we do that instead of just the `#` - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7157459/
	*/
	background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E');
	background-repeat: no-repeat;
	background-position: center left;
}

.todo-list li .toggle:checked + label {
	background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E');
}

.todo-list li label {
	word-break: break-all;
	padding: 15px 15px 15px 60px;
	display: block;
	line-height: 1.2;
	transition: color 0.4s;
	font-weight: 400;
	color: #4d4d4d;
}

.todo-list li.completed label {
	color: #cdcdcd;
	text-decoration: line-through;
}

.todo-list li .destroy {
	display: none;
	position: absolute;
	top: 0;
	right: 10px;
	bottom: 0;
	width: 40px;
	height: 40px;
	margin: auto 0;
	font-size: 30px;
	color: #cc9a9a;
	margin-bottom: 11px;
	transition: color 0.2s ease-out;
}

.todo-list li .destroy:hover {
	color: #af5b5e;
}

.todo-list li .destroy:after {
	content: '×';
}

.todo-list li:hover .destroy {
	display: block;
}

.todo-list li .edit {
	display: none;
}

.todo-list li.editing:last-child {
	margin-bottom: -1px;
}

.footer {
	padding: 10px 15px;
	height: 20px;
	text-align: center;
	font-size: 15px;
	border-top: 1px solid #e6e6e6;
}

.footer:before {
	content: '';
	position: absolute;
	right: 0;
	bottom: 0;
	left: 0;
	height: 50px;
	overflow: hidden;
	box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2),
	            0 8px 0 -3px #f6f6f6,
	            0 9px 1px -3px rgba(0, 0, 0, 0.2),
	            0 16px 0 -6px #f6f6f6,
	            0 17px 2px -6px rgba(0, 0, 0, 0.2);
}

.todo-count {
	float: left;
	text-align: left;
}

.todo-count strong {
	font-weight: 300;
}

.filters {
	margin: 0;
	padding: 0;
	list-style: none;
	position: absolute;
	right: 0;
	left: 0;
}

.filters li {
	display: inline;
}

.filters li a {
	color: inherit;
	margin: 3px;
	padding: 3px 7px;
	text-decoration: none;
	border: 1px solid transparent;
	border-radius: 3px;
}

.filters li a:hover {
	border-color: rgba(175, 47, 47, 0.1);
}

.filters li a.selected {
	border-color: rgba(175, 47, 47, 0.2);
}

.clear-completed,
html .clear-completed:active {
	float: right;
	position: relative;
	line-height: 20px;
	text-decoration: none;
	cursor: pointer;
}

.clear-completed:hover {
	text-decoration: underline;
}

.info {
	margin: 65px auto 0;
	color: #4d4d4d;
	font-size: 11px;
	text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
	text-align: center;
}

.info p {
	line-height: 1;
}

.info a {
	color: inherit;
	text-decoration: none;
	font-weight: 400;
}

.info a:hover {
	text-decoration: underline;
}

/*
	Hack to remove background from Mobile Safari.
	Can't use it globally since it destroys checkboxes in Firefox
*/
@media screen and (-webkit-min-device-pixel-ratio:0) {
	.toggle-all,
	.todo-list li .toggle {
		background: none;
	}

	.todo-list li .toggle {
		height: 40px;
	}
}

@media (max-width: 430px) {
	.footer {
		height: 50px;
	}

	.filters {
		bottom: 10px;
	}
}

utils/useLocalStorage.js

function parse(str){
  let value
  try{
    value = JSON.parse(str)
  }catch{
    value = null
  }
  return value
}
function stringify(obj){
  let value
  try{
    value = JSON.stringify(obj)
  }catch{
    value = null
  }
  return value
}

export default function useLocalStorage(){
  function setItem(key, value){
    value = stringify(value)
    window.localStorage.setItem(key, value)
  }
  function getItem(key){
    let value = window.localStorage.getItem(key)
    if(value){
      value = parse(value)
    }
    return value
  }
  return {
    setItem,
    getItem
  }
}

环境&依赖

node 18.16.0
vue 3.3.2

自定义指令一、
Vue.js 3.x Composition APIs 及简单使用
自定义指令二、
Vue.js 3.x Composition APIs 及简单使用文章来源地址https://www.toymoban.com/news/detail-476356.html

到了这里,关于Vue.js 3.x Composition APIs 及简单使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Js-web APIs(一)

    目录 Web API 基本认知 • 作用和分类 • 什么是DOM • DOM树 • DOM对象(重要) 获取DOM对象 • 根据CSS选择器来获取DOM元素 (重点) 1.选择匹配的第一个元素  2.选择匹配的多个元素 • 其他获取DOM元素方法(了解) 操作元素内容 • 对象.innerText 属性 • 对象.innerHTML 属性 操作元素属

    2024年01月17日
    浏览(38)
  • Mastering RESTful APIs with Node.js

    作者:禅与计算机程序设计艺术 REST (Representational State Transfer) 表述性状态转移 是一种基于HTTP协议的软件架构风格,旨在通过设计简单、灵活的接口来提升互联网应用的可伸缩性、可用性及安全性。RESTful API是遵循REST风格设计的API。本教程将介绍如何使用Node.js构建RESTful API并

    2024年02月07日
    浏览(35)
  • Vue 3 Composition API 详解

    在Vue 3中,引入了一个新的Composition API,旨在提供一种更灵活和可重用的方式来组织组件代码。Composition API基于函数式编程思想,允许开发者将逻辑和状态管理逻辑分离,使代码更加清晰和可维护。 响应式数据 在Vue 3中,响应式数据是组件状态的重要组成部分。通过使用 re

    2024年01月21日
    浏览(41)
  • VUE使用Three.js实现模型,点击交互,相机旋转视角跟随移动(Threejs中使用Tweenjs,含demo源码)

    目录 一、Three.js是什么? 二、VUE简单使用Three.js步骤 1.npm安装 2.template模板 3.引入库 4.定义全局变量 5.初始化场景 6.初始化相机 7.初始化灯光 8.初始化渲染器 9.创建模型(这里我搭建的模型是一个简单双面货架模型) 10.根据浏览器窗口自适应 11.初始化函数,页面加载完成时调用

    2024年02月03日
    浏览(69)
  • 详解Vue 3 的 Composition API

    Vue 3 的 Composition API 是一种新的组合式 API 风格,它可以更好地组织和复用组件逻辑。相比于 Vue 2 的 Options API,Composition API 提供了更灵活和可组合的方式来编写组件。 下面是 Composition API 的一些特点和优势: 函数式组件:Composition API 支持使用函数式组件的方式来编写组件。

    2024年02月10日
    浏览(37)
  • 【vue3】11-Vue 3中的Composition Api(一)

    在Vue2中,我们编写组件的方式是Options APl: Options API的一大特点就是在 对应的属性 中编写 对应的功能模块 ; 比如 data定义数据 、 methods中定义方法 、 computed中定义计算属性 、 watch中监听属性改变 ,也包括 生命周期钩子 ; 但是这种代码有一个很大的弊端: 当我们 实现某一个功

    2024年02月08日
    浏览(42)
  • 从Vue2到Vue3【一】——Composition API(第一章)

    内容 链接 从Vue2到Vue3【零】 Vue3简介 从Vue2到Vue3【一】 Composition API(第一章) 从Vue2到Vue3【二】 Composition API(第二章) 从Vue2到Vue3【三】 Composition API(第三章) 从Vue2到Vue3【四】 Composition API(第四章) Vue3作为Vue.js框架的最新版本,引入了许多令人激动的新特性和改进。其

    2024年02月16日
    浏览(32)
  • AngularJS 和 Vue.JS区别

    AngularJS 和 Vue.JS 都是流行的 JavaScript 框架,用于构建 Web 应用程序。以下是它们之间的一些主要区别: AngularJS 由 Google 的前雇员 Misko Hevery 开发,并于 2009 年首次发布。它是一种基于 JavaScript 的前端框架,用于构建动态 Web 应用程序。AngularJS 的最新版本是 Angular 14。 Vue.JS 由中

    2024年02月14日
    浏览(45)
  • Vue 2和Vue 3路由Router创建的区别简记(在main.js文件中引入的区别和router的js文件中创建语法的区别)

    1、版本的搭配: Vue 2到Vue 3的改版升级,同样的带来Vue Router的升级。创建Vue项目之后,我们可以在package.json文件中看到,Vue 2创建的项目往往是与Vue Router 3.X版本搭配的,而Vue 3创建的项目与Vue Router 4.X版本搭配。 Vue 3搭配Vue Router 4.X版本: Vue 2搭配Vue Router3.X版本: 2、在main

    2024年02月08日
    浏览(60)
  • 从Vue2到Vue3【二】——Composition API(第二章)

    内容 链接 从Vue2到Vue3【零】 Vue3简介 从Vue2到Vue3【一】 Composition API(第一章) 从Vue2到Vue3【二】 Composition API(第二章) 从Vue2到Vue3【三】 Composition API(第三章) 从Vue2到Vue3【四】 Composition API(第四章) Vue3作为Vue.js框架的最新版本,引入了许多令人激动的新特性和改进。其

    2024年02月17日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包