vite

1、npm init vite@latest // 简单版,不只适用于vue(react也可以)

npm init vue@latest // 复杂版,更多选项(针对vue做了封装)

 

2、配置文件

// **********************************************
// package.json 文件
// **********************************************

***
"dev": "vite --host 0.0.0.0",
***


// **********************************************
// vite-env.d.ts 文件
// **********************************************

/// <reference types="vite/client" />

declare module '*.vue' {
  import type { DefineComponent } from 'vue'
  const component: DefineComponent<{}, {}, any>
  export default component
}

 

3、安装插件

// 安装less
cnpm install less

 

4、安装volar 2个插件【Vue Language Features (Volar)、TypeScript Vue Plugin (Volar)】,禁用vetur【有冲突,适用于vue2】

 

5、页面模版代码

<template>
  <div>{{ xxx }}</div>
</template>
 
 
<script setup lang="ts">
import { ref, shallowRef } from 'vue'
const name = ref<string>('xxx')
</script>

<style lang="less" scoped>
</style>

 

语法

1、

// v-text
<div v-text="a">

// v-html
<div v-html="a">

// v-if
<div v-if="a=='a'">
    a
</div>
<div v-else-if="a=='b'">
    b
</div>
<div v-else>
    c
</div>

//动态修改事件
const click:string='dblclick'
  const xxx = () => {
  console.info("xxx")
}
<button @[click].stop="xxx">双击我</button>   <!-- .stop 阻止冒泡 .once 只点击一次 .prevent阻止(submit阻止刷新页面)   其他的可以看自动提示 -->
 
// 绑定属性 v-bind
const id:string = '1001'
const style = {
  color:'red',
  border:'1px solid red'
}
const classOption = true
 
<div v-bind:id="id"></div>    <!-- 简写【:】,可以绑定任何属性 -->
<div :style="style">sdfsd</div>
<div class="d" :class="classOption? ['a','s']:'b'">sdfsd</div>    <!-- 静态、动态class可以各一个 -->
 
.a{
border:1px solid red
}
.b{
border:1px solid blue
}
.d{
font-weight: bold;
}
.s{
font-size: 40px;
}
 
// 绑定数据 v-model     // ref 或 reactive 才是响应式的
import {ref} from 'vue'
const a=ref('asdf')
 
<input v-model="a" type="text">
<div>{{ a }}</div>
 
// 循环 v-for
const arr:string[] = ['北京','重庆']
const arrObj = [{id:'1001',name:"北京"},{id:'1002',name:"重庆"}]
 
<div :key="index" v-for="(item,index) in arr">
  <p>{{ index }} - {{ item }}</p>
</div>
<div :key="item.id" v-for="(item,index) in arrObj">
  <p>{{ index }} - {{ item.id }} - {{ item.name }}</p>
</div>
 
 
// ref、reactive 添加ref、reactive才能双向绑定    
// 区别1:reactive不支持基本类型,只支持引用类型
// 区别2:reactive调用属性时,可以不用.value
// 区别3:reactive不能直接附值(会破坏proxy,页面不会渲染),如果是数组可以push+解构(...arr),其他类型数据可以放到对象里面的一个属性上,保障proxy不会被破坏
// 总结:异步时尽量不用reactive,比较麻烦
type T = { // 定义一个相对复杂对象 相当于list<map>    // ref 略,上面讲到了
  id:string
  name:string
}[]
const arrObj = reactive<T>([{id:'1001',name:"北京"},{id:'1002',name:"重庆"}])
const click = () => {
  const temp:T = [{id:'9001',name:"改变了1"},{id:'9001',name:"改变了2"}]
  // arrObj = temp // 直接附值会破坏proxy,数据不会渲染到页面
  arrObj.length=0
  arrObj.push(...temp)
}
 
<div :key="item.id" v-for="(item,index) in arrObj">
  <p>{{ index }} - {{ item.id }} - {{ item.name }}</p>
</div>
<button @click="click">点击我接收后台数据</button>
 
//计算 computed   // 解决场景:复杂计算场景,不用封装计算的方法每次调用,只需要修改关联值就行了,采用computed包裹,修改了关联值会触发回调自动重新计算
const n1 = ref<number>(0)
const n2 = ref<number>(0)
let number1 = computed(()=>{
  return n1.value+n2.value
})
 
