Vue基础

67 阅读3分钟

介绍

渐进式框架:我们可以用最简单的方式导入vue.js,使用vue,随着项目变大,可以集成周边插件使用逐步集成

vue的接入

  1. 先下载vue.js
  2. 在html 文件中导入 vue.js
  3. 创建一个vue实例
  4. 将 vue实例和页面模板进行绑定,让其产生联系
  • createApp:用来创建一个 vue实例用的
  • mount: 将实例挂载到 id 是app 的元素上

模板语法

双大括号语法是 js表达式,可以取到 data 中的数据

  • 指令
  1. v-text 渲染普通文本,不会解析标签
  2. v-html 渲染标签文本,可以解析标签
  3. v-bind 用来绑定属性用的(简写是冒号:)
  4. v-on 用来绑定事件 用的(简写是艾特符号@)
  5. v-if 用来进行条件判断,条件成立就添加,否则移除
  6. v-for用来做循环的
  7. :[attr]="url"动态属性,可以将attr进行修改,是的 v-bind 绑定不同的属性
<div id="app">
        <p>{{ msg }}</p>

        <div>
            {{ message }}
        </div>
        <!-- v-text 不做解析直接渲染 -->
        <div v-text="message"></div>

        <!-- v-html 该指令是用来解析标签和样式用的 -->
        <!-- 在 vue 中使用 v- 开头的属性叫做指令 -->
        <div v-html="message"></div>

        <!-- v-bind: 是用来给标签绑定属性用的 -->
        <p v-bind:id="myid" v-bind:title="title">具有 id 的 p 标签</p>

        <!-- : 冒号是 v-bind 的简写 -->
        <p :class="myclass">具有 class 属性的 p 标签</p>

        <!-- v-on 是用来监听事件用的 -->
        <button v-on:click="count++"> 点击增加 {{count}} </button>
        <!-- @ 是 v-on 的简写 -->
        <button @click="count++"> 点击增加 {{count}} </button>

        <!-- v-if 当条件成立时会显示该标签 -->
        <div v-if="flag">flag 为真</div>
        <!-- <span></span> -->
        <!-- v-else/v-else-if 中间不能有其他标签 -->
        <div v-else-if="flag == '111111'">flag 为111111</div>
        <div v-else>flag 为假</div>
        <button @click="flag = !flag">切换 flag</button>

        <ul>
            <!-- v-for 用来做循环用的 -->
            <li v-for="item in list"> {{ item }} </li>
        </ul>
        <button @click="addItem">点击在 list 中添加内容</button>

        <a :[attr]="url">求点击</a>

        <!-- 
            js 表达式
            {{}} 双大括号中的内容为 js 表达式
            通过 v-bind:class=''  此时引号内的内容是 js 表达式
         -->
    </div>
    <script>

    const app = Vue.createApp({
        // data 选项中放的是 数据  状态
        data () {
            return {
                msg: '成大事者不拘小节,但是首先,你得能成大事',
                message: '<h1 style="color: red">成大事者不拘小节</h1>',
                myid: 'bpp',
                title: '你好世界',
                myclass: 'box',
                count: 100,
                flag: false,
                list: [
                    '摇一摇',
                    '晃一晃',
                    '扭一扭',
                    '舔一舔',
                    '泡一泡'
                ],
                url: 'https://www.jd.com',
                attr: 'href'
            }
        },
        // methods 选项是用来放函数的地方
        methods: {
            addItem () {
                // alert('被点击了')
                console.log(this.list);
                this.list.push('奥利奥')
            }
        },
    })

    const vm = app.mount('#app')


</script>

vue响应式

数据发生改变后不会立即改变页面,先修改虚拟DOM 中的值,然后由虚拟的DOM修改真实的DOM

  1. 虚拟DOM 其实是一个队形
  2. vue 数据发生改变后不会立即更新到真实 DOM中,而是先更新虚拟的DOM
  3. 当虚拟DOM改变后会通过 DIFF算法将改变后的值更新到真实DOM中
  4. DIFF:会比较新老 DOM找到有改变的地方,只更新有变化的地方,提高性能
  5. nextTick 会在真实DOM更新之后调用
