1. createApp
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vue3.0</title>
</head>
<body>
<div id="app">
<h1 :title="title">{{title}}</h1>
<course v-model="inputVal" @add="addCourse"></course>
<p>{{ list.toString() }}</p>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script type="text/x-template" id="course">
<input :value="modelValue" @input="$emit('update:modelValue',$event.target.value)" placeholder="添加课程" />
<button @click="$emit('add')">添加数据</button>
</script>
<script>
const Course= {
template: "#course",
props: {
modelValue:{
type: String,
required: true
}
},
emits: ["add","update:modelValue"]
}
Vue.createApp({
components:{
course: Course
},
data() {
return {
title: "缪冬冬",
list:[],
inputVal:"默认值"
};
},
methods: {
addCourse() {
this.list.push(this.inputVal)
}
},
}).mount("#app");
</script>
</body>
</html>
2.setup
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vue Composition Api</title>
</head>
<body>
<div id="app">
<h2>{{ state.title }}</h2>
<h2>数值ref: {{count}}</h2>
<comp title="666" desc="555"></comp>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script type="text/x-template" id="com">
<input v-model="val" placeholder="请输入内容" />
<button @click="addItem">添加内容</button>
<ul>
<li v-for="(item,i) in list" :key="i">{{item}}</li>
</ul>
</script>
<script>
const { reactive, onMounted, ref, toRefs } = Vue;
const Comp = {
template: "#com",
props: ["title"],
setup(props, ctx) {
console.log(props, ctx);
const { attrs } = ctx;
const state = reactive({
val: props.title,
list: [attrs.desc],
});
function addItem() {
state.list.push(state.val);
}
return {
...toRefs(state),
addItem,
};
},
};
const app = Vue.createApp({
components: {
Comp,
},
setup() {
const state = reactive({
title: "默认值",
});
onMounted(() => {
console.log(document.getElementById("app"));
setTimeout(() => {
state.title = "修改的值";
}, 2000);
});
const count = ref(0);
setInterval(() => {
count.value++;
}, 1000);
return {
state,
count,
};
},
}).mount("#app");
</script>
</body>
</html>
3.watch
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app">
<p>count的值: --- {{count}}</p>
<p>count的值: --- {{newCount}}</p>
<input v-model="val" /><button @click="addCourse">添加课程</button>
<p>{{valDesc}}</p>
<ul>
<li v-for="(item,i) in list" :key="i">{{item}}</li>
</ul>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const { reactive, toRefs, watchEffect, watch, computed, ref } = Vue;
Vue.createApp({
setup() {
const state = reactive({
count: 1,
newCount: null,
});
watchEffect(() => {
// setTimeout(() => {
// state.newCount = state.count * 2;
// }, 1000);
state.newCount = state.count * 2;
});
watch(
() => state.count,
(count, prev) => {
console.log(count, prev);
}
);
const num = ref(0);
watch(num, (nm, prev) => console.log(nm, prev, "ref watch"));
const interval = setInterval(() => {
if (state.count >= 10) {
clearInterval(interval);
}
state.count++;
num.value++;
}, 2000);
// 测试demo
const msg = reactive({
list: ["java", "php"],
val: "",
valDesc: computed(() => `输入的值是:${msg.val}`),
});
function addCourse() {
msg.list.push(msg.val);
}
return {
...toRefs(state),
num,
...toRefs(msg),
addCourse,
};
},
}).mount("#app");
</script>
</body>
</html>
4.provide,inject
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app">
<p>useCounter:{{count}}</p>
<cp></cp>
<p><button @click="setCount(number)">设置值</button></p>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script type="text/x-template" id="comp">
<input v-model="val" />
</script>
<script type="module">
import { useCounter } from "./hook.js";
const { reactive, ref, toRefs, provide, inject } = Vue;
const Comp= {
template: "#comp",
setup(){
const val= inject("num");
return {
val
};
}
}
Vue.createApp({
components:{
cp: Comp
},
setup() {
const [count, setCount] = useCounter();
const number= ref(10);
provide("num",number);
return {
count,
setCount,
number
};
},
}).mount("#app");
</script>
</body>
</html>
5.directive
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app">
<input v-focus v-model="val" />
<p><button @click="changeShow">改变权限</button></p>
<p v-permission="show">用户名</p>
</div>
<script src="./vue.js"></script>
<script>
const { createApp, reactive, toRefs } = Vue;
const app = createApp({
setup() {
const state = reactive({
val: "",
show: true,
});
function changeShow() {
state.show = !state.show;
console.log(state.show);
}
return {
...toRefs(state),
changeShow,
};
},
directives: {
permission(el, binding) {
if (!binding.value) {
el.style.display = "none";
} else {
el.style.display = "block";
}
},
},
});
app.directive("focus", {
mounted(el) {
el.focus();
},
});
app.mount("#app");
</script>
</body>
</html>
6.teleport
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.md {
width: 400px;
height: 200px;
position: fixed;
top: 50%;
left: 50%;
box-shadow: 0 0 3px 3px rgba(0, 0, 0, 0.1);
transform: translate(-50%, -50%);
}
</style>
</head>
<body>
<div id="app">
<button @click="changeShow">打开/关闭</button>
<modal v-model:visible="show"></modal>
<div id="md"></div>
</div>
<script src="./vue.js"></script>
<script type="text/x-template" id="modal">
<teleport :to="dom" v-if="dom">
<div class="md" v-show="vib">
<p>这是个弹框</p>
<slot></slot>
<button @click="$emit('update:visible',false)">关闭</button>
</div>
</teleport>
</script>
<script>
const { reactive, ref, computed, onMounted } = Vue;
const Modal = {
template: "#modal",
props: ["visible"],
emits: ["update:visible"],
setup(props) {
const vib = computed(() => props.visible);
let dom = ref(null);
onMounted(() => {
dom.value = document.getElementById("md");
});
return {
vib,
dom,
};
},
};
Vue.createApp({
components: {
Modal,
},
setup() {
const show = ref(false);
function changeShow() {
show.value = !show.value;
console.log(show.value);
}
return {
show,
changeShow,
};
},
}).mount("#app");
</script>
</body>
</html>
7.h render渲染
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app">
<input v-model="appVal" />
<button @click="getVal">获取值</button>
<x-head :level="2" :list="[1,2,3,4,85]">测试标题</x-head>
<l-input v-model="lVal"></l-input>
</div>
<script src="./vue.js"></script>
<script type="text/x-template" id="input">
<p>这是个输入组件</p>
<input :value="modelValue" @input="$emit('update:modelValue',$event.target.value)" />
</script>
<script>
const { createApp, h, ref } = Vue;
const AInput = {
template: "#input",
props: ["modelValue"],
emits: ["update:modelValue"],
};
createApp({
setup() {
const appVal = ref("");
const lVal = ref("1");
function getVal() {
console.log(appVal.value, "appVal");
console.log(lVal.value, "lVal");
}
return {
appVal,
getVal,
lVal,
};
},
})
.component("x-head", {
props: {
level: {
type: Number,
required: true,
},
list: Array,
},
render() {
if (this.list && this.list.length > 0) {
const children = this.list.map((item) =>
h(
"li",
{
// onClick: {
// handler: () => {
// console.log("click", item);
// },
// once: true,
// capture: true,
// },
title: item,
onDblclick: () => console.log("db", item),
},
item
)
);
return h("ul", children);
} else {
return h(`h${this.level}`, this.$slots.default());
}
},
})
.component("l-input", {
props: ["modelValue"],
emits: ["update:modelValue"],
render() {
return h(AInput, {
modelValue: this.modelValue,
"onUpdate:modelValue": (val) =>
this.$emit("update:modelValue", val),
});
},
})
.mount("#app");
</script>
</body>
</html>
8. 插件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.mes {
width: 400px;
height: 200px;
position: fixed;
top: 50%;
left: 50%;
box-shadow: 0 0 3px 3px rgba(0, 0, 0, 0.1);
transform: translate(-50%, -50%);
}
</style>
</head>
<body>
<div id="app">
<button @click="showMsg">打开消息</button>
</div>
<script src="./vue.js"></script>
<script type="text/x-template" id="mes">
<div class="mes">
{{msg}}
</div>
</script>
<script>
const { createApp, render, h } = Vue;
const app = createApp({
methods: {
showMsg() {
this.$message({ msg: "测试" });
},
},
});
const MessagePlugin = {
install() {
const Message = {
template: "#mes",
props: {
duration: {
type: Number,
default: 2000,
},
msg: String,
},
mounted() {
setTimeout(() => {
app.config.globalProperties.$message(null);
}, this.duration);
},
};
const container = document.createElement("div");
document.body.appendChild(container);
app.config.globalProperties.$message = (props) => {
if (props) {
render(h(Message, { msg: props.msg }), container);
} else {
render(null, container);
}
};
},
};
app.use(MessagePlugin);
app.mount("#app");
</script>
</body>
</html>
9.hook.js
const { onMounted, onUnmounted, ref } = Vue;
export function useCounter() {
const count = ref(0);
let timer;
onMounted(() => {
timer = setInterval(() => {
count.value++;
}, 1000);
});
function setCount(val) {
count.value = val;
}
onUnmounted(() => {
clearInterval(timer);
});
return [count, setCount];
}