vue基础学习

Vue

创建一个简单的vue

<!--准备容器-->
<div id="app">
    <!--插值语法 {{xxx}}-->
    <h1>hello {{name}}</h1>
</div>

<script src="js/vue2.7.15.js"></script> //引入vue
<script type="text/javascript">
    //1.创建vue实例
    const vm = new Vue({
        el:'#app', //绑定容器
        data:{
            //存储数据,数据在容器中使用
            name:'猿究院'
        }
    });
</script>

模板语法

<!--插值语法 {{xxx}}-->
<h1>hello {{name}}</h1>
<!-- 指令语法 v-text 操作文本-->
<h2 v-text="name"></h2>
<!-- 指令语法 v-bind 属性定义-->
<a v-bind:href="url">点我跳转</a>
<!--简写形式 :xxx == v-bind:xxx -->
<input :value="name" />

vue中el和data的两种写法

/**
 * el写法
 * 1.vm的el属性 >>>  el:'#app', //绑定容器
 * 2.vm的$mount方法 >>> vm.$mount('#app')
 */
/**
 * data写法
 * 1.data对象 data:{xxx:{}}
 * 2.data函数 返回值是对象 data(){return {}}
 * data函数可以避免数据的同步,造成一处修改,全部改变
 */
 
<script src="js/vue.js"></script>
<script type="text/javascript">
    //1.创建vue实例
    const vm = new Vue({
        // el:'#app', //绑定容器
        data(){
            //存储数据,数据在容器中使用
            return{
                name:'猿究院',
                url:'http://www.apesource.com'
            }
        }
    });
    vm.$mount('#app') //第二种el写法
</script>

数据绑定

两种方式
 单项数据绑定:<input type="text" :value="name"/> <br>
 双项数据绑定:<input type="text" v-model:value="name"/>
Object.defineProperty
定义:

Object.defineProperty()方法会直接在一个对象上定义一个新的属性 或者 修改一个对象的现有属性,并返回此对象

参数

Object.defineProperty(obj,prop,descriptor) 有三个参数

  1. obj 要定义的属性的对象
  2. prop 要定义或者修改的属性名称
  3. descriptor 要定义或者修改的属性的描述(内容)
控制属性
  • enumerable:true, //控制属性是否可以遍历 默认 false
  • writable:true, //控制属性是否可以被修改 默认false
  • configurable:true //控制属性是否可以删除 默认false
返回值

返回 传递函数的对象

<script type="text/javascript">
    let person ={
        name:'张三',
        sex:'男'
    }
    // Object.defineProperty(person,'age',{
    //     value:25,
    //     enumerable:true, //控制属性是否可以遍历 默认 false
    //     writable:true, //控制属性是否可以被修改 默认false
    //     configurable:true //控制属性是否可以删除 默认false
    // });
    Object.defineProperty(person,'age',{
        // 当有人读取person 的 age属性时
        //get函数就会被触发,并且返回值
        get(){
            return this.age;
        },
        // 当有人写入person 的 age属性时
        //set函数就会被触发,并且传入参数,修改属性
        set(value){
            console.log('修改内容')
            return this.age = value;
        }
    })
    console.log(person.age)

</script>
模拟vue的双向绑定
<input type="text" id="ipt">
<div id="contain"></div>
<script>
    let oIn = document.getElementById("ipt");
    let oDiv = document.getElementById("contain");
    let text;
    window.data={};
    // 添加监听器,通过监听器来获取数据的改变
    oIn.addEventListener('input',function (e) {
        //获取当前input的value属性
        window.data.value = e.target.value;
    })
    //通过Object.defineProperty()方法来实现数据绑定
    Object.defineProperty(window.data,'value',{
        get(){
            return this.value;
        },
        set(value){
            oDiv.innerHTML = value;
        }
    })
</script>

事件

v-on:xxx ( 简写形式:@xxx ) 事件指令语法

<div id="root">  

    <button v-on:click="showInfo">点击试试</button><br>
    <button @click="showInfo">点击试试</button>
</div>
<script src="js/vue.js"></script>
<script type="text/javascript">
    const vm = new Vue({
    	data(){},
        methods:{
            showInfo(){
                console.log("执行方法")
            }
        }
    });
    vm.$mount('#root');
