基于vue3.0简单的页面使用
- 项目效果图
- 项目文件图
- package.json
- main.js
- App.vue
- views/Tutorial.vue
- views/TS.vue
- views/Docs.vue
- views/Community.vue
- views/Blog.vue
- views/About.vue
- utils/create.jsx
- utils/defineCom.js
- utils/DragIcon.js
- utils/someName.ts
- utils/TS.ts
- stores/client.js
- stores/message.js
- router/index.js
- components/createHtml.vue
- components/footer.vue
- components/header.vue
- components/test.vue
- assets/base.css
- assets/main.scss
- assets/styles.scss
项目效果图
项目文件图
package.json
{
"name": "ping-vue",
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore",
"format": "prettier --write src/"
},
"dependencies": {
"miao-drag": "^1.0.0",
"pinia": "^2.0.35",
"vue": "^3.2.47",
"vue-router": "^4.1.6"
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.2.0",
"@vitejs/plugin-vue": "^4.0.0",
"@vitejs/plugin-vue-jsx": "^3.0.0",
"@vue/eslint-config-prettier": "^7.1.0",
"eslint": "^8.34.0",
"eslint-plugin-vue": "^9.9.0",
"prettier": "^2.8.4",
"sass": "^1.62.0",
"vite": "^4.1.4"
}
}
main.js
import {
createApp
} from 'vue'
import {
createPinia
} from 'pinia'
import App from './App.vue'
import router from './router'
import '@/assets/main.scss'
const pinia = createPinia();
const app = createApp(App);
app.config.globalProperties.isRouterAlive = true;
app.use(router);
app.use(pinia);
app.mount('#app')
App.vue
<template>
<RouterView v-if="isRouterAlive" />
</template>
<script setup>
import {
ref,
watch,
getCurrentInstance,
nextTick
} from 'vue';
import {
RouterView,
useRoute
} from 'vue-router';
const {
appContext
} = getCurrentInstance();
/**
* 监听路由是否变化
* **/
const route = useRoute();
watch(route, (params) => {
}, {
deep: true,
immediate: true
})
const isRouterAlive = ref(true);
appContext.config.reload = () => {
console.log("[萍萍]")
isRouterAlive.value = false;
nextTick(() => {
isRouterAlive.value = true;
})
}
watch(isRouterAlive, (value) => {
console.log("[监听变化]", value)
})
watch(() => appContext.config.globalProperties.isRouterAlive, (value) => {
console.log("[振-萍]", value)
}, {
deep: true,
immediate: true
})
</script>
<style lang="scss">
</style>
views/Tutorial.vue
<template>
<div class="ping-wrap">
<!-- header -->
<headerComponent></headerComponent>
<!-- container -->
<div class="ping-container">
手机号:{{ clientStore.phone }}
<button @click="plusSalaryHandle">年龄{{ clientStore.age }}</button>
总工资:{{ totalSal }}元
<button @click="resetHandle">reset</button>
</div>
<!-- footer -->
<footerComponent></footerComponent>
</div>
</template>
<script setup>
import headerComponent from '@/components/header.vue'
import footerComponent from '@/components/footer.vue'
import {
useClientStore
} from '@/stores/client'
import {
computed,
ref,
watch
} from 'vue'
const clientStore = useClientStore()
console.log('[clientStore]', clientStore)
const totalSal = ref(0)
watch(
() => clientStore.totalSalary,
(value) => {
totalSal.value = value
}, {
deep: true,
immediate: true
}
)
totalSal.value = computed(() => clientStore.totalSalary)
function plusSalaryHandle() {
console.log('[新增]')
clientStore.$patch({
age: 45,
phone: '15262680856'
})
}
function resetHandle() {
clientStore.$reset()
}
</script>
<style lang="scss" scoped>
</style>
views/TS.vue
<template>
<div class="ping-wrap">
<!-- header -->
<headerComponent></headerComponent>
<!-- container -->
<div class="ping-container">
<p v-my-directive:premi="['miao', 'zhen']">{{ name }}</p>
<createH name="清太祖" :params="tempList"></createH>
<p v-stname:pers="['ping']">你应该看到我</p>
<p v-stname:pers="['ze']">你不应该看到我</p>
</div>
<!-- footer -->
<footerComponent></footerComponent>
</div>
</template>
<script setup>
import headerComponent from '@/components/header.vue'
import footerComponent from '@/components/footer.vue'
import '@/utils/TS.ts'
import createH from '@/utils/create.jsx'
import {
ref
} from 'vue'
const name = ref('ping')
const tempList = [{
name: '宋太宗',
age: 29,
address: '北京市海淀区'
},
{
name: '汉武帝',
age: 32,
address: '上海市浦东新区'
},
{
name: '唐太宗',
age: 27,
address: '河南省郑州市'
},
{
name: '秦始皇',
age: 270,
address: '河南省郑州市'
},
{
name: '',
age: 450,
address: '西安市'
}
]
class Miao {
constructor(firstName, lastName) {
this._firstName = firstName
this._lastName = lastName
}
get firstName() {
return this._firstName
}
set firstName(value) {
this._firstName = value
}
get lastName() {
return this._lastName
}
set lastName(value) {
this._lastName = value
}
draw() {
return this._firstName + ' ' + this._lastName
}
}
const miao = new Miao('Miao', 'zhenzhen')
const fullName = miao.draw()
console.log(fullName)
const vMyDirective = (el, binding) => {
console.log(el)
console.log(binding)
}
const vStname = (el, binding) => {
if (binding.value.includes('ze')) {
el.parentNode.removeChild(el)
}
}
</script>
<style scoped lang="scss">
</style>
views/Docs.vue
<template>
<div class="ping-wrap">
<!-- header -->
<headerComponent></headerComponent>
<!-- container -->
<div class="ping-container">
<div id="reload">刷新页面</div>
<div id="btn">按钮</div>
<input v-model="tempList.name" />
<input v-model="tempList.age" />
<input v-model="tempList.wife" />
<p>单价:</p>
<input v-model="price" />
<p>数量:</p>
<input v-model="count" />
<p>总价:</p>
{{ total }}
x:{{ coordinate.x }}-y:{{ coordinate.y }}
</div>
<!-- footer -->
<footerComponent ref="footerRef">
<template v-slot:left>
<div>
<p>朱元璋</p>
<p>马皇后</p>
</div>
</template>
<template #center> 2023 </template>
<template #right>
<div>
<p>杨坚</p>
<p>独孤皇后</p>
</div>
</template>
</footerComponent>
</div>
</template>
<script setup>
import {
onBeforeMount,
onMounted,
onBeforeUnmount,
onUnmounted,
ref,
reactive,
watch,
watchEffect,
computed,
getCurrentInstance
} from 'vue'
import headerComponent from '@/components/header.vue'
import footerComponent from '@/components/footer.vue'
const footerRef = ref(null)
const tempList = reactive({
name: '杨坚',
age: 29,
wife: '独孤皇后'
})
const coordinate = reactive({
x: 0,
y: 0
})
watch(
tempList,
(value) => {
console.log('[监听1]', value)
}, {
deep: true
}
)
watch(
() => tempList.age,
(value) => {
console.log('[监听]', value)
}
)
watchEffect(() => {
console.log('[]', tempList.name)
console.log('[]', tempList.age)
console.log('[你执行了我]')
})
const price = ref(100)
const count = ref(1)
watch(count, (newCount, oldCount) => {
console.log('[数量]', newCount, oldCount)
})
const total = computed(() => {
return price.value * count.value
})
onBeforeMount(() => {
console.log('[onBeforeMount]')
})
onMounted(() => {
console.log('[onMounted]', tempList.name)
document.querySelector('#btn').addEventListener('click', handleClick)
document.querySelector('#btn').style.color = 'red'
document.querySelector("#reload").addEventListener("click", handleReload)
})
window.addEventListener('mousemove', (e) => {
coordinate.x = e.clientX
coordinate.y = e.clientY
})
onBeforeUnmount(() => {
console.log('[onBeforeUnmount]')
})
onUnmounted(() => {
console.log('[onUnmounted]')
})
const {
appContext
} = getCurrentInstance()
function handleClick() {
footerRef.value.init()
console.log('[footer]', footerRef.value.publice)
}
function handleReload() {
appContext.config.reload()
}
//vue3.0中的自定义指令
const vMyDirective = (el, binding) => {
console.log(el)
console.log(binding)
}
</script>
<style lang="scss" scoped>
</style>
views/Community.vue
<template>
<div class="ping-wrap">
<!-- header -->
<headerComponent></headerComponent>
<!-- container -->
<div class="ping-container">
<test message="你是好人"></test>
<clientComponent></clientComponent>
</div>
<!-- footer -->
<footerComponent></footerComponent>
</div>
</template>
<script setup>
import clientComponent from '@/utils/defineCom'
import headerComponent from '@/components/header.vue'
import footerComponent from '@/components/footer.vue'
import test from '@/components/test.vue'
import { reactive } from 'vue'
const dataList = reactive([
{
name: '周武王',
id: 1
},
{
name: '汉光帝',
id: 2
},
{
name: '乾隆皇帝',
id: 3
}
])
console.log('[]', dataList)
const tempList = dataList.map((item) => {
return item.id + 1
})
console.log(tempList)
</script>
<style lang="scss" scoped>
</style>
views/Blog.vue
<template>
<div class="ping-wrap">
<!-- header -->
<headerComponent></headerComponent>
<!-- container -->
<div class="ping-container">
<p>标题:{{messageStore.title}}</p>
<p>内容:{{messageStore.content}}</p>
<p>总数量:{{messageStore.totalCount}}</p>
<button @click="changeCountHandle">改变数量</button>
</div>
<!-- footer -->
<footerComponent></footerComponent>
</div>
</template>
<script setup>
import headerComponent from "@/components/header.vue"
import footerComponent from "@/components/footer.vue"
import {
useMessageStore
} from "@/stores/message.js";
const messageStore = useMessageStore();
console.log("[messageStore]", messageStore);
function changeCountHandle() {
console.log("[改变]")
messageStore.setCount(12)
}
</script>
<style lang="scss" scoped>
</style>
views/About.vue
<template>
<div class="ping-wrap">
<!-- header -->
<headerComponent></headerComponent>
<!-- container -->
<div class="ping-container">关于我们{{ count }}</div>
<!-- footer -->
<footerComponent></footerComponent>
</div>
</template>
<script setup>
import headerComponent from '@/components/header.vue'
import footerComponent from '@/components/footer.vue'
import { ref, onMounted, onUnmounted, watch } from 'vue'
const count = ref(0)
const timerHandle = ref(null)
timerHandle.value = setInterval(() => {
count.value += 1
console.log('[计时器]', count.value)
}, 1000)
watch(count, (newVal, oldVal) => {
console.log('[watch]', newVal, oldVal)
})
onMounted(() => {
console.log('[onMounted]')
})
onUnmounted(() => {
console.log('[onUnmounted]')
clearInterval(timerHandle.value)
})
</script>
<style lang="scss" scoped>
</style>
utils/create.jsx
import { defineComponent } from 'vue'
import '@/assets/main.scss'
const defaultStyles = {
border: '1px solid #eee',
borderRadius: '5px',
padding: '10px 15px',
margin: '10px 0'
}
export default defineComponent({
props: {
name: {
type: String,
default: 'hello world'
},
params: {
type: Object,
default: () => ({})
}
},
data() {
return {
count: 0,
styles: {
border: '1px solid #eee',
borderRadius: '5px',
padding: '10px 15px',
margin: '10px 0'
}
}
},
render(props) {
return (
<>
<div style={this.styles}>
<h1>当前计数:{this.count}</h1>
<p style={{ color: 'red' }}>姓名:{props.name}</p>
<button onClick={() => this.count++}>增加</button>
</div>
<div style={defaultStyles}>
<div className="row">
<div className="col-6">col-6</div>
<div className="col-6">col-6</div>
</div>
{props.params.map((item, index) => {
if (item.age > 30) {
return (
<ul className="ul-block ul-block-current" key={index}>
<li>{index + 1}</li>
<li>{item.name ? '真实姓名' : '你个骗子'}</li>
<li>{item.age}</li>
<li>{item.address}</li>
</ul>
)
} else {
return (
<ul className="ul-block" key={index}>
<li>{index + 1}</li>
<li>{item.name ? '真实姓名' : '你个骗子'}</li>
<li>{item.age}</li>
<li>{item.address}</li>
</ul>
)
}
})}
</div>
</>
)
}
})
utils/defineCom.js
import {
h,
defineComponent
} from "vue";
const clientComponent = defineComponent({
name: "clientComponent",
props: {
},
setup() {
console.log("[我是组件-defineComponent]")
},
render() {
return h('div', '我是组件')
}
})
export default clientComponent;
utils/DragIcon.js
"use strict"
/**
* 可拖拽悬浮框
*
* el:被拖拽的元素,如:#dragIcon|.dragIcon
*
* top:初始化悬浮框距离窗口顶部的距离,如100px|10%
*
* left:初始化悬浮框距离窗口左边的距离,如100px|10%
*
* onClick:悬浮框点击触发事件
**/
class DragIcon {
static DEFINED_CONFIG = {
el: '#dragIcon',
top: '100px',
left: '100px',
onClick: () => {
}
}
constructor(options) {
console.log("[]", options)
if (Object.prototype.toString.call(options) !== '[object Object]') {
throw "配置项必须为对象,你传递的是" + Object.prototype.toString.call(options);
}
this.config = Object.assign({}, DragIcon.DEFINED_CONFIG, options);
this.dragElement = document.querySelector(this.config.el);
this.clientWidth = document.documentElement.clientWidth || window.innerWidth;
this.clientHeight = document.documentElement.clientHeight || window.innerHeight;
this.create();
this.drag();
this.isDragging = false; // 初始化时未拖拽
}
/**
* 初始化悬浮框
**/
create() {
const {
top,
left
} = this.config;
this.dragElement.style.top = `${top}`;
this.dragElement.style.left = `${left}`;
}
/**
* 悬浮框拖拽事件
**/
drag() {
this.dragElement.addEventListener("mousedown", (e) => {
e.preventDefault();
this.isDragging = true; // 拖拽开始
const rect = this.dragElement.getBoundingClientRect();
const disX = e.clientX - rect.left;
const disY = e.clientY - rect.top;
const onMouseMove = (e) => {
let moveX = e.clientX - disX;
let moveY = e.clientY - disY;
moveX = Math.min(moveX, this.clientWidth - rect.width);
moveY = Math.min(moveY, this.clientHeight - rect.height);
moveX = Math.max(0, moveX);
moveY = Math.max(0, moveY)
this.dragElement.style.left = `${moveX}px`;
this.dragElement.style.top = `${moveY}px`;
this.isDragging = false; // 拖拽结束
}
const onMouseUp = () => {
window.removeEventListener("mousemove", onMouseMove);
window.removeEventListener("mouseup", onMouseUp);
this.onClick();
}
window.addEventListener("mousemove", onMouseMove);
window.addEventListener("mouseup", onMouseUp);
});
}
/**
* 悬浮框点击事件
**/
onClick() {
if (this.isDragging) {
this.config.onClick();
this.isDragging = false; // 拖拽结束
}
}
}
export default DragIcon;
utils/someName.ts
namespace MiaoName {
export interface person {
name: string;
age: number;
}
export interface student extends person {
school: string;
}
class Miao implements student {
name: string;
age: number;
school: string;
constructor(name: string, age: number) {
this.name = name;
this.age = age
}
}
}
utils/TS.ts
class People {
/**
* public:公共访问修饰符,可以在类内或者类外使用public修饰的属性或者行为,默认修饰符。
* private:私有访问修饰符,只能在类内使用private修饰的属性或者行为。
* protected:受保护的访问修饰符,可以本类和子类中使用protected修饰的属性和行为。
* **/
public _firstName: string;//公共属性
public _lastName: string;//公共属性
private _age: number;//私有属性
protected _phone: number;//受保护的属性
//公共属性与静态属性的区别
//公共属性:每次实例化都会生成一个新的属性
//静态属性:每次实例化都会共用一个属性
static _site: string = "www.baidu.com";//静态属性
_website: string = "www.baidu.com";//公共属性
//什么是静态成员?
//静态成员是指在类中通过static修饰的属性或者方法,静态成员只能通过类名.的方式调用。
//静态成员可以被继承吗?
//可以
//静态成员可以被子类重写吗?
//不可以
//静态成员可以被实例化调用吗?
//不可以
//静态成员可以被实例化修改吗?
//不可以
//静态成员可以被实例化删除吗?
//不可以
//静态成员可以被实例化添加吗?
//不可以
//静态成员可以被实例化访问吗?
//不可以
//静态成员可以被实例化继承吗?
//不可以
//静态成员可以被实例化重写吗?
//不可以
//静态成员可以被实例化调用吗?
//不可以
//什么是实例成员?
//实例成员是指在类中通过this.的方式定义的属性或者方法,实例成员只能通过实例化对象.的方式调用。
//实例成员可以被继承吗?
//可以
//实例成员可以被子类重写吗?
//可以
//实例成员可以被实例化调用吗?
//可以
//实例成员可以被实例化修改吗?
//可以
//实例成员可以被实例化删除吗?
//可以
//实例成员可以被实例化添加吗?
//可以
//实例成员可以被实例化访问吗?
//可以
//实例成员可以被实例化继承吗?
//可以
//实例成员可以被实例化重写吗?
//可以
//实例成员可以被实例化调用吗?
//可以
//实例员工分为哪几种?
//公共实例成员:公共实例成员是指在类中通过public修饰的属性或者方法,公共实例成员可以在本类、子类和实例化对象中使用。
//私有实例成员:私有实例成员是指在类中通过private修饰的属性或者方法,私有实例成员只能在本类中使用。
//私有实例成员:私有实例成员是指在类中通过private修饰的属性或者方法,私有实例成员只能在本类中使用。可以被实例化调用吗?
//不可以
//受保护的实例成员:受保护的实例成员是指在类中通过protected修饰的属性或者方法,受保护的实例成员只能在本类和子类中使用。
//受保护的实例成员:受保护的实例成员是指在类中通过protected修饰的属性或者方法,受保护的实例成员只能在本类和子类中使用。可以被实例化调用吗?
//不可以
//静态实例成员:静态实例成员是指在类中通过static修饰的属性或者方法,静态实例成员只能通过类名.的方式调用。
constructor(firstName: string, lastName: string, age: number, phone: number) {
console.log("构造函数");
this._firstName = firstName;
this._lastName = lastName;
this._age = age;
this._phone = phone;
this.showAge();
console.log("[static]", People._site);
console.log("[public]", this._website);
}
/**
* void:用于标识方法返回值的类型,表示该方法没有返回值。
* **/
init(): void {
console.log("init");
console.log("[public]", this._firstName);
console.log("[public]", this._lastName);
console.log("[private]", this._age);
console.log("[protected]", this._phone);
const price: number = 103;
const num: number = 2.456;
const total: number = price * num;
console.log("[number]", total);
interface person {
name: string,
age: number,
phone?: number,
family?: family[]
}
interface family {
name: string,
age: number,
phone: number
}
let dataList: person[] = [];
dataList.push({ name: "张三", age: 18, phone: 123456789 });
dataList.push({ name: "张三", age: 18, phone: 123456789, family: [{ name: "张三", age: 18, phone: 123456789 }] });
console.log("[interface]", dataList);
dataList[0].age = 19;
console.log("[interface]", dataList);
dataList.forEach((item: person, index: number) => {
console.log("[interface]", item, index);
})
}
get firstName(): string {
return this._firstName;
}
set firstName(value: string) {
this._firstName = value;
}
showFullName(): string {
console.log("[姓名:]", this._firstName + "" + this._lastName);
return this._firstName + "" + this._lastName;
}
private showAge(): number {
console.log("[年龄:]", this._age);
return this._age;
}
protected showPhone() {
console.log("[手机号:]", this._phone);
}
}
const site = new People("张", "三", 18, 123456789);
console.log(site.firstName);
site.firstName = "李";
console.log(site.firstName);
site.showFullName();
site.init();
console.log("[People]", People._site);
/**
* 子类继承父类
* **/
class Woman extends People {
constructor(firstName: string, lastName: string, age: number, phone: number) {
super(firstName, lastName, age, phone);
console.log("子类构造函数");
console.log("[Woman]", Woman._site);
}
show() {
console.log("子类", this._phone);
}
}
const woman = new Woman("李", "四", 19, 123456789);
woman.show();
//子类可以使用父类的静态属性吗?
//可以
//子类可以使用父类的公共属性吗?
//可以
//子类可以使用父类的私有属性吗?
//不可以
//子类可以使用父类的受保护的属性吗?
//可以
console.log("[Woman]", Woman._site)
//循环数据时,使用forEach,for,find,还是map
//forEach:只能遍历数组,不能return,不能返回一个新的数组
//for:可以遍历数组,可以return,返回一个新的数组
//map:可以遍历数组,可以return,返回一个新的数组
//find:可以遍历数组,可以return,只返回第一个符合条件的数据
const dataList: any[] = [{
name: "张三",
age: 18,
phone: 123456789
}, {
name: "张四",
age: 19,
phone: 123456789
}, {
name: "张五",
age: 20,
phone: 123456789
}, {
name: "张六",
age: 21,
phone: 123456789
}, {
name: "张七",
age: 22,
phone: 123456789
}, {
name: "张八",
age: 23,
phone: 123456789
}]
dataList.map((item: any, index: number) => {
item['id'] = index
return item;
})
console.log("[map]", dataList);
dataList.find((item: any, index: number) => {
item['code'] = index;
return item
})
console.log("[find]", dataList);
dataList.forEach((item: any, index: number) => {
item['code'] = index;
})
console.log("[forEach]", dataList);
const str: string = "MiaoZhenZhen";
console.log("[slice]", str.slice(2, 3));
console.log("[substr]", str.substr(2, 3));
console.log("[substring]", str.substring(2, 3));
const count = new Number(123);
console.log("[toString]", count);
console.log("[valueOf]", count.valueOf());
//slice:截取字符串,返回一个新的字符串,不会改变原来的字符串
//substr:截取字符串,返回一个新的字符串,不会改变原来的字符串
//substring:截取字符串,返回一个新的字符串,不会改变原来的字符串
//slice与substring的区别:slice可以接受负数,substring不可以接受负数
//slice与substr的区别:slice第二个参数是截取的长度,substr第二个参数是截取的结束位置
const temp = [{
name: "张三1",
}, {
name: "张三2",
}]
console.log("[temp]", temp);
temp.push({
name: "张三3",
})
console.log("[temp]", temp);
//为什么两次console。log(temp)值一样
//因为temp是一个引用类型,指向的是同一个内存地址,所以改变temp的值,会改变内存地址的值,所以两次打印的值一样
//如何解决两次值一样的问题?
//使用深拷贝,浅拷贝
//深拷贝:拷贝的是值,不是内存地址
//浅拷贝:拷贝的是内存地址,不是值
//如何实现深拷贝?
//JSON.parse(JSON.stringify(temp))
//如何实现浅拷贝?
//Object.assign({},temp)
const tempStr = JSON.parse(JSON.stringify(temp));
console.log("[JSON.parse(JSON.stringify(temp))]", tempStr);
tempStr.push({
name: "张三4",
})
console.log("[JSON.parse(JSON.stringify(temp))]", tempStr);
//使用JSON.parse(JSON.stringify(temp))实现深拷贝,但是有一个问题,如果temp中有函数,会怎么样?
//函数会被忽略掉
//使用Object.assign({},temp)实现浅拷贝,但是有一个问题,如果temp中有函数,会怎么样?
//函数会被忽略掉
//使用JSON.parse(JSON.stringify(temp))处理过的数据,需要重新赋值新变量吗?
//需要
//为什么不能继续使用temp变量
//因为temp变量已经被重新赋值了
//如果继续使用temp变量,会怎么样?
//会报错,因为temp变量已经被重新赋值了
//在js中,每创建一个变量,都会在内存中开辟一个空间,存储这个变量的值,
//如果这个变量的值是一个引用类型,那么这个变量存储的是一个内存地址,这个内存地址指向的是引用类型的值,
//如果这个变量的值是一个基本类型,那么这个变量存储的是一个基本类型的值,
//什么是基本类型?什么是引用类型?
//基本类型:string,number,boolean,null,undefined,symbol
//引用类型:object,array,function
//如何判断一个变量是基本类型还是引用类型?
//typeof
const tempArr: any[] = ["miao", "zhen", "zhen", 1, 3, 5, 6, 8];
console.log("[tempArr]", tempArr.join(","));
console.log("[tempArr]", tempArr.toString());//join(",")与toString()的区别?
//元组和数组的区别?
//元组:可以存储不同类型的数据
//数组:只能存储相同类型的数据
//元组和数组的相同点?
//都可以存储多个数据
//如何定义元组?
const tempTuple: [string, number, boolean] = ["miao", 1, true]
tempTuple.push("zhen")
console.log("[tempTuple]", tempTuple);
//如何定义数组?
//const tempArr:any[] = ["miao",1,true]
//如何获取元组中的数据?
//tempTuple[0]
//如何获取数组中的数据?
//tempArr[0]
//如何修改元组中的数据?
//tempTuple[0] = "zhen"
//如何修改数组中的数据?
//tempArr[0] = "zhen"
const tempMap = new Map();
tempMap.set("name", "miao");
tempMap.set("age", 18);
console.log("[tempMap]", tempMap);
console.log("[Map-1]", Map)
console.log("[Map-tempMap-2]", tempMap)
//Map有原型吗?
//有
//Map的原型是什么?
//Map.prototype
//Map的原型是谁?
//Map.prototype.constructor
///<reference path="./test.ts" />
console.log(Object.prototype)
const obj: { name: string, age: number, school: string } = {
name: "miao",
age: 18,
school: '北京大学'
};
const obj1: MiaoName.student = {
name: "miao",
age: 18,
school: '北京大学'
};
console.log("[obj]", obj);
//如何引入其他文件的内容?
console.log("[MiaoName.temp]",)
const p: MiaoName.person[] = [{
name: "miao",
age: 18
}]
const p1: MiaoName.student[] = [{
name: "miao",
age: 18,
school: '北京大学'
}]
console.log("[MiaoName.temp]", p)
console.log("[MiaoName.temp]", p1)
function test(): MiaoName.person[] {
return [{
name: "miao",
age: 18
}]
}
console.log("[MiaoName.temp]", test.prototype.constructor())
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age
}
say() {
console.log("[say]", "hello")
}
}
stores/client.js
import {
defineStore
} from "pinia";
export const useClientStore = defineStore("client", {
state: () => {
return {
name: '忽必烈',
age: 29,
salary: 10,
phone: '18895350000'
}
},
getters: {
totalSalary: (state) => {
console.log("[state]", state)
return state.age * state.salary
}
},
actions: {
setAge(params) {
console.log("[params]", params)
this.age = params;
}
}
})
stores/message.js
import {
defineStore
} from "pinia";
import {
computed,
ref
} from "vue";
export const useMessageStore = defineStore("message", () => {
const title = ref("标题");
const content = ref("内容");
const count = ref(0);
const totalCount = computed(() => {
return count.value * 12
})
function setCount(params) {
console.log("[]", params)
count.value = params
}
return {
title,
content,
totalCount,
setCount
}
})
router/index.js
import {
createRouter,
createWebHistory
} from 'vue-router'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [{
path: '',
redirect: '/docs',
}, {
path: '/docs',
name: 'Docs',
meta: {
title: '文档'
},
component: () => import('@/views/Docs.vue')
},
{
path: '/tutorial',
name: 'Tutorial',
meta: {
title: '教程'
},
component: () => import('@/views/Tutorial.vue')
},
{
path: '/blog',
name: 'Blog',
meta: {
title: '博客'
},
component: () => import('@/views/Blog.vue')
},
{
path: '/community',
name: 'Community',
meta: {
title: '社区'
},
component: () => import('@/views/Community.vue')
},
{
path: '/about',
name: 'About',
meta: {
title: '关于'
},
component: () => import('@/views/About.vue')
},
{
path: '/ts',
name: 'Ts',
meta: {
title: 'TypeScript 教程'
},
component: () => import('@/views/TS.vue')
}
],
scrollBehavior: () => {
return {
top: 0
}
}
})
import {
useClientStore
} from '@/stores/client'
router.beforeEach((to, from, next) => {
console.log("[to]", to)
const store = useClientStore();
console.log("[store]", store)
next();
})
export default router
components/createHtml.vue
<script>
import { defineComponent } from 'vue';
export default defineComponent({
data() {
return {
count: 0,
};
},
render() {
return (
<div>
<h1>当前计数:{this.count}</h1>
<button onClick={() => this.count++}>增加</button>
</div>
);
},
});
</script>
components/footer.vue
<template>
<div class="footer-wrap">
<slot name="left" v-if="!isShow"></slot>
<p>Copyright © <slot name="center"></slot> Meta Platforms, Inc.</p>
<slot name="right" v-if="isShow"></slot>
</div>
</template>
<script setup>
import {
ref,
watch
} from 'vue';
const publice = ref('123');
const isShow = ref(true)
function init() {
console.log("[我是footer]")
publice.value = '456';
}
watch(publice, (value) => {
console.log("[我改变了]", value, publice.value)
isShow.value = false;
})
defineExpose({
init,
publice
})
</script>
<style lang="scss" scoped>
.footer-wrap {
width: 100%;
min-height: 100px;
background-color: rgb(249, 249, 251);
display: flex;
justify-content: center;
align-items: center;
}
</style>
components/header.vue
<template>
<div class="header-wrap">
<div class="header-tips">This site is no longer updated.</div>
<ul class="header-content">
<li class="header-icon" @click="goLinkHandle('docs')">
<img :src="icon" />
<span>React</span>
</li>
<template v-for="(item,index) in menuList" :key="index">
<li class="header-li" :class="{'header-li-current':currentPath==item.path}"
@click="goLinkHandle(item.type)">{{item.name}}</li>
</template>
</ul>
</div>
<div id="dragIcon"></div>
</template>
<script setup>
import dragIcon from "miao-drag";
import {
watch,
ref,
reactive,
onMounted
} from 'vue';
import {
useRoute,
useRouter
} from 'vue-router';
const icon = ref(
'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ii0xMS41IC0xMC4yMzE3NCAyMyAyMC40NjM0OCI+CiAgPHRpdGxlPlJlYWN0IExvZ288L3RpdGxlPgogIDxjaXJjbGUgY3g9IjAiIGN5PSIwIiByPSIyLjA1IiBmaWxsPSIjNjFkYWZiIi8+CiAgPGcgc3Ryb2tlPSIjNjFkYWZiIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9Im5vbmUiPgogICAgPGVsbGlwc2Ugcng9IjExIiByeT0iNC4yIi8+CiAgICA8ZWxsaXBzZSByeD0iMTEiIHJ5PSI0LjIiIHRyYW5zZm9ybT0icm90YXRlKDYwKSIvPgogICAgPGVsbGlwc2Ugcng9IjExIiByeT0iNC4yIiB0cmFuc2Zvcm09InJvdGF0ZSgxMjApIi8+CiAgPC9nPgo8L3N2Zz4K'
)
const currentPath = ref('');
const route = useRoute();
watch(route, (params) => {
currentPath.value = params.path;
}, {
deep: true,
immediate: true
})
onMounted(() => {
console.log("[onMounted]")
setDragIcon();
});
const menuList = reactive([{
id: 1,
name: 'Docs',
path: '/docs',
type: 'docs'
}, {
id: 2,
name: 'Tutorial',
path: '/tutorial',
type: 'tutorial'
}, {
id: 3,
name: 'Blog',
path: '/blog',
type: 'blog'
}, {
id: 4,
name: 'Community',
path: '/community',
type: 'community'
}, {
id: 5,
name: 'About',
path: '/about',
type: 'about'
}, {
id: 5,
name: 'TypeScript 教程',
path: '/ts',
type: 'ts'
}])
//进行页面跳转
const router = useRouter();
function goLinkHandle(type) {
if (type == 'docs') {
router.push({
path: '/docs'
})
} else if (type == 'tutorial') {
router.push({
path: '/tutorial'
})
} else if (type == 'blog') {
router.push({
path: '/blog'
})
} else if (type == 'community') {
router.push({
path: '/community'
})
} else if (type == 'about') {
router.push({
path: '/about'
})
} else if (type == 'ts') {
router.push({
path: '/ts'
})
}
}
function setDragIcon() {
const clientHeight = document.documentElement.clientHeight;
const clientWidth = document.documentElement.clientWidth;
new dragIcon({
el: '#dragIcon',
top: ((clientHeight / 2) - 50) + 'px',
left: (clientWidth - 250) + 'px',
onClick: () => {
console.log("我是点击事件")
}
});
}
</script>
<style lang="scss" scoped>
.header-wrap {
width: 100%;
display: flex;
flex-direction: column;
background-color: rgb(22, 24, 29);
.header-tips {
width: 100%;
max-width: 1200px;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
font-size: 18px;
font-weight: bold;
color: #ffffff;
margin: 12px auto;
}
.header-content {
width: 100%;
max-width: 1200px;
display: flex;
flex-direction: row;
margin: 12px auto;
align-items: center;
.header-icon {
height: auto;
display: flex;
flex-direction: row;
color: #61dafb;
align-items: center;
justify-content: center;
margin-right: 100px;
cursor: pointer;
img {
width: 40px;
height: 40px;
}
span {
font-weight: 700;
font-size: 20px;
margin-left: 12px;
}
}
.header-li {
height: 40px;
position: relative;
font-size: 18px;
color: #ffffff;
padding-left: 15px;
padding-right: 15px;
cursor: pointer;
}
.header-li-current {
color: #61dafb;
}
.header-li-current::after {
content: " ";
height: 3px;
position: absolute;
width: 100%;
left: 50%;
transform: translate(-50%);
bottom: 0px;
background-color: #61dafb;
animation: identifier 1s ease;
}
@keyframes identifier {
0% {
width: 0%;
}
100% {
width: 100%;
}
}
}
}
#dragIcon {
border: 1px solid #00a2ef;
border-radius: 8px;
width: 100px;
height: 100px;
position: fixed;
cursor: pointer;
z-index: 999;
}
</style>
components/test.vue
<template>
<div>
<p>{{message}}</p>
</div>
</template>
<script>
export default {
props: {
message: {
type: String,
default: () => {
return "消息"
}
}
},
setup(props) {
console.log("[props]", props)
console.log("[this]", props.message)
return {
}
}
}
</script>
<style>
</style>
assets/base.css
* {
padding: 0px;
margin: 0px;
box-sizing: border-box;
-webkit-box-sizing: border-box;
}
html,
body {
width: 100%;
background-color: #f2f2f2;
}
a {
text-decoration: none;
}
ul,
li,
ol {
list-style: none;
}
button {
cursor: pointer;
}
button::after {
border: none;
}
assets/main.scss
@import './base.css';
@import './styles.scss';
.ping-wrap {
width: 100%;
display: flex;
flex-direction: column;
.ping-container {
width: 100%;
max-width: 1200px;
min-height: 100vh;
margin: 0px auto;
display: flex;
flex-direction: column;
background-color: #fff;
}
}
assets/styles.scss
.row {
border: 1px solid red;
width: 100%;
display: flex;
}
.col-6 {
border: 1px solid red;
width: 50%;
}
.ul-block {
border: 1px solid #dcdcdc;
border-radius: 12px;
padding: 10px;
margin-bottom: 12px;
li {
border-bottom: 1px solid #dcdcdc;
padding: 12px 0px;
}
li:last-child {
border-bottom: none;
}
}
.ul-block-current{
border: 1px solid #00a2ef;
}
vue3.0官网
Pinia官网
Vue Router4.X官网
Vite官网
https://github.com/zzmiao/vue3.0.git