一、项目搭建
vite是尤大大开发的一款意图取代webpack的工具。其实现原理是利用ES6的import发送请求加载文件的特性。拦截这些请求,做一些编译,省去webpack冗长的打包时间。并将其与Rollup捆绑在一起用于生产。 在开发过程中没有捆绑。源代码中的ES Import语法直接提供给浏览器,浏览器通过本机<script module>
支持对其进行解析,从而为每次导入发出HTTP请求。开发服务器拦截请求,并在必要时执行代码转换。例如,对*.vue
文件的导入会在发送回浏览器之前即时进行编译。
1、全局安装vite脚手架
npm install -g create-vite-app
2、使用脚手架创建项目
create-vite-app projectName
3、进入项目文件夹
cd projectName
4、安装依赖
npm install
5、启动vue3.0项目
npm run dev
二、vue2.x存在的问题
2.x中的一点问题是当业务不断增多时,数据跟逻辑分散,会很难维护。
<template> <div> <div> <input type="text" v-model="obj.id"> <input type="text" v-model="obj.con"> <button @click="submit">提 交</button> </div> <ul> <li v-for="(item,index) in list" :key="item.id" @click="cli(index)"> {{item.id}}-{{item.con}} </li> </ul> </div> </template> <script> export default { name:"filterBox", data(){ return { list:[ { id:1, con:"a" }, { id:2, con:"b" } ], obj:{ id:"", con:"" } // 代码数据1 // 代码数据2 // ... } }, methods:{ cli(index){ this.list = this.list.filter((item,idx)=>idx!==index); console.log(this.list); }, submit(){ // const obj = Object.assign({},this.obj); this.list.push(this.obj); this.obj.id = ""; this.obj.con = ""; }, // 执行代码代码逻辑3 // ... }, computed:{ // 执行代码代码逻辑1 }, watch:{ // 执行代码逻辑2 } } </script> <style> </style>
三、组合API
ref
<template> <div> <p>{{count}}</p> <button @click="add">add</button> </div> </template> <script> import {ref} from "vue" export default { name: 'App', setup(){ // 定义一个名称叫做count变量,这个变量的初始值是0 // 这个变量发生该改变之后,vue会自动更新页面。 const count = ref(0); // 在组合API中,如果想定义方法,不用定义到methods中,直接在setup函数中定义即可。 const add = () => { count.value+=1; } // 在组合API中定义的变量/方法,要想在外界使用,必须return出去。 return { count, add } } } </script>
ref
只能监听简单类型的变化,不能监听复杂类型的变化(对象/数组)。 它的本质是reactive
,当我们给ref函数传递一个值时,ref
函数会自动将ref
转换成reactive
。
ref(0) --> reactive({ value:0 })
另外,需要注意的是,如果是通过ref
创建出来的数据,那么在template
中使用的时候不用通过.value
来获取。因为Vue会自动给我们添加.value
。
那么vue是如何决定是否需要自动添加.value
的。vue在解析数据之前,会自动判断这个数据是否是ref
类型的,如果是就自动添加.value
,如果不是就不自动添加.value
。
vue是如何判断当前的数据是否是ref类型的? 通过当前数据的__v_ref
来判断的,如果有这个私有的属性,并且取值为true
,那么就代表是一个ref
类型的数据。
那么我们开发者也有自己api来判断。isRef(数据)
,返回true
或者是false
。
import {isRef} from 'vue'
reactive
reactive
可以监听复杂类型的变化,如对象或者数组。
let state = reactive({ name:"maomin" }); // 或 let arr = reactive([1,2,3]);
<template> <div> <ul> <li v-for="(item,index) in state.list" :key="item.id" @click="removeItem(index)">{{item.id}}--{{item.con}}</li> </ul> </div> </template> <script> import {reactive} from "vue" export default { name: 'App', setup(){ const state = reactive({ list:[ { id:1, con:"A" }, { id:2, con:"B" }, { id:3, con:"C" } ] }); const removeItem = (index) => { state.list = state.list.filter((item,i)=>i!==index) } return { state, removeItem } } } </script>
我们可以改变下,把数据跟逻辑放在一块,这样就解决了vue2.x的数据跟逻辑分散的问题。
<template> <div> <ul> <li v-for="(item, index) in state.list" :key="item.id" @click="removeItem(index)" > {{ item.id }}--{{ item.con }} </li> </ul> </div> </template> <script> import { reactive } from "vue"; export default { name: "App", setup() { let {state,removeItem} = userReturn(); return { state, removeItem, }; }, }; function userReturn(params) { const state = reactive({ list: [ { id: 1, con: "A", }, { id: 2, con: "B", }, { id: 3, con: "C", }, ], }); const removeItem = (index) => { state.list = state.list.filter((item, i) => i !== index); }; return {state,removeItem} } </script>
我们实现了上面的删除功能,那我们在实现一个添加的功能。
<template> <div> <input type="text" v-model="state2.items.id"> <input type="text" v-model="state2.items.con"> <button @click="addItem">添加</button> <ul> <li v-for="(item, index) in state.list" :key="item.id" @click="removeItem(index)" > {{ item.id }}--{{ item.con }} </li> </ul> </div> </template> <script> import { reactive } from "vue"; export default { name: "App", setup() { let {state,removeItem} = userRemove(); let {state2,addItem} = userAdd(state); return { state, removeItem, state2, addItem }; }, }; // 添加 function userAdd(state) { const state2 = reactive({ items:{ id:"", con:"" } }); const addItem = () => { const items = Object.assign({},state2.items); state.list.push(items); state2.items.id = ""; state2.items.con = ""; }; return {state,state2,addItem} } // 删除 function userRemove(params) { const state = reactive({ list: [ { id: 1, con: "A", }, { id: 2, con: "B", }, { id: 3, con: "C", }, ], }); const removeItem = (index) => { state.list = state.list.filter((item, i) => i !== index); }; return {state,removeItem} } </script>
如果是其他对象,默认情况下修改对象,界面不会更新。
<template> <div> <p>{{state.time}}</p> <button @click="add">加一天</button> </div> </template> <script> import {reactive} from 'vue' export default { name:"Demo4", setup(){ const state = reactive( { time:new Date() } ); function add () { state.time.setDate(state.time.getDate()+1); console.log(state); } return { state, add } } } </script> <style> </style>
如果想更新,可以通过重新赋值的方法。
<template> <div> <p>{{ state.time }}</p> <button @click="add">加一天</button> </div> </template> <script> import { reactive } from "vue"; export default { name: "Demo4", setup() { const state = reactive({ time: new Date(), }); function add() { const newTime = new Date(state.time.getTime()); newTime.setDate(state.time.getDate() + 1); state.time = newTime; console.log(state); } return { state, add, }; }, }; </script> <style> </style>
同样,我们开发者如果要是检测一个数据是否是reactive
类型的。可以用isReactive(数据)
,返回true
或者false
。
import {isReactive} from 'vue'
四、组合API本质
compositionAPI
与optionAPI
可以混合使用。其本质是注入。
<template> <div> <p>Vue2.x</p> <button @click="cli1">点击</button> <p>Vue3.0</p> <button @click="cli2">点击</button> </div> </template> <script> import {ref} from "vue" export default { name:"Demo2", data(){ return { msg:"Vue2.x" } }, methods:{ cli1(){ alert(this.msg); } }, setup(){ let txt = ref("Vue3.0"); // 注入到data函数内 function cli2() { // 注入到methods属性内 alert(txt.value); } return { txt, cli2 } } } </script> <style> </style>
五、setup执行时机与注意事项
setup函数,是在beforecreate
钩子之前完成的。所以无法使用data
跟methods
。 另外要注意的是setup是同步的,不是异步的。
<template> <div> <button @click="name">打开</button> </div> </template> <script> export default { name:"Demo3", data(){ return { msg:"hello" } }, setup(){ function name() { console.log(this.msg); // undefined } return { name } } } </script> <style> </style>