</script>
事件修饰符
<div id="root">
    <!--@click.prevent 取消默认行为-->
    <a @click.prevent="showInfo" :href="url">点我试试</a>
    <div class="demo1"  @click="showInfo" >
        <!--@click.stop 阻止冒泡-->
        <button @click.stop="showInfo">按钮</button>
    </div>
    <!--只执行一次-->
    <button @click.once="showInfo">按钮!!</button>

    <!--反转冒泡顺序-->
    <div class="box1" @click.capture="showMsg('A')">
        div1
        <div class="box2" @click="showMsg('B')">div2</div>
    </div>
	 <!--wheel.passive 事件的默认行为立即执行,无序等待事件的回调-->
    <ul class="list" @wheel.passive="demo">
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>
</div>
<script src="js/vue.js"></script>
<script type="text/javascript">
    const vm = new Vue({
        data() {
            return {
                url:'http://www.apesource.com'
            };
        },
        methods:{
            showInfo(){
                console.log("执行方法")
            },
            showMsg(num){
                console.log(num)
            },
            demo(){
                for (let i = 0; i < 1000; i++) {
                    console.log("执行完毕")
                }
                console.log("@_@")
            }
        }
    });
    vm.$mount('#root');
</script>
键盘事件

.enter (13 不建议使用) 回车时触发

.esc 退出

.delete 删除 1.backapace 2.delete

.space 空格

<div id="root">
    <input type="text" @keydown="demo" v-model:value="name"/>
    <input type="text" @keydown.enter="demo" v-model:value="name"/>
    <input type="text" @keydown.delete="demo" v-model:value="name"/>
</div>
<script src="js/vue.js"></script>
<script type="text/javascript">
    const vm = new Vue({
        data() {
            return {
                name:'apesource'
            };
        },
        methods:{
            demo(event){
                console.log(event.key,this.name)
                // console.log("+++",event.keyCode)
            }
        }
    });
    vm.$mount('#root');
</script>
计算属性

1.有缓存,可以二次复用

2.当参与计算的属性发生改变时,会再次执行

3.当需要一个属性但不存在时,需要通过已有属性计算的新属性

<div id="root">
    姓:<input type="text" v-model:value="fName"/><br>
    名:<input type="text" v-model:value="lName"/>
    <hr>
    <h1>姓名{{fullName}}</h1>
    <h1>姓名{{fullName}}</h1>
    姓名:<input type="text" v-model:value="fullName"/>
</div>
<script src="js/vue.js"></script>
<script type="text/javascript">
    const vm = new Vue({
        data() {
            return {
                fName:'',
                lName:'',
            };
        },
        methods:{},
        computed:{
            // 1.简写计算属性 只能读
            // fullName(){
            //     return this.fName +"-"+ this.lName;
            // }
            fullName:{
                get(){
                   return  this.fName +"-"+ this.lName;
                },
                set(value){
                   let arr = value.split("-");
                   this.fName = arr[0];
                   this.lName = arr[1];
                }
            }
        }
    });
    vm.$mount('#root');
</script>

监听器

两种方式

1.在创建Vue实例时,通过watch属性实现

2.vm.$watch实现

  //1.watch:{}
        // watch:{
        //     // 'nums.a':{
        //     //     //初始化时监视属性
        //     //     immediate:true,
        //     //     handler(newValue,oldValue){
        //     //         console.log(newValue,oldValue)
        //     //     }
        //     // }
        //     nums:{
        //         //初始化时监视属性
        //         immediate:true,
        //         deep:true, //深度监视
        //         handler(newValue,oldValue){
        //             console.log(newValue,oldValue)
        //         }
        //     }
        // }
    });
    // 2.vm.$watch
    vm.$watch('nums',{
        immediate: true,
        deep: true,
        handler(newValue, oldValue) {
            console.log(newValue, oldValue)
        }
    });

样式绑定

class样式
  • :class=‘xxx’ xxx可以是字符串 数组 对象

    • 字符串 用于类名不确定
    • 对象 要绑定多个样式,个数不确定 名字不确定、
    • 数组 用于 绑定多个样式,个数确定,名字确定,但是不确定用不用
