vue各个版本和react不同,用表格归类,方便记忆。
说明 | vue2 | vue3 | vue3.2 | react16类组件 | react16.8函数组件 |
---|---|---|---|---|---|
1.生命周期 | 1、beforecreate;2、created;3、beforemount;4、mounted;5、beforeupdate;6、updated;7、beforedestroy;8、destroyed;9、activated;10、deactivated; | setup代替了前两个beforeCreate、created,setup调用在beforecreate之前。setup() { const count = ref(0); onMounted(() => {}); onUnmounted(() => { }等等); | beforeCreate、created、beforeMount、Mounted、beforeUpdate、updated、beforeDestroy、destroy | 一:constructor、getDerivedstatefromprops、render、didMount;二:prop和state、getDerivedstatefromprops、render、didUpdate三:willunmount | useEffect三种状态,据第二个参数:1.[],2.空 3.return; userState; 4.useMemo则可以看作是componentWillUpdate |
2.结构形式 | 生命周期、component等分类 | import {com***} from vue 《script》 setup(props,context){const { attrs, slots, emit, expose } = context} return{// 想在tempate里面使用需要在setup内return暴露出来,麻烦}; setup 在创建我们的组件实例之前运行,我们将无法访问这三个组件属性data computed methods | 《script setup》,不用写export default{}、return{}。新增且必须使用 defineProps 、defineEmits API、defineExpose、defineStore;const slots = useSlots(); const attrs = useAttrs() | constructor(props){super(props) this.state={} render(){return 《p>{message}Hello, React 《/p>}}} 、《Fragment>《/Fragment> 可以加key,<></>不可以加key | function SayHi({ message }) { return 《p>{message}Hello, React《/p>} |
3.响应data | data(){} | const data = ref({…})、const data = reactive({…}) | 同左 | state = {count:0};this.setState( state => ({count:state.count+1})) | const [value, setValue] = useState(“”) |
4.性能优化 | 自带SCU | 自带SCU | 自带SCU | shouldComponentUpdate | React.memo()、useMemo+useCallback |
5.ref | ref绑定子组件 | 1.绑定子组件,获取子组件的方法属性 2.绑定响应式数据 .value | 1.绑定子组件,获取子组件的方法属性,子组件defineExpose 2.绑定响应式数据 .value 其他ref的API:isRef、toRef、toRefs、triggleRef、customRef 、storeToRefs | 1.stringRef通过 this.refs.传入的字符串格式获取对应的元素;《h2 ref=“titleRef”>Hello React《/h2>this.refs.titleRef.innerHTML = ‘zepp’ 2.this.titleRef = createRef(); = React.createRef(); this.titleRef.current.innerHTML = ‘zep~’ | 函数式组件是没有实例的,所以无法通过ref获取他们的实例一、const inputRef = useRef(null) inputRef.current 不需要响应render 2.获取子组件的属性方法; 让函数组件拥有ref 二、在父级创建ref:my = createRef();2.在父级引入child之后使用时增加ref 3.在子组件函数的第二个参数是ref 4.使用React.forwarRef()高阶组件 5.接收到的ref作为某个元素的属性值,属性名为ref ;三、useImperativeHandle(ref, () => {return {// … your methods … };}, []); |
6.teleport | 弹窗用 | 弹窗用 | 弹窗用 | ReactDOM.createPortal | 同左边 |
7.传参 | props、emit、refs、provide&inject(用computed实现响应)、vuex(even-bus、pub-sub、localstorage) | setup(props,context){context.attrs,context.emit,context.expose,context.slots} (even-bus、pub-sub、localstorage); return{} | defineProps([“width”, “height”])、const emits = defineEmits([‘fun’]); emits(‘gatewayData’, label.value)、defineExpose({state1,play2});(even-bus、pub-sub、localstorage) | 父传子props、父子互传ref 、跨级或同级context、同级也可以EventBus。props、React.createContext->context.Provider(computed、toRef实现响应数据)->context.Consumer爷孙、(parentcomponent、pub-sub、localstorage) | 爷孙createContext(…)->context.provide value={{…data}}->useContext、ref、redux (parentcomponent、pub-sub、localstorage) |
7.1.父组件操作子组件方法 | this.$refs[‘xxx’] | 父组件ref,const input = ref(null);input.value.fun();ref=“input” 子组件setup(props,{expose}){expose({fun,data})} | defineExpose({ fun}) | childRef = React.createRef(); this.childRef.current.sendMessage() ref={this.childRef};或者《Child ref=‘childData’>《/Child> this.refs.childData.run();//拿到子组件中runn方法;二、如果子组件包含HOC,需要用onRef修改thiscomponentDidMount(){this.props.onRef && this.props.onRef(this);} | const inputRef = useRef(null); 《child ref={this.inputRef}》 forwardRef(function Counter({ num }, ref) { useImperativeHandle(ref, () => {})}) |
7.2.子操作父组件 | emit,props | setup(props, context){ props.name; //通过context下面的emit进行事件传递 context.emit(‘hello’,‘子组件参数:哈哈哈’)} | defineProps() 和 defineEmits()、defineExpose();useSlots | createContext-> context.provider ->useContext;子组件toParent =()=>{ this.props.toParent}《div onClick={this.toParent}》父组件:《Child toParent={this.toParent}》 | 子组件 forwardRef(props, ref) =>{props.toParent()}父组件 《Child toParent={toParent}》 |
8.watch事件 | watch | watch默认深度监听,如果不是响应数据才写deep:true、watchEffect(不用指定监听对象、访问不到修改之前的值) | 同左 | componentDidUpdate(prevProps, prevState) { if (prevState.name !== this.state.name) { console.log(‘Name changed to:’, this.state.name) } } | useEffect(() => { console.log(name: ${data.name} );}, [data.name]) |
9.computed | 有 | 有 | 有 | get computed() { return this.props.value } | const computed = useMemo(() => handler(value), [value]) |
10.兄弟组件传值 | event bus、PubSub.publish() | event bus、PubSub.publish() | eventbus、PubSub.publish() | parent component、EventBus库、PubSub.publish() | parent component、EventBus库、PubSub.publish() |
11.slot | slot、匿名、具名、作用域(父读子参数,子:data=“item” 父 v-slot="data"或者#default=‘data’) | 在vue2基础增加动态名字插槽 #[name] let name=ref(‘duan’)、setup第二个参数的context.slots、等价attrs | 同左,useSlots()的返回值与 $slots 和 setup的context.slots 等价,Ts,vue3.3才能用defineSlots() | 子组件{this.props.children[0]} | 没有this {props.children[0]} |
12.this | 有 | 无,let proxy = getCurrentInstance();proxy.$refs[“test”] | 同左 | this,需要bind 1.constructor中this.btnClick = this.btnClick.bind(this)、2.箭头函数btnClickTwo =()=>{console.log( this )} 3.《div onClick={(event) => this.handleClick(“过火”, “上火”, event)} >点我《/div> 4.onClick={this.handleClick1.bind( this )}推荐后两种写法 | 没有 |
13.innerHtml | v-html | v-html | v-html | <div dangerouslySetInnerHTML={{ __html: ‘《div》123《/div》’ }} /> | 《div dangerouslySetInnerHTML={{ __html: ‘《div>123《/div>’ }} /> |
14.根目录render | 只能有一个vue实例。vue2new Vue({ render: h => h(App)}).$mount(‘#app’);template+render | 可以有多个vue实例。createApp(App).mount(‘#app’) | 同左 | ReactDOM.render(<React.StrictMode>《App /></React.StrictMode>,document.getElementById(“root”)😉; render(){return()} | 同左 |
15.ssr | nuxt | nuxt | nuxt | next | next |
16.路由 | 应用场景:1.登录token是否存在,if(haveToken===true){next()}else{next(‘/login’)}2.请求数据,成功next(),失败next(‘/404’), 3.做统一的弹框 | 在setup()上面写createRouter(), beforeEach等路由 | 另外创建《script>写beforeRouteEnter等。setup里面写useRouter(),userRouter.push({}),beforeEach等路由, | 没有路由守卫,高阶组件 进行包裹,或者用react-router-config这个库实现。路由:import { Switch, Route, Redirect,withRouter,Link,NavLink,useParams } from ‘react-router-dom’; params路由上的参数 | 同左 |
常用路由api | new Vue Router(), 全局4个:1.router.beforeEach 2.router.beforeResolve 3.router.afterEach 4.router.beforeEnter,局部组件用 beforeRouteEnter, beforeRouteUpdate,beforeRouteLeave (to, from, next) { next() // 在beforeCreate前,还不能取到this } | import { useRouter } from ‘vue-router’; const router = useRouter(); router.push({ name: ‘user’, params: { userId: ‘123’ }}) | 同左 | 1.路由鉴权:《Route> render={()=>{if(){return 《Dashboard />}else{return 《Redirect to=“/login” />}}}2.《Redirect to=‘/login’>《/Redirect>3.《PrivateRoute path=‘/orderdetail’ component={Orderdetail}>《/PrivateRoute>4.requireAuth5.导航守卫React Router 4.0以下 ,提供了onEnter和onLeave钩子函数。6.《Switch>《Route path=‘map’ component={Map} onEnter={enterTab.bind(this)} onLeave={leaveTab.bind(this)}>《/Route>《Redirect to=“/404” />《Switch> | 同左 |
路由模式选择 | 1.history模式:1.1.通过 history.pushState 使用它做页面跳转不会触发页面刷新。1.2.刷新会丢失,所以需要配置vue.config.js mode=history,服务器也得配置。2.hash模式 2.1有#,2.2 window.onhashchange方法获取新URL中hash值 | 同左 | 同左 | 同左 | 同左 |
17. useMemo | computed | useMemo | useMemo | React.memo | useMemo(calculateValue, dependencies) |
18.Diff | 1.同层比较,采用双指针头对尾两端对比的方式;2.全量diff,然后移动节点时通过 splice 进行数组操作 | 1.同层比较,采用双指针头对尾两端对比的方式;2.增量diff;在编译阶段提前标记静态节点,Diff 过程中直接跳过有静态标记的节点,并且使用最长递增子序列算法优化了对比流程,快速 Diff | 同左 | 1.Fiber链表结构树;2.新增打上标记,增量比较,3.异步操作。4.多节点比较需要2轮,Diff 算法的实现在 reconcileChildrenArray 函数。是递归同层比较,标识差异点保存到 Diff 队列保存,得到 patch 树,再统一操作批量更新 DOM。Diff 总共就是移动、删除、增加三个操作,如果结构发生改变就直接卸载重新创建,如果没有则将节点在新集合中的位置和老集合中的 lastIndex 进行比较是否需要移动,如果遍历过程中发现新集合没有,但老集合有就删除 | redux、flux |
mixin类似Object.assign(),@decorator.缺点:命名冲突,难以维护 | mixins:[] | 同左 | 同左 | 早期用PureRenderMixin,后来用HOC(HOC 不会修改传入的组件,也不会使用继承来复制其行为。HOC 是纯函数,没有副作用) | 同左 |
19. 常用API | 一、全局new Vue({render: h => h(App)}).$mount(‘#app’); 、 unmount()app.component() app.directive() app.use() app.mixin() app.provide() app.version() 二、选项式data() props() computed() methods() watch() component() mixin()beforeCreate()…nextTick() | 同左,一、全局createApp(App) 俩个vue实例的功能要完全独立,相互隔离createSSRApp(App)app.mount() 另增加二、组合式setup() ref() toRef() toRefs() toRaw() shallowRef() triggleRef() isRef() isReadonly() isProxy() isReactive() reactive() readonly() watchEffect()watch()onMounted() onUpdated() onUnmounted() onBeforeMount() onBeforeUpdate() onBeforeUnmount()provide() inject() | defineProps, defineEmits、defineExpose、defineStore、withDefaults;const slots = useSlots(); const attrs = useAttrs() | constructor、componentDidMount、static getDerivedStateFromProps、shouldComponentUpdate、componentDidUpdate、componentWillUnmount | useState、useReducer、useContext、useEffect、useMemo、useCallback、useImperativeHandle+forwardRef。 |
20. 状态管理 | vuex | pinia,没有mutation module概念(用defineStore代替),体积更小,对ts支持更友好。异步用async await | pinia | redux缺点:1,简单逻辑但是代码太长2.新手上手不友好、推荐recoil、mobx | recoil:Atom数据,useRecoilState、useRecoilValue、useSetRecoilState、Selector异步 |
状态管理概念 | store.state、action(dispatch)->mutation(commit)、getter(computed) | pinia defineStore(‘storeId’, {state: () => { return { counter: 0 } },getters:{},actions:{}}),storeToRefs | 同左边 | action(dispatch)-》reducer(state, action)-》store、react-thunk异步 | redux7.1 redux usereducer方法合集 useselector读取 usedispatch设置 |
21.render | vue默认优化 | 同左 | 同左 | 通过shouldComponentUpdate这个生命周期方法可以进行控制、类组件可以用PureComponent | useMemo代替SCU,export default React.memo(MyComponent, (prevProps, nextProps) => { // 如果prevProps和nextProps完全相同,则返回true // 否则返回false,组件将重新渲染 return prevProps.name === nextProps.name;}); |
keep-alive | keep-alive | 同左 | 同左 | react-activation | 同左 |
1.说明:shouldComponentUpdate和useMemo两个的返回值相反,SCU false跳过渲染,useMemo true跳过渲染
16.8以上,父组件state发生变化,子组件也会变化,这时需要优化:
1.1把发生变化的父组件部分,单独封装成一个组件,这样不会影响父和子。
1.2用memo,const Child = React.memo((props)=>{return{《div》props.name《/div》}})
1.3用usecallback,缓存函数,如果给子组件传参了方法《Child handleClick={handleClick}>,就用 const handleChick = useCallback(()={ setCount(count+1)},[]) // 用缓存函数
1.4用useMemo(vue的computed),缓存对象值,必须return,防止被渲染。和而useCallback缓存的是函数
const test = useMemo(()=>{ return…},[])
1.5 类组件用shouldComponentUpdate
shouldComponentUpdate(nextProps, nextState) {
// 判断是否需要被渲染,如果需要则返回true,否则返回false
if (nextProps.b === this.props.b) {
return false;
} else {
return true;
}
}
2.useRef可以用来定义变量,这些变量更改之后不会引起页面重新渲染,比如分页获取数据时,存储页码。
useRef也可以用来区分初始渲染还是更新(通过current有没值,具体见示例库里的didOrUpdate.tsx)
在DOM节点上定义ref属性,通过.current就可以获取到该DOM元素
通过forwardRef就可以给函数子组件传入ref属性。
使用useImperativeHandle用于定义暴露给父组件的ref方法
3.vuex和redux的差异
4.类组件和函数式组件区别
4.1react类组件
import React from 'react';
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
componentDidMount() {
// 组件挂载后的生命周期函数
}
componentDidUpdate(prevP函数
}
componentDidUpdate(prevProps, prevState) {
// 组件更新后的生命周期函数
}
componentWillUnmount() {
// 组件卸载前的生命周期函数
}
handleClick = () => {
// 事件处理函数
this.setState({ count: this.state.count + 1 });
};
render() {
// 渲染组件
return (
<div>
<p>{this.state.count}</p>
<button onClick={this.handleClick}>增加</button>
</div>
);
}
}
4.2react函数式编程
import React, { useState, useEffect } from 'react';
function MyComponent() {
const [count, setCount] = useState(0);
useEffect(() => {
// 组件挂载后或依赖的props更新后的效果
return () => {
// 组件卸载前的清理函数
};
}, []); // 依赖数组,控制更新时机
const handleClick = () => {
setCount(count + 1);
};
return (
<div>
<p>{count}</p>
<button onClick={handleClick}>增加</button>
</div>
);
}
5.react16.8 父调子的方法
import { useState, forwardRef, useImperativeHandle, useRef } from "react";
export default function App() {
const xiaoji = useRef(null); //这个ref是绑定到子组件的
const add1 = () => {
console.log("xiaoji", xiaoji);
// 调用子组件的加方法
xiaoji.current.add();
};
const add2 = () => {
// 调用子组件的减方法
xiaoji.current.sub();
};
return (
<div>
{/* 绑定的ref,此时无数据,需要通过子组件返回绑定的数据或方法才能有值 */}
<Counter
ref={xiaoji}
num={1}
></Counter>
<button onClick={add1}>+</button>
<button onClick={add2}>-</button>
</div>
);
}
// 子组件需要使用forwardRef进行包裹,接收两个参数,参数一为传来的数据(必填,不然会把ref当成第一个参数),参数二为父组件绑定到子组件的ref值
const Counter = forwardRef(function Counter({ num }, ref) {
console.log("ref", ref); //传过来的ref
let [count, setCount] = useState(0); //定义的count值
function add() {
//子组件加方法
setCount((a) => (a += 1));
}
function sub() {
// 子组件减方法
setCount((a) => (a -= 1));
}
// 参数一为组件绑定的ref,参数二为绑定到ref上的数据或方法
useImperativeHandle(ref, () => {
return {
// 将子组件的方法绑定到ref,使父组件能通过ref访问到子组件方法
add,
sub,
};
});
return (
// 把上面整个useImperativeHandle注释掉, 给标签添加ref={ref}就可以通过父组件得到这个标签(因为上面是返回绑定属性或方法的ref,这个是返回绑定标签的ref,两者都是返回ref,不能同时使用)
<p ref={ref}>
{/* 显示的内容 */}
{count}----{num}
</p>
);
});
// 以上完成就可以通过父组件对子组件的方法进行调用了,这里就是对count值进行加减的例子
6.常用API
6.1 react 类组件常用API
import {Component} from "react";
import {Button} from "antd";
interface IState{
counter:number
}
export default class Index extends Component <any,any>{
constructor(props: any, context: any) {
super(props, context);
this.state={
counter:0
}
console.log("constructor")
}
componentDidMount() {
console.log("componentDidMount")
}
static getDerivedStateFromProps(props: any, state: any) {
console.log("getDerivedStateFromProps")
return null
}
shouldComponentUpdate(nextProps: Readonly<any>, nextState: Readonly<any>, nextContext: any): boolean {
console.log("shouldComponentUpdate")
return nextState.counter!<=5
}
add=()=>{
this.setState({
counter:this.state.counter+1
})
}
componentDidUpdate(prevProps: Readonly<any>, prevState: Readonly<any>, snapshot?: any) {
console.log("componentDidUpdate")
}
componentWillUnmount() {
console.log("componentWillUnmount")
}
render(){
console.log("render")
return(
<>
<div>{this.state.counter}</div>
<Button onClick={this.add}>add</Button></>
)
}
}
6.2 react用vue的指令
第三方插件: https://github.com/hkduan2004/react-directive
npm i @dbfu/react-directive
7.vue3 defineProps和withDefault区别
<template>
<h1>{{ msg }}</h1>
</template>
<script setuplang="ts">
// 采⽤ts专有声明,⽆默认值
defineProps<{
msg: string,
num?: number
}>()
// 采⽤ts专有声明,有默认值
interface Props {
msg?: string
labels?: string[]
}
const props =withDefaults(defineProps<Props>(),{
msg:'hello',
labels:()=>['one','two']
})
// ⾮ts专有声明
defineProps({
msg: String,
num:{
type:Number,
default:''
}
})
</script>
vue2 vue3 vue3.2区别
tv code2&tf spa
tv code2: vue3用defineProps和defineEmits、defineExpose、useSlots和useAttrs)
event 缓存
vue2,vue3:template、vue3加入tree shaking,vite,composition ApI,生命周期都加on,diff算法优化(添加静态标记,最长升序子元素算法,增量diff),dom优化、expose
react:1.jsx,2.webpack,3.constructor,4.mount、update、unmount,
typescript,function编程vue3新增了一个名为setup的入口函数,value, computed, watch, onMounted等方法都需要从外部import。 setup pinia api
说明 | vue2 | vue3.0 | vue3.2 |
---|---|---|---|
数据结构 | data() | setup(){} | <script setup /> |
变量使用 | data(){return{} | setup(){return{…data}} | 不需要return 和export default{} |
顶级 await 的支持 | 要写async | 要写async | 不需要写async,直接await |
ref、parent | this.$parent | child组件return expose、emits | ref、 defineExpose、defineEmits |
父子组件传值 | props、emit | props、emit | defineProps、defineEmits |
slot | slot、匿名、具名、作用域(父读子参数,子:data=“item” 父 v-slot="data"或者#default=‘data’) | 在vue2基础增加动态名字插槽 #[name] let name=ref(‘duan’)、attrs | useSlots(在jsx/tsx中更实用)和useAttrs() |
vuex | slot | slot、attrs | useSlots和useAttrs() |
watch事件 | watch | watch默认深度监听,如果不是响应数据才写deep:true、watchEffect(不用指定监听对象、访问不到修改之前的值) | 同左 |
v-memo | 没有 | 没有 | 有。在v-for中使用v-memo时,确保它们被用在了同一个元素上。v-memo在v-for内部是无效的 |
component | 需要注册 | 需要注册 | 不需要注册 |
vscode插件 | 需要注册 | vetur | volar |
第三方插件 | 需要注册 | 需要注册 | 一般在 mounted中初始化(注:1) |
this | this | getCurrentInstance() | getCurrentInstance() |
路由 | new VueRouter() | createRouter() | useRouter() |
beforeRouteEnter | beforeRouteEnter | 放在setup(){}前面。 | 单独建一个script放beforeRouteEnter 《script lang=“ts”>import { defineComponent } from “vue”;export default defineComponent({ beforeRouteEnter(to, from, next) { },});《/script> |
emit | this.$emit | setup(props,context){context.emit(‘fun name’, var)} | import defineEmits from 'vue' ;const emit = defineEmits([“changeMsg”]);emit(“changeMsg”, “is son”); |
v-for v-if | 优先级v-for 然后v-if | 先v-if | 同左 |
创建 | new Vue({render: h => h(App)}).$mount(‘#app’); h=createElement | let app = Vue.createApp({}) // 将应用与模板绑定app.mount(‘#app’) | 合并到attrs |
v-model | v-model.trim v-model.lazy v-number | 除了左边的,增加自定义修饰符v-model.capitalize 输入文字首字母大写const props = defineProps({modelValue: String, modelModifiers: { default: () => ({}) }})const emit = defineEmits([‘update:modelValue’]) | 同左边 |
listener | this.$listener | 合并到attrs | 合并到attrs |
移除的api | 有$on $once $off filter | 移除了左边那些 | 移除了左边那些 |
常用API | vue3常见api一、全局new Vue({render: h => h(App)}).$mount(‘#app’); 、 unmount()app.component() app.directive() app.use() app.mixin() app.provide() app.version() 二、选项式data() props() computed() methods() watch() component() mixin()beforeCreate()…nextTick() | 同左,i一、全局createApp(App) createSSRApp(App)app.mount() 另增加二、组合式setup() ref() toRef() toRefs() toRaw() shallowRef() triggleRef() isRef() isReadonly() isProxy() isReactive() reactive() readonly() watchEffect()watch()onMounted() onUpdated() onUnmounted() onBeforeMount() onBeforeUpdate() onBeforeUnmount()provide() inject() | 有 |
性能优化 | keep-alive、路由懒加载、v-for加key、v-if和v-for不能同时使用,大组件拆分小组件 | 合理运用shallowRef,triggleRef。const state =shallowRef({ count: 1 }) // 不会触发更改 state.value.count = 2; // 会触发更改 state.value = { count: 2 } | 有 |
指令:
v-html v-text v-show v-if v-for v-on v-model v-slot v-once v-pre v-cloak | 有| 有 |
一、vue2 template
export default {
name: 'baseData',
computed:{},//设置计算属性
data() {return {} },//定义状态
methods: {}, //定义事件方法
watch:{} //设置监听属性
}
</script>
修饰符:
1.1.表单修饰符
v-mode.number v-model.lazy=“value” v-model.trim v-model.custom
1.2.事件修饰符
vue: @click.stop阻止冒泡 @click.capture捕获 @click.prevent阻止默认 @click.once只执行一次
react: e.stopPropagation,onClickCapture
1.3.鼠标修饰符
@click.left @click.right @click.middle
1.4.键盘修饰符
@keyup.enter @keydown.esc等
二、vue3 template,支持option API 和compositionAPI
<template>
<div>
<p>{{ text1 }}</p>
<button @click="myFun1">按钮1</button>
<p>{{ age }}</p>
<button @click="myfun2">按钮2</button>
</div>
</template>
<script>
import { ref } from "vue";
export default {
name: "App",
data() {
return {
text1: "option api",
};
},
// setu函数是组合api的入口函数
setup() {
let age = ref(20);
function myfun2() {
alert("llooppp");
}
return { age, myfun2 };
},
components: {},
methods: {
myFun1() {
alert("abcdefg");
},
},
};
</script>
也可以让option API引用 compositionAPI里面的内容,需要return出date和methods
<template>
<div>
<p>{{ text1 }}</p>
<button @click="myFun1">按钮1</button>
<p>{{ age }}</p>
<button @click="myfun2">按钮2</button>
</div>
</template>
<script>
import { ref } from "vue";
export default {
name: "App",
data() {
return {
text1: 1,
};
},
// setu函数是组合api的入口函数
setup() {
console.log("setUp函数被执行", this);
let age = ref(20);
function myfun2() {
age.value+=1
}
return { age, myfun2 };
},
data: () => ({ counter: null }),
beforeCreate() {
console.log("beforeCreate被执行", this);
},
created() {
console.log("Create被执行", this);
},
components: {},
methods: {
reset() {
this.age+=1
this.text1 +=2
},
},
expose: ['reset']
};
</script>
vue3.0和vue3.2区别
vue3.0暴露变量必须 return 出来,template中才能使用
<script>
import Foo from './Foo.vue'
import Bar from './Bar.vue'
export default {
setup (props) {
console.log(props)
return {
ok: Math.random(),
Foo,
Bar
}
}
}
</script>
vue3.2在 script 标签上加上 setup 属性,组件在编译的过程中代码运行的上下是 setup() 函数中。所有ES模块导出都被认为是暴露给上下文的值,并包含在 setup() 返回对象中。
<template>
<button @click="color = color === 'red' ? 'green' : 'red'"> Color is: {{ color }} </button>
</template>
<script setup>
import { ref } from 'vue'
export const color = ref('red')
</script>
<style scoped>
button { color: v-bind(color);}
</style>
https://juejin.cn/post/7241374490490552376