Vue3
1、数据双向绑定
<body>
<div id="app">
<h1>{{msg}}</h1>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
/* 使用vue对象创建vue实例
mount("#app")挂载
*/
Vue.createApp({
data() {
return {
msg: "数据双向绑定!"
}
}
}).mount("#app");
</script>
</body>
2、常用例子
1. 如何操作文本
<body>
<div id="app">
<!-- 指令:vue提供的一些特殊属性v-开头 -->
<h1 v-text="msg"></h1>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
// 选项api(option api)
data() {
return {
msg: "数据双向绑定!-绑定文本"
}
}
}).mount("#app");
</script>
</body>
2. 如何操作html的属性
<body>
<div id="app">
<!-- 指令:vue提供的一些特殊属性v-开头 -->
<h1 v-text="msg" v-bind:title="tit"></h1>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
// 选项api(option api)
data() {
return {
msg: "数据双向绑定!-绑定文本",
tit: "操作属性!title"
}
}
}).mount("#app");
</script>
</body>
3. 如何绑定事件
<body>
<div id="app">
<!-- 指令:vue提供的一些特殊属性v-开头 -->
<h1 v-text="msg" v-bind:title="tit" v-on:click="showData"></h1>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
// 选项api(option api)
data() {
return {
msg: "数据双向绑定!-绑定文本",
tit: "操作属性!title"
}
},
methods: {
showData() {
alert("绑定事件!")
}
}
}).mount("#app");
4. 计数器练习
<body>
<div id="app">
<button v-on:click="decrease">-</button>
<span>{{number}}</span>
<button v-on:click="increase">+</button>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
// 选项api(option api)
data() {
return {
number: 0
}
},
methods: {
decrease() {
if(this.number>0){
this.number--;
}
},
increase() {
this.number++;
}
}
}).mount("#app");
</script>
</body>
5. 渲染列表图片切换
<body>
<div id="app">
<img :src="src" alt="">
<button @click="changePic(0)">1</button>
<button @click="changePic(1)">2</button>
<button @click="changePic(2)">3</button>
/*<button v-for="item,index in list" @click="changePic(index)">{{index+1}}</button>*/
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
// 选项api(option api)
data() {
return {
src: "1.jpg",
list: [
"1.jpg",
"2.jpg",
"3.jpg",
]
}
},
methods: {
changePic(i) {
this.src = this.list[i];
}
}
}).mount("#app");
</script>
</body>
6. 渲染列表
<body>
<div id="app">
<ul>
<li v-for="item in list">{{item}}</li>
</ul>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
// 选项api(option api)
data() {
return {
list: [
"香蕉",
"苹果",
"梨子"
]
}
},
methods: {
}
}).mount("#app");
</script>
</body>
7. 添加数据
<body>
<div id="app">
<button @click="insert">添加品种</button>
<ul>
<li v-for="item in list">{{item}}</li>
</ul>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
// 选项api(option api)
data() {
return {
list: [
"香蕉",
"苹果",
"梨子"
]
}
},
methods: {
insert() {
this.list.push("猕猴桃")
}
}
}).mount("#app");
</script>
</body>
3、表单提交双向数据绑定
<body>
<div id="app">
<!-- 阻止默认提交行为@submit.prevent -->
<form @submit.prevent="post">
<input type="text">
<button>提交表单</button>
</form>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
// 选项api(option api)
data() {
return {
}
},
methods: {
post() {
console.log("表单提交");
}
}
}).mount("#app");
</script>
</body>
双向绑定
<body>
<div id="app">
<!-- 阻止默认提交行为@submit.prevent -->
<form @submit.prevent="post">
<input type="text" v-model="msg">
<button>提交表单</button>
</form>
<h1>{{msg}}</h1>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
// 选项api(option api)
data() {
return {
msg: "我是表单里的数据"
}
},
methods: {
}
}).mount("#app");
</script>
</body>
输出
v-model.number="msg"输出数值
v-model.lazy="msg" 失去焦点的时候再绑定
v-model.trim="msg" 去掉空格
<body>
<div id="app">
<!-- 阻止默认提交行为@submit.prevent -->
<form @submit.prevent="post">
<!--v-model.number="msg"输出数值 -->
<input type="text" v-model="msg">
<button>提交表单</button>
</form>
<h1>{{msg}}</h1>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
// 选项api(option api)
data() {
return {
msg: "我是表单里的数据"
}
},
methods: {
post() {
console.log(this.msg);
}
}
}).mount("#app");
</script>
</body>
简单购物车
<body>
<div id="app">
<h1>水果列表</h1>
<form @submit.prevent="insert">
<span>品种:</span><input type="text" v-model="name">
<span>价格:</span><input type="text" v-model.number="price">
<button>添加</button>
</form>
<ul>
<li v-for="item,index in list">
名称:{{item.name}}
单价:{{item.price}}
<button @click="decrease(index)">-</button>
数量:{{item.count}}
<button @click="increase(index)">+</button>
</li>
</ul>
<h3>总计:{{totalPrice}}</h3>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
Vue.createApp({
// 选项api(option api)
data() {
return {
name: "",
price: 0,
list: [
]
}
},
computed: {
totalPrice() {
let sum = 0;
this.list.forEach(v => {
sum += (v.price) * (v.count)
})
return sum;
}
},
methods: {
insert() {
this.list.push({
name: this.name,
price: this.price,
count: 1
})
},
decrease(i) {
this.list[i].count--;
if (this.list[i].count <= 0 && confirm("是否删除")) {
this.list.splice(i, 1);
}
},
increase(i) {
this.list[i].count++
}
}
}).mount("#app");
</script>
</body>
4、组件化开发
定义:
app.component("组件名",{
template:组件模板
});
使用:<组件名></组件名>
<body>
<div id="app">
<hello></hello>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const app = Vue.createApp({
// 选项api(option api)
data() {
return {}
}
});
app.component("hello", {
data() {
return {
msg: "我是组件hello"
}
},
template: `
<h1>{{msg}}</h1>
`
});
app.mount("#app");
</script>
</body>
组件可以嵌套:组件模板里面放子组件标签
app.component("hello", {
data() {
return {
msg: "我是组件hello"
}
},
template: `
<h1>{{msg}}</h1>
<child></child>
`
});
app.component("child", {
data() {
return {
msg: "我是组件hello的子组件"
}
},
template: `
<h1>{{msg}}</h1>
`
});
1.根组件:
const app=Vue.createApp({});
//根组件
const rootComponent=app.mount("#app");
2.全局组件与局部组件
使用component方法注册的组件叫全局组件
可以使用components属性实现局部组件
<body>
<div id="app">
<my-hello></my-hello>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const myHello = {
template: `
<h1>局部组件</h1>`
}
const app = Vue.createApp({
components: {
"myHello": myHello
}
})
app.mount("#app")
</script>
</body>
在局部组件1中使用局部组件2要在局部组件1中注册组件2
3.组件的生命周期
1.创建 create
没有data(),method() 在js中创建虚拟dom
2.挂载 mount
有了data(),method()挂载到html上
3.详细
- beforeCreate()
没有数据和方法 - created()
有数据有方法,没有dom - beforeMount()
没有dom,有数据 - mounted()
能够拿到标签,有dom,有数据 - 用在刷新页面的时候,自动加载
<body>
<div id="app">
<h1>{{msg}}</h1>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const app = Vue.createApp({
data() {
return {
list: ["你好", "亲爱的用户", "很高兴见到你"],
msg: ""
}
},
created() {
this.showData();
},
methods: {
showData() {
let i = 0;
let t = setInterval(() => {
this.msg = this.list[i];
i++;
if (i === 3) {
clearInterval(t);
}
}, 500)
}
}
})
app.mount("#app")
</script>
</body>
5、自定义指令
刷新页面自动获取焦点
<body>
<div id="app">
<input ref="inp" type="text">
<button>搜索</button>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const app = Vue.createApp({
data() {
},
mounted() {
this.$refs.inp.focus();
}
})
app.mount("#app")
</script>
</body>
自定义指令
<body>
<div id="app">
<input v-focus type="text">
<button>搜索</button>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const app = Vue.createApp({
})
app.directive("focus", {
mounted(el) {
el.focus()
}
})
app.mount("#app")
</script>
</body>
6、路由
npm i --save vue-router@4
1. 配置俩页面
<template>
<router-link to="/home">首页</router-link>
|
<router-link to="/blog">博客</router-link>
<router-view></router-view>
</template>
<script>
export default {
name: "App",
components: {},
};
</script>
2. 设置路由
import { createRouter } from "vue-router";
const router = createRouter({
});
export default router;
3. main.js中引入路由
import { createApp } from 'vue'
import App from './App.vue'
import './index.css'
import router from "./router.js"
const app = createApp(App)
app.use(router)
app.mount('#app')
4. 配置路由
import { createRouter, createWebHashHistory } from "vue-router";
import Home from "./components/Home.vue";
import Blog from "./components/Blog.vue";
const router = createRouter({
history: createWebHashHistory(),
routes: [
{
path: "/home",
component: Home
},
{
path: "/blog",
component: Blog
},
]
});
export default router;
7、路由传参(动态路由)
<template>
<router-view></router-view>
</template>
<script>
export default {
name: "App",
};
</script>
<router-link :to="'/blog/' + item.id">{{ item.title }}</router-link>
<template>
<h1>列表</h1>
<ul>
<li v-for="item in blogList">
<router-link :to="'/blog/' + item.id">{{ item.title }}</router-link>
</li>
</ul>
</template>
<script>
export default {
name: "List",
data() {
return {
blogList: [
{ id: 1, title: "测试文章1" },
{ id: 2, title: "测试文章2" },
{ id: 3, title: "测试文章3" },
{ id: 4, title: "测试文章4" },
{ id: 5, title: "测试文章5" },
],
};
},
};
</script>
<h1>博客详情:{{ $route.params.id }}</h1>
<template>
<h1>博客详情:{{ $route.params.id }}</h1>
</template>
<script>
export default {
name: "Blog",
data() {
return {};
},
};
</script>
{
path: "/blog/:id",
component: Blog
},
import { createRouter, createWebHashHistory } from "vue-router";
import List from "./components/List.vue";
import Blog from "./components/Blog.vue";
const router = createRouter({
history: createWebHashHistory(),
routes: [
{
path: "/",
component: List
},
{
path: "/blog/:id",
component: Blog
},
]
});
export default router;
<template>
<h1>博客详情:{{ $route.params.id }}</h1>
<p>
{{ blogContent }}
</p>
</template>
<script>
export default {
data() {
return {
blogContent: "",
};
},
created() {
let id = this.$route.params.id;
this.getBlogDataById(id);
},
methods: {
getBlogDataById(id) {
switch (id) {
case "1":
this.blogContent = "第一篇测试";
break;
case "2":
this.blogContent = "第二篇测试";
break;
case "3":
this.blogContent = "第三篇测试";
break;
case "4":
this.blogContent = "第四篇测试";
break;
case "5":
this.blogContent = "第五篇测试";
break;
}
},
},
};
</script>
8、实现登录
<template>
<h1>登录</h1>
<form @submit.prevent="login">
<div>
<label>用户名:</label>
<input type="text" v-model="username" />
</div>
<div>
<label>密码:</label>
<input type="password" v-model="password" />
</div>
<button>登录</button>
</form>
</template>
<script>
export default {
data() {
return {
username: "",
password: "",
};
},
methods: {
login() {
if (this.username === "admin" && this.password === "123456") {
this.$router.push("/list");
} else {
alert("用户名或密码错误!");
}
},
},
};
</script>
9、验证登录状态
localStorage.setItem("token", "token1111");
<template>
<h1>登录</h1>
<form @submit.prevent="login">
<div>
<label>用户名:</label>
<input type="text" v-model="username" />
</div>
<div>
<label>密码:</label>
<input type="password" v-model="password" />
</div>
<button>登录</button>
</form>
</template>
<script>
export default {
data() {
return {
username: "",
password: "",
};
},
methods: {
login() {
if (this.username === "admin" && this.password === "123456") {
this.$router.push("/list");
localStorage.setItem("token", "token1111");
} else {
alert("用户名和密码错误!");
}
},
},
};
</script>
created() {
console.log(localStorage.getItem("name"));
},
<template>
<h1>列表</h1>
<ul>
<li v-for="item in blogList">
<router-link :to="'/blog/' + item.id">{{ item.title }}</router-link>
</li>
</ul>
</template>
<script>
export default {
created() {
console.log(localStorage.getItem("name"));
},
data() {
return {
blogList: [
{ id: 1, title: "测试文章1" },
{ id: 2, title: "测试文章2" },
{ id: 3, title: "测试文章3" },
{ id: 4, title: "测试文章4" },
{ id: 5, title: "测试文章5" },
],
};
},
};
</script>
// 导航守卫:路由拦截、路由守卫
router.beforeEach((to, from, next) => {
// 验证token,只有存在token的时候才能跳转到内容页
let token = localStorage.getItem("token");
if (token || to.path === "/login") {
next();
} else {
next("/login");
}
})
import { createRouter, createWebHashHistory } from "vue-router";
import List from "./components/List.vue";
import Blog from "./components/Blog.vue";
import Login from "./components/Login.vue";
const router = createRouter({
history: createWebHashHistory(),
routes: [
{
path: "/login",
component: Login
},
{
path: "/list",
component: List
},
{
path: "/blog/:id",
component: Blog
},
]
});
// 导航守卫:路由拦截、路由守卫
router.beforeEach((to, from, next) => {
// 验证token,只有存在token的时候才能跳转到内容页
let token = localStorage.getItem("token");
if (token || to.path === "/login") {
next();
} else {
next("/login");
}
})
export default router;
10、组合api-响应式变量
所有功能写在set up(){}
npm init vite-app demovue3
<template>
<h1>{{ title }}</h1>
<button @click="sayHi">按钮</button>
</template>
<script>
export default {
setup() {
let title = "组合api";
function sayHi() {
alert("组合api,暴露什么就用什么");
}
return {
title,
sayHi,
};
},
};
</script>
1. 响应式:ref把字符串变为响应式变量
<template>
<h1>{{ title }}</h1>
<button @click="sayHi">按钮</button>
</template>
<script>
// 解构一个ref
import { ref } from "vue";
export default {
setup() {
// 把字符串变为响应式变量
let title = ref("组合api");
function sayHi() {
title.value = "hello 我是响应式变量";
}
return {
title,
sayHi,
};
},
};
</script>
- reactive将对象变成响应式对象
<template>
<h1>{{ title }}</h1>
<p>{{ student.name }}</p>
</template>
<script>
// 解构一个ref
// reactive将对象变成响应式对象
import { reactive, ref } from "vue";
export default {
setup() {
// 把字符串变为响应式变量
let title = ref("组合api");
const student = { name: "小明", age: 2 };
return {
// 绑定到页面
title,
student,
};
},
};
</script>
<template>
<h1>{{ title }}</h1>
<button @click="sayHi">按钮</button>
<p>{{ student.name }}</p>
</template>
<script>
// 解构一个ref
// reactive将对象变成响应式对象
import { reactive, ref } from "vue";
export default {
setup() {
// 把字符串变为响应式变量
let title = ref("组合api");
const student = reactive({ name: "小明", age: 2 });
function sayHi() {
student.name = "我是小红";
}
return {
title,
student,
sayHi,
};
},
};
</script>
3.生命周期
beforeCreate——>use setup()
created——>use setup()
解构:
beforeMount——>onBeforeMount
mounted——>onBeforeUpdate
beforeUnmount——>onBeforeUnmount
unmounted——>onUnmounted
<template>
<h1>{{ title }}</h1>
</template>
<script>
import { onMounted, ref } from "vue";
export default {
setup() {
const list = ["你好", "亲爱的用户", "很高兴遇见你"];
const title = ref("");
onMounted(() => {
let i = 0;
let t = setInterval(() => {
title.value = list[i];
i++;
if (i === 3) {
clearInterval(t);
}
}, 500);
});
return {
title,
};
},
};
</script>
11、计算属性
<template>
<h1>{{ number }}</h1>
</template>
<script>
import { computed } from "vue";
export default {
setup() {
const number = computed(() => {
return 100;
});
return {
number,
};
},
};
</script>
<template>
<h1>苹果 2元一斤</h1>
<button @click="decrease">-</button>
<span>{{ number }}</span>
<button @click="increase">+</button>
<h2>总计:{{ totalPrice }}</h2>
</template>
<script>
import { computed, ref } from "vue";
export default {
setup() {
const number = ref(0);
function increase() {
number.value++;
}
function decrease() {
number.value--;
}
const totalPrice = computed(() => {
return number.value * 2;
});
return {
number,
increase,
decrease,
totalPrice,
};
},
};
</script>