style 样式
  • :style=“{fontSize:xxx}” xxx是动态值
  • :style=“[a,b,c]” a b c对象
  • a == {fontSize:xxx,…}
<style>
    .basic {
        width: 400px;
        height: 100px;
        border: 1px solid black;
    }
    .demoA {
        border: 4px solid red;
        background-color: orange;
    }
    .demoB {
        border: 4px dashed pink;
        background-color: gray;
    }
    .demoC {
        background-color: skyblue;
    }
    .box1 {
        background-color: yellow;
    }
    .box2 {
        font-size: 30px;
        text-shadow: 2px 2px 10px red;
    }
    .box3 {
        border-radius: 20px;
    }

</style>
<body>
<div id="root">

    <div class="basic" :class="mood" @click="changeMood">
        {{name}}
    </div>
    <div class="basic" :class="classArr">
        {{name}}
    </div>
    <div class="basic" :class="classObj">
        {{name}}
    </div>
    <div class="basic" :style="styleArr">
        {{name}}
    </div>
    <div class="basic" :style="styleObj">
        {{name}}
    </div>


</div>
<script src="js/vue.js"></script>
<script type="text/javascript">
    
    const vm = new Vue({
        data() {
            return {
                name:'猿究院',
                mood:'demoC',
                classArr:[ 'box1','box2'],
                classObj:{
                    box1:true,
                    box2:false,
                    box3:true
                },
                styleObj:{
                    fontSize:'50px',
                    color:'red'
                },
                styleArr:[
                    {
                        fontSize:'50px',
                        color:'green'
                    },
                    {
                        backgroundColor:'red'
                    }],

            };
        },
        methods:{
            changeMood(){
                const arr = ['demoA','demoB','demoC']
                const index = Math.floor(Math.random()*3);
                this.mood = arr[index];
            }
        }
    });

    vm.$mount('#root');
</script>

页面渲染

条件渲染
  1. v-if 适合切换频率低的场景不展示DOM时会直接移除DOM元素
    注意: v-if v-else-if v-esle 使用时结构不能被打断
  2. v-show 适合切换频率高的场景不展示DOM元素时,DOM元素不被移除
    仅仅是使用样式隐藏了
<!-- v-if -->
<!-- v-show -->
<div id="root">
    <button @click="count++">count++</button>
    <h2>{{count}}</h2>
    <hr>
    <h2 v-show="count==5">{{count}}</h2>
    <hr>
    <h2 v-if="count == 1">{{count}}</h2>
    <h2 v-else-if="count == 2">{{count}}</h2>
    <h2 v-else>其他</h2>
列表渲染
  • v-for指令< li v-for=“(item,index) in xXX” :key=“yyy”>

  • key可以是index也可以是遍历元素的唯一标识

  • 可以遍历数组对象字符串指定次数

<!--遍历数组-->
<ul>
    <li v-for="(stu,index) in students" :key="stu.sNo">
        {{index}} - {{stu.name}} - {{stu.sNo}}
    </li>
</ul>

<!--遍历对象-->
<ul>
    <li v-for="(value,k) in person" :key="k">
        {{k}} - {{value}}
    </li>
</ul>

<!--遍历字符串-->
<ul>
    <li v-for="(char,index) in str" :key="index">
        {{index}} - {{char}}
    </li>
</ul>

<!--循环次数-->
<ul>
    <li v-for="(number,index) in 5">
        {{index}} - {{number}}

    </li>
</ul>
key的作用
  • 虚拟DOM中的key的作用,key是虚拟DOM中对象的标识
  • 当数据发生改变时,Vue会根据{新的数据}生成{新的虚拟DOM}
  • 随后Vue会进行新的虚拟DOM与旧的虚拟DOM的差异比较
<!--没有key 或设置key为index-->
<ul>
    <li v-for="(stu,index) in students" :key="index">
        {{stu.sNo}} - {{stu.name}}
        <input type="text"/>
    </li>
</ul>

<!--设置key-->
<ul>
    <li v-for="(stu,index) in students" :key="stu.sNo">
        {{stu.sNo}} - {{stu.name}}
        <input type="text"/>
    </li>
