个人技术分享

Vue 使用一种基于 HTML 的模板语法,使我们能够声明式地将其组件实例的数据绑定到呈现的 DOM 上。所有的 Vue 模板都是语法层面合法的 HTML,可以被符合规范的浏览器和 HTML 解析器解析。在底层机制中,Vue 会将模板编译成高度优化的 JavaScript 代码。结合响应式系统,当应用状态变更时,Vue 能够智能地推导出需要重新渲染的组件的最少数量,并应用最少的 DOM 操作。 


 使用vite创建一个vue+JavaScript项目

npm create vite
npm install 
npm run dev

1. 插值表达式

插值表达式:最基本的数据绑定形式是文本插值,它使用的是“Mustache”语法 ,即双大括号`{{}}`

<script setup>
  //定义变量  
  let msg = 'hello world'
  //定义函数
  let fun = () => {
    return 'hello china'
  }
  //定义对象
  let compurse = [{name:'纽纳', number:3, price:9}, {name:'牛', number:8, price:60}]
  function add() {
    let count = 0;
    for(let index in compurse) {
      count += compurse[index].price * compurse[index].number
    }
    return count
  }

</script>

<template>
  <div>
    <!--插值表达式 {{  }}-->
    {{ msg }}
    <h1>{{ msg }}</h1>
    {{ fun() }} <hr>
    {{ add() }} <hr>
    {{ compurse }}
 </div>
</template>

<style scoped>

 2. 文本渲染命令

/**

   * v-text:不识别html结构的文本 类似于innerText

   * v-html:识别html结构的文本        innerHtml

   * 插值表达式{{}}

   * v-*** vue命令(该命令必须在标签中使用才生效)

   */

<script setup>
  let msg = "hello wrold"
  //命令支持模板字符串
  let msg2 = `hello ${"china"}`
  //命令支持常见运算符
  let age = 19
  //命令支持常见对象的API调用
  let bee = '蜜,蜂'
  //命令支持函数调用
  function hello() {
    return 'hello'
  }
  //命令中支持
  let msg3 = '<h1>哈哈</h1>'
</script>

<template>
  <div>
    <h1 v-text="msg"></h1>
    <h1 v-text="msg2"></h1>
    <h1 v-text="`hello ${'china'}`"></h1>
    <h1 v-text="age > 18 ? '成年' : '未成年'"></h1>
    <h1 v-text="bee.split(',')[0]"></h1>
    <h1 v-text="hello()"></h1>
    <h1 v-html="msg3"></h1>
  </div>
</template>

<style scoped>

</style>

 3. 属性渲染命令

/***

 * 属性渲染命令:v-bind:属性名=

 */

<script setup>
let dregon = {
    picture: 'demo1-html\img\屏幕截图 2024-03-23 162925.png',
    name: '奶龙',
    href:'https://blog.csdn.net/2301_79526467?type=blog'
}
</script>

<template>
    <a v-bind:href="dregon.href">
        <img v-bind:src="dregon.picture" v-bind:title="dregon.name">
    </a>
</template>

<style scoped>

</style>

 4. 事件渲染命令

  /***

     * 事件渲染命令语法:

     * v-on:事件名=函数名()

     * @事件名=函数名()

     * 原生js中绑定事件:onclick ondbclick ...

     * vue事件命令事件名去掉on即可 此时click dbclick

     */

<script setup>
    import {ref} from 'vue'
    let count = ref(10)

    function add() {
        count.value++
    }

    function desc() {
        count.value--;
    }

    function p(event) {
        let flag = confirm("确认要跳转页面吗?")
        console.log(flag)
        if (!flag) {
            //原生js方式阻止提交
            event.preventDefault()
        }
    }
</script>

<template>
    <div>
        <!--vue事件渲染命令-->
        <button v-on:click="add()">+</button>
        {{ count }}
        <button @click="desc()">-</button>
        <!--函数内联(即要执行的函数体直接放入此处)-->
        <button v-on:click="count--">hello</button>
        <!--事件修饰符once prevent
        once:只生效一次
        prevent:直接阻止提交
        -->
        <a href="https://blog.csdn.net/2301_79526467?type=blog" v-on:click="p($event)">奶龙鸭</a>
    </div>
</template>

<style scoped>

</style>

 5. 响应式数据