<input type="number" v-model="n1">
<input type="number" v-model="n2">
计算结果:{{ number1 }}
 
// 计算2 watchEffect
const a1 = ref<string>('')
const a2 = ref<string>('')
const watchEffect1 = watchEffect((oninvalidate)=>{
  let btn:HTMLButtonElement = document.querySelector('#btn') as HTMLButtonElement // as ... 断言
  console.info('btn EL:',btn)
  console.log('a1:'+a1.value)
  oninvalidate(()=>{ // 监听之前执行
  console.info("************* before *************")
})
},{
  flush:'post', // 组件更新后执行,其他参数看自动提示
  onTrigger(e){
    debugger // 断点调试
  }
})
const stopWatch = () => watchEffect1() // watchEffect1返回的就是stop函数,一旦被执行,就停止监听
 
<input type="text" v-model="a1">
<input type="text" v-model="a2">
<button id="btn" @click="stopWatch">停止监听</button>

 

// 父子组件传值
// 父组件 -> 子组件

// 父组件
import Menu from "./Menu/index.vue"
const name ="名称"

<Menu :title="name" :arr="[1,2,3]"></Menu>

// 子组件
// 方式一:普通js型
// const props = defineProps({
//     title:{
//         type:String,
//         default:"未设置默认值"
//     }
// })

// 方式二:ts方式 defineProps(简约版,推荐)
const props = defineProps<{
    title:string,
    arr:number[],
}>()

// 方式三:ts方式 withDefaults(复杂版,支持默认值设置,不传参数也会有警告)
// const props = withDefaults(
//     defineProps<{
//     title:string,
//     arr:number[],
// }>(),
// {
//     arr:()=>[666]   // 当没有传递arr参数时,为arr设置的默认值
// }
// )
console.log("【父组件给子组件传值】在子组件中打印,父组件传递给子组件的title值为:"+props.title)
console.log("【父组件给子组件传值】在子组件中打印,父组件传递给子组件的arr值为:"+props.arr)

<div class="menu">
    标题:{{ title }}
    其他:{{ arr }}
</div>


// 子组件 -> 父组件

// 父组件
onMounted(()=>{
  console.info("【子组件给父组件传值】在父组件中打印,子组件暴露给父组件的属性name的值为:"+menuComponents.value?.name)
  const funRlt = menuComponents.value?.open('asdf')
  console.info(funRlt)
})
const menuComponents = ref<InstanceType<typeof Menu>>();
const getInfo = (name:string) => {
  console.info("【子组件给父组件传值】在父组件中打印,【点击按钮时】子组件传递给父组件的name值为:"+name)
}
const getInfo2 = (name:string) => {
  console.info("【子组件给父组件传值】在父组件中打印,【点击按钮时】子组件传递给父组件的name值为:"+name)
  console.info("【子组件给父组件传值】在父组件中打印,子组件暴露给父组件的属性name的值为:"+menuComponents.value?.name)
}

<Menu @on-click="getInfo" @on-click2="getInfo2"></Menu>

// 子组件

// 方式一:js方式
// const emit = defineEmits(['on-click','on-click2'])
// const send = () => {
//     emit('on-click','我是子组件的name')
// }
// const send2 = () => {
//     emit('on-click2','我是子组件的name2')
// }

// 方式二:ts方式
const emit = defineEmits<{
    (emit:"on-click",name:string):void
    (emit:"on-click2",name:string):void
}>()
const send = () => {
    emit('on-click','我是子组件的name')
}
const send2 = () => {
    emit('on-click2','我是子组件的name')
}

// 方式三:暴露方法或属性
defineExpose({
    name:"123456",
    open:(param:string)=>{
        console.info("我是子组件中的方法,我打印了一句话,父组件还给我传了一个参数param:"+param)
        return param+"kkkk"
    }
})

<button @click="send">第一个按钮</button>
<button @click="send2">第二个按钮</button>

 

posted @ 2023-02-13 00:01  vv_online  阅读(70)  评论(0编辑  收藏  举报