</ul>

<button @click="addStudent">添加毛笔</button>

总结

  1. 旧的虚拟DOM中找到了与新的虚拟DOM相同的key

    • 如果虚拟DOM中的内容没有发生改变,则直接使用旧的虚拟DOM
    • 如果虚拟DOM中的内容发生改变,则生成新的真实DOM,替换旧的真实DOM
  2. 旧日的虚拟DOM中未找到与新的虚拟DOM相同的key

    • 创建新的真实DOM,渲染到页面

用index作为key的问题?

  • 如果对数据进行逆序的操作(添加删除)等破坏顺序的操作,会产生没有必要的真实DOM更新
  • 如果包含有输入类型的DOM,会产生错误的DOM更新

列表排序、过滤

filterStudents(){
    arr =  this.students.filter(item =>{
    	return item.name.indexOf(this.keyWord) != -1;
    })

    if (this.sortType){
        arr.sort((s1,s2)=>{
        return this.sortType == 1 ? s1.age - s2.age :s2.age - s1.age
    })
    }

    return arr;
    }
列表案例
<div id="root">
    <h2>学生信息</h2>
    <button @click="student.age++">age+1</button>
    <button @click="addSex">新增性别</button>
    <button @click="addFristFriend">列表首位添加朋友</button>
    <button @click="updateFriendName">修改第一位朋友的姓名为老刘</button>
    <button @click="addHobby">添加一个爱好</button>
    <button @click="updateHobby">删除并修改第二个爱好</button>
    <button @click="filterHobbySmoke">过滤爱好中的抽烟</button>
    <hr>
    
    <h3>姓名:{{student.name}}</h3>
    <h3>年龄:{{student.age}}</h3>
    <h3 v-if="student.sex">性别:{{student.sex}}</h3>
    <h3>爱好:</h3>
    <ul>
        <li v-for="(h,index) in student.hobby" :key="index">
            {{h}}
        </li>
    </ul>
    <h3>朋友:</h3>
    <ol>
        <li v-for="(f,index) in student.friends" :key="index">
            {{f.name}} - {{f.age}}
        </li>
    </ol>

</div>
<script src="js/vue.js"></script>
<script type="text/javascript">
    const vm = new Vue({
        data() {
            return {
                student:{
                    name:'李四',
                    age:18,
                    hobby:['抽烟','喝酒','烫头'],
                    friends:[
                        {name:'张三',age: 20},
                        {name:'王五',age: 30}
                    ]
                }
            };
        },
        methods:{
            addSex(){
                this.$set(this.student,'sex','男');
            },
            addFristFriend(){
                this.student.friends.unshift({name: '赵六',age:63});
            },
            updateFriendName(){
               this.student.friends[0].name = '老刘';
            },
            addHobby(){
                this.student.hobby.push('骑马');
            },
            updateHobby(){
                this.student.hobby.splice(1,1,'美人');
            },
            filterHobbySmoke(){
                return  this.student.hobby = this.student.hobby.filter(item =>{
                    return item !='抽烟';
                })
            }
        }
    });

    vm.$mount('#root');

</script>

数据接收

页面
<form action="#" method="post" @submit.prevent="demo" >
    账号:<input v-model="userInfo.account" type="text" /> <br/><br/>
    密码:<input v-model.trim="userInfo.password" type="password" /> <br/><br/>
    年龄:<input v-model="userInfo.age" type="number" /> <br/><br/>

    性别:<label><input v-model="userInfo.sex" type="radio" name="sex" value="男" /> 男</label>
        <label><input v-model="userInfo.sex" type="radio" name="sex" value="女" /> 女</label><br/><br/>

    爱好:<label><input v-model="userInfo.hobby" type="checkbox" value="0" /> 吃 </label>
        <label><input v-model="userInfo.hobby" type="checkbox" value="1" /> 喝</label>
        <label><input v-model="userInfo.hobby" type="checkbox" value="2" /> 嫖</label>
        <label><input v-model="userInfo.hobby" type="checkbox" value="3" /> 赌</label>
    <br/><br/>
    城市:<select v-model="userInfo.city">
            <option value="">请选择</option>
            <option value="xian">西安</option>
            <option value="lanzhou">兰州</option>
            <option value="xining">西宁</option>
            <option value="lasa">拉萨</option>
            <option value="yinchuan">银川</option>
        </select> <br/><br/>
    其他信息:<textarea v-model.lazy="userInfo.other"></textarea> <br/><br/>
    <input v-model="userInfo.agree" type="checkbox" /><a>我已阅读xxxx</a> <br/>
    <button type="submit">提交</button>

</form>
接收参数
data() {
            return {
                userInfo:{
                    account:'',
                    password:'',
                    age: 18,
                    sex:'男',
                    hobby:[],
                    city:'xian',
                    other:'',
                    agree:''
                }
            };
        },
        methods:{
            demo(){
                console.log(JSON.stringify(this.userInfo))
                return ;
            }
        }

过滤器

<div id="root">
    <h2>当前时间戳:{{time}}</h2>
    <h2>转换后的时间:{{time | timeFormater()}}</h2>
    <h2>转换后的时间:{{time | timeFormater('YYYY-MM-DD HH:mm:ss')}}</h2>
    <h2>转换后的时间:{{time | timeFormater('YYYY-MM-DD HH:mm:ss') | strTime}}</h2>
</div>
<script src="js/vue.js"></script>
<script src="js/dayjs.min.js"></script>
<script type="text/javascript">
    
    //全局过滤器
    Vue.filter('strTime',function (value,str) {
        return value.slice(0,11)
    })
    const vm = new Vue({
        data() {
            return {
                time:1702370485000 //时间戳
            };
        },
        //局部过滤器
        filters:{            
            timeFormater(value,str = 'YYYY MM DD$HH:mm:ss'){
                return dayjs(value).format(str)
            }
        }
    });
    vm.$mount('#root');
</script>

指令

常见指令
/**
 * 指令
 * v-bind
 * v-model
 * v-for
 * v-if
 * v-else-if
 * v-else
 * v-show
 * v-text
 * v-html 不会使用
 * v-cloak 没有值
 * 本质是一个特殊的属性 Vue的实例
 * 创建完毕并接管容器后 会删除v-cloak属性
 *   **** 需要css的配置 解决网速慢时 页面展示{{}}的问题
 * v-once 所在的节点 初次被渲染后,就视为静态内容
 * v-pre 跳过所在的节点的编译过程
 */
 
 <style>
    [v-cloak]{
        display: none;
    }
</style>

<div id="root">
    <div v-text="name">这是文本内容</div>
    <div v-html="str"></div>
    <div v-cloak>{{name}}</div>
    <div v-once>{{name}}</div>
    <div v-pre>{{name}}</div>
</div>
自定义指令
<div id="root">
    <h2>h的值:<span v-text="num"></span></h2>
    <h3>放大h的值(*2):<span v-big="num"></span></h3>
    <button @click="num++">num++</button>
    <input type="text" v-fbind="num" />
</div>
<script src="js/vue.js"></script>
<script type="text/javascript">
    const vm = new Vue({
        data() {
            return {
                num:1
            };
        },
        methods:{},
        //1.创建实例时,添加directives对象
        directives:{
            //自定义指令
            big(element,binding){
                // console.log(element,binding);
                element.innerText = binding.value*2;
            },
            fbind:{
                bind(element,binding){
                    console.log("bind")
                    element.value = binding.value *2;
                },
                inserted(element,binding){
                    console.log("inserted")
                    element.focus()

                },
                update(element,binding){
                    console.log("update")
                    element.value = binding.value *2;
                }
            }
        }
    });
    //2. Vue.directive(指令名,function)
    Vue.directive('fbind',{
        //指令与元素成功绑定时执行(一进来)
        bind(element,binding){
            console.log("bind")
            element.value = binding.value *2;
        },
        //指令所在的元素被载入页面时执行
        inserted(element,binding){
            console.log("inserted")
            element.focus()

        },
        //指令所在的模板被解析时
        update(element,binding){
            console.log("update")
            element.value = binding.value *2;
        }
    })
    vm.$mount('#root');
</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值