/***

 * 响应式数据处理方式

 * 1.ref函数:多用于响应单个数据

 *      在script标签中改变值需通过.value的形式

 *      在template标签中改变值不需要通过.value形式

 * 2.reactive函数:多用于响应对象

 *      在script、template中处理响应式数据直接通过 对象名.属性名处理即可

 */

<script setup>
import { ref, reactive } from 'vue'
let num = ref(10);

function add() {
    num.value++
}

let people = reactive(
    {
        name: 'zhangsan',
        age: 19
    }
)

</script>

<template>
    <div>
        <button @click="add()">+</button>
        {{ num }} <hr>
        <button @click="people.age++">age</button>
        {{ people }}
    </div>
</template>

<style scoped>

</style>

 6. 条件渲染命令

/**

 * 条件渲染命令:

 * v-if:条件未true则执行该命令

 * v-else:不满足if则执行该else命令

 *

 * v-show:为true则展示

 *

 * v-if和v-show区别:

 * v-if只有条件为true时才会进行渲染

 * v-show不论初始化条件是否为true都会进行渲染保留在dom树中,只是通过display进行控制

 */

<script setup>
import {ref} from 'vue'
let flag = ref(true)
</script>

<template>
    <diV>
        <h1 id="a" v-if="flag">if执行啦</h1>
        <h1 id="b" v-else>else执行啦</h1>
        <h1 id="c" v-show="flag">show展示</h1>
        <button @click="flag = !flag">展示</button>
    </diV>
</template>

<style scoped>

</style>

 7. 列表渲染命令

/**

 * 列表渲染:

 * v-for命令

 * 语法规则:

 * v-for="变量名 in 数组名" 类似于Java中的forEach语句 for(变量名 : 数组名)

 * 该命令尽量加上key属性

 * 如:v-for="item, index in items" v-bind:key="item.id"

 * 第一个参数表示迭代到的当前数据的变量名,第二个参数表示当前数据的数组下标

 */

<script setup>
import {reactive} from 'vue'
//商品列表
let items = reactive([
    {
        id: 'item1',
        name: '牛奶',
        price: 3.5,
        num: 12
    },
    {
        id: 'item2',
        name: '薯片',
        price: 6,
        num: 18
    },
    {
        id: 'item3',
        name: '炸鸡',
        price: 19,
        num: 3
    }
])
//删除单个商品函数
function removeItem(index) {
    //调用数组的api删除,index表示从哪开始,1代表要删除数组内多少个数据
    items.splice(index, 1)
}
//计算商品总金额函数
function count() {
    let tem = 0;
    for(let index in items) {
        tem += items[index].price * items[index].num
    }
    return tem
}
//清空购物车
function removeAll() {
    items.splice(0, items.length)
}
</script>

<template>
    <div>
        <h1>皇家购物车</h1>
        <table border="black">
            <thead>
                <td>序号</td>
                <td>商品</td>
                <td>价格</td>
                <td>数量</td>
                <td>小计</td>
                <td>操作</td>
            </thead>
            <tbody v-for="item, index in items" v-bind:key="item.id">
                <td>{{ index + 1 }}</td>
                <td>{{ item.name }}</td>
                <td>{{ item.price }}</td>
                <td>{{ item.num }}</td>
                <td>{{ item.price * item.num }}</td>
                <button @click="removeItem(index)">删除</button>
            </tbody>
            <td colspan="5">
                商品总金额:{{ count() }}
            </td>
            <button @click="removeAll()">清空</button>
        </table>

        <hr>
        <ul>
            <li v-for="item, index in items" v-bind:key="item.id">
                {{ index + 1 }}
                {{ item.name }}
            </li>
        </ul>
    </div>
    
</template>

<style scoped>

</style>

 8. 双向绑定

/**

 * 单向绑定

 * 如:v-bind:value="变量名"

        单向绑定也可以 :value='变量名'

 * 双向绑定

 * v-model="变量名"

 */

<script setup>
import {reactive} from 'vue'
let people = reactive(
    {
        name: '',
        password: '',
        sex: '',
        hobby: [],
        introduce: ''
    }
)

function remove() {
    people.name = ''
    people.password = ''
    people.sex = ''
    people.hobby.splice(0, people.hobby.length)
    people.introduce = ''
}
</script>