const app = {
        data(){
            return {
                count:100
            }
        },
        methods:{
            
        add(){
            this.count++
            Vue.nextTick(()=>{
            console.log(document.querySelector('h1').innerText);
        })
        // setTimeout(()=>{
        //     console.log(document.querySelector('h1').innerText);
        // },100)
        },
        },
       

        
    }
    const vm =Vue.createApp(app).mount('#app')

data要是一个函数,就要返回一个对象

  1. 因为要保证每个组件都有自己独立的数据,具备独立的作用域
  2. 写在data 中的数据是具备响应式的 ,通过proxy 实现
<div id="app">
        <h1>{{count}}</h1>
        <button @click="add">app 求点击</button>
    </div>

    <div id="bpp">
        <h1>{{count}}</h1>
        <button @click="add">bpp 求点击</button>
    </div>
    
    const data = {
        count: 101
    }

    const app = {
        // 每个组件中都要有自己的独立数据
        // 所以 data 要是函数要 return 一个新的对象
        data () {
            return {
                count: 101,
                myObj: {}
            }
        },
        methods: {
            add () {
                this.count++
            }
        },
    }

    const vm = Vue.createApp(app).mount('#app')

    const newObj = {}
    console.log('11111', vm.myObj == newObj);
    console.log('vm.myObj', vm.myObj); // 是一个 vm.myObj Proxy {} 被代理了
    console.log('newObj', newObj); // 是一个普通对象  没有被代理不具备响应式

    const bpp = {
        data () {
            return {
                count: 101
            }
        },
        methods: {
            add () {
            }
        },
    }

    const vm2 = Vue.createApp(bpp).mount('#bpp')

计算属性

计算属性的特点:

  1. 计算属性有缓存
  2. 计算属性一上来就会立即执行一次
  3. 如果计算属性中使用到多个属性,那么这些属性全部都会被监听到,只要有一个发生改变那么该函数就会被执行
  4. 计算属性中一定要有一个return ,因为要有一个计算的结果
  5. 计算属性是多个值影响一个值
 <div id="app">
        <p> num 的值是: {{ num }} </p>
        <p> 当前 num 是: {{ msg }} </p>
        <p> 计算属性中的值 {{message}}</p>
        <button @click="change"> 改变 num 值 </button>
    </div>
    <script>
    const app = Vue.createApp({
        data () {
            return {
                num: 0,
                msg: '偶数',
                name: '高举'
            }
        },
        // 计算属性选项,所有的计算属性都会放在这里
        computed: {
            message () {
                /*
                    当 this.num 的值发生改变时才会执行 message 函数进行计算
                    如果当前值和上一次的值相同,该方法一定是不会被执行的
                    也就相当于 this.num 被监听了,只有改变才会被触发
                    计算属性的特点:
                    1. 计算属性有缓存
                    2. 计算属性一上来就会立即执行一次
                    3. 如果计算属性中有使用到多个属性,那么这些属性全部都会被监听到
                    只要有一个发生改变那么该函数就会被执行
                    4. 计算属性中一定要有一个 return,因为要有一个计算的结果
                    5. 计算属性是多个值影响一个值
                */

                // 只要是被写在计算属性内的变量,都会被监听到
                console.log(this.name);
                console.log('计算属性被调用了');
                return this.num ? '奇数' : '偶数'
            }
        },
        methods: {
            change () {
                // console.log(Math.floor(Math.random() * 2));
                this.num = Math.floor(Math.random() * 2)
                // 调用方法来获取是奇数还是偶数
                this.showMsg()
            },
            showMsg () {
                // 用来判断是奇数还是偶数
                this.msg = this.num ? '奇数' : '偶数'

                console.log('函数被调用了');
            }
        },
    })

    const vm = app.mount('#app')

</script>

可写的计算属性

  • 可以将计算属性定义为一个对象
  • 该对象中可以设置一个set 和 一个 get 方法
  • get 是用户计算结果用的
  • set 是用来修改计算属性的
<div id="app">
        {{ birthYear }} -- {{ age }}
        <button @click="change"> 修改出生年份 </button>
        <button @click="setAge"> 修改年龄 </button>

    </div>
    <script>
    Vue.createApp({
        data () {
            return {
                birthYear: 2000
            }
        },
        computed: {
            // age () {
            //     return new Date().getFullYear() - this.birthYear
            // }
            // 如果需要可以设置的计算属性,可以将 age 写为对象
            // 该对象中定义两个方法一个 get 用来获取值,一个 set 用来修改值
            age: {
                get () {
                    return new Date().getFullYear() - this.birthYear
                },
                // set 方法中一定要有一个参数,该参数就是我们要设置的值
                set (value) {
                    console.log(value);
                    // 根据年龄计算出,出生年份,此时年份发生改变,年龄自然就会改了
                    this.birthYear = new Date().getFullYear() - value
                }
            }
        },
        methods: {
            change () {
                // 设置出生的年份时,年龄会改变
                this.birthYear = 1999
            },
            setAge () {
                console.log(this.age);
                // 设置年龄的时候,发现失败,警告说的是只读
                // this.age = 30

                this.age = 30
            }
        },
    }).mount('#app')
</script>

侦听器

  1. 一上来不会立即执行一次(具有惰性)
  2. 侦听器无需返回值
  3. 支持异步的
  4. 没有缓存
  5. 侦听器一次只能监听一个值,一个值影响多个值
  <div id="app">
        <h3> 原价: {{ price }} </h3>
        <!-- 通过计算属性进行打折 -->
        <h3> 计算属性价格: {{ changePrice }} </h3>
        <h3> VIP 价格:{{ VIPPrice }} </h3>
        <h3> SVIP 价格:{{ SVIPPrice }} </h3>

        <button @click="btnClick">修改 price</button>
    </div>
    <script>
    Vue.createApp({
        data () {
            return {
                price: 100,
                VIPPrice: 0,
                SVIPPrice: 0
            }
        },
        computed: {
            changePrice () {
                // setTimeout(() => {
                return this.price * 0.95
                // }, 1000)
            }
        },
        watch: {
            // 侦听器的名字就是我们要监听属性的名字
            // price 为我们要监听的属性
            // price (current, price) {
            //     // current 是修改后的值
            //     // price 原来值
            //     console.log(current, price);


            //     setTimeout(() => {
            //         this.VIPPrice = current * 0.8

            //         this.SVIPPrice = current * 0.5
            //     }, 1000)

            // }

            price: {
                // 侦听器发送变化时,立即执行的函数
                handler (current, price) {
                    this.VIPPrice = current * 0.8
                    this.SVIPPrice = current * 0.5
                },
                // 强制执行,立即执行,配置为非惰性
                immediate: true,
                // 如果需要监听对象,那么需要配置深度监听
                // 谨慎使用:深度监听需要变量被监听的对象中所有嵌套的属性,当用于大型
                // 数据解构时,开销会特别的大,因此请在必要的时候再来使用
                deep: true,
                // 该配置指明 侦听器中获取更新之后的 DOM 同  nextTick 功能一致
                flush: 'post'
            }
        },
        methods: {
            btnClick () {
                this.price = 1000
            }
        },
    }).mount('#app')

    /*
        计算属性:
        1. 运行就会立即执行一次 (非 惰性)
        2. 计算属性中需要一个返回值
        3. 计算属性不支持异步
        4. 计算属性是有缓存
        5. 计算属性能监听多个值,多个值影响一个值

        侦听器: 
        1. 一上来不会立即执行一次(具有惰性)
        2. 侦听器无需返回值
        3. 支持异步的
        4. 没有缓存
        5. 侦听器一次只能监听一个值,一个值影响多个值

    */

</script>