<template>
    <div>
        账号<input type="text" v-model="people.name"> <br>
        密码<input type="password" v-model="people.password"> <br>
        性别:
            男<input type="radio" value="boy" name="sex" v-model="people.sex">
            女<input type="radio" value="gril" name="sex" v-model="people.sex">
            <br>
        爱好:
            唱<input type="checkbox" value="sing" name="hobby" v-model="people.hobby">
            跳<input type="checkbox" value="dance" name="hobby" v-model="people.hobby">
            rap<input type="checkbox" value="rap" name="hobby" v-model="people.hobby">
            <br>
        个人简介:
            <textarea v-model="people.introduce"></textarea> <br>
        <button @click="remove()">清空</button>
        <hr>
        {{ people }}
    </div>
</template>

<style scoped>

</style>

 9. 计算属性

/**

 * 计算属性:

 * computer函数

 */

<script setup>
import {reactive, computed} from 'vue'

let people = reactive({
    name: "张三",
    book: ["java", "mysql", "c++"]
})
function f() {
    return people.book.length > 0 ? "yes" : "no"
}

//数据未发生变化则不会重新计算区别于直接调用方法,方法每执行一次就会计算一次
let flag = computed(() => {return people.book.length > 0 ? "yes" : "no"})
</script>

<template>
    <div>
        <p>作者:{{ people.name }}</p>
        是否出版图书:{{ flag }} <br>
        是否出版图书:{{ f() }}
    </div>
    
</template>

<style scoped>

</style>

10. 数据监听器

/**

 * 数据监听器:watch、watchEffect函数

 */

<script setup>

import {reactive, watchEffect} from 'vue'

let people = reactive({
    username: "", 
    userpassword: ""
})
//要监听哪个事件直接监听即可
watchEffect(() => {
       console.log(people.username)
    }
)
</script>

<template>
    <div>
        账号:<input type="text" v-model="people.username"> <br>
        密码:<input type="password" v-model="people.userpassword"> <br>
        {{ people }}
    </div>
</template>

<style scoped>

</style>

 11. 导入其他组件

<script setup>
  import Header from './components/Header.vue';
  import Navigator from './components/Navigator.vue';
  import Control from './components/Control.vue';
</script>

 12. 组件传递参数

<script setup>
  import Header from './components/Header.vue';
  import Navigator from './components/Navigator.vue';
  import Control from './components/Control.vue';

  import {ref} from 'vue'

  //定义一个变量接收子组件传递的信息
  let message = ref('')
  //定义函数处理子组件传递的数据
  function receive(data) {
    message.value = data
  }
</script>

<template>
  <div>
    {{ message }}
    <hr>
    <Header class="header"></Header>
    <!--绑定的事件名必须和子组件中定义和传递的事件名保持一致-->
    <Navigator @sendMenu="receive" class="navigator"></Navigator>
    <!--父组件传递数据给子组件可直接在此处定义属性名和传递的数据-->
    <control class="control" :delieve="message"></control>
  </div>
</template>

<style scoped>
  .header {
    border: 2px solid red;
  }
  .navigator {
    border: 2px solid green;
    width: 15%;
    height: 300px;
    float: left;
  }
  .control {
    border: 2px solid blue;
    width: 83%;
    height: 300px;
    float: right;
  }
</style>

子传父

<script setup>
/**
 * 子组件传递数据给父组件
 * 用函数defineEmits
 */
import {defineEmits, ref} from 'vue'

//通过defineEmits函数获取传递参数的对象
const emit = defineEmits(['sendMenu'])

//定义要传递给父组件的数据
let data = ref('')

function send(data) {
    //参数一:组件定义的事件名,接收数据的组件可通过该事件名进行绑定操作
    //参数二:当前组件传递的数据
    emit('sendMenu', data)
}
</script>

<template>
    <div>
        <ul>
            <!--send函数的参数即组件要传递的内容-->
            <li @click="send('探花管理')">探花管理</li>
            <li @click="send('学员管理')">学员管理</li>
            <li @click="send('教员管理')">教员管理</li>
            <li @click="send('系统管理')">系统管理</li>
            <li @click="send('请假管理')">请假管理</li>
        </ul>
    </div>
</template>

<style scoped>

</style>

 父传子

<script setup>
/**
 * 父组件传递数据给子组件
 * 用函数defineProps
 */
import {defineProps} from 'vue'

defineProps({
  //子组件接收父组件传递信息时属性名必须和定义的保持一致:后面的数据类型和传递的数据类型必须保持一致
  delieve:String
})
</script>

<template>
  <div>
    <!--直接使用父组件传递的数据-->
    {{delieve}}
  </div>
</template>

<style scoped>

</style>