4

万字血书Vue—Vue语法 - 辜负寒彻骨

 1 year ago
source link: https://www.cnblogs.com/gfhcg/p/17222239.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

模板语法#

插值语法#

Mustache插值采用{{ }},用于解析标签体内容,将Vue实例中的数据插入DOM中

 <h1>Hello {{name}}</h1>

指令语法#

指令用于解析标签,是vue为开发者提供的一套模板语法辅助开发者渲染页面的基本结构

(指令是vue开发中最基础、最常用、最简单的知识点)(支持绑定简单的数据值之外,还支持js表达式运算)

内容渲染指令

1、v-text=" " 会覆盖元素内默认的值、无法写HTML标签语句

2、{{ }} 插值表达式(Mustache) 不会覆盖元素中默认的内容

3、v-html 可以渲染包含HTML标签的字符串

v-html有安全性问题,在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击;永远不要再用户提交的内容上使用v-html

属性绑定指令

v-bind: 为元素的属性动态绑定属性值

属性:placeholder、src等

简写::

<a v-bind:href="url">点击跳转</a>
<a :href="url">点击跳转</a>
事件绑定指令

v-on: 为DOM元素绑定事件监听

v-on:click=” “、v-on:input、v-on:keyup

事件处理函数,需要在methods节点中进行声明

简写:@、如果事件处理函数的代码足够简单,只有一行代码,则可以简写到行内

事件对象event
<body>
    <div id="app">{{username}}</div>
    <button @click="addcount($event,88)">
        点击我
    </button>

    <script src="vue.js"></script>
    <script>
        const vm=new Vue({
            el:'#app',
            data:{
                username:'zs',
                count:0
            },
            methods:{
                addcount(e,88){
                    const nowBgColor =e.target.style.backgroundColor
                    console.log(nowB gColor)
                    this.count+=1
                }
            }
        })
    </script>
</body>

绑定事件并传参,使用() 小括号,但会占用event的位置

$event是vue提供的特殊变量用于占位,用来表示原生事件参数对象event,使用e接受

事件修饰符

vue提供事件修饰符,来辅助程序员更方便的对事件的触发进行控制

  • .stop阻止事件冒泡()里到外

  • .prevent 阻止默认行为()比如阻止跳转

  • .capture以捕获模式触发当前事件处理函数(外到里)

  • .self只有在event.target是当前元素自身时触发事件处理函数

  • .once绑定的事件只触发一次

  • .passive事件的默认行为立即执行,无需等待事件回调执行完毕

按键修饰符

监听键盘事件时,我们经常需要判断详细的按键,此时可为键盘相关的事件添加按键修饰符

  • .enter、.delete、.esc、.space、.tab(特殊:只适用于keydown)、.up、.down、.left、.right
  • 系统修饰符(用法特殊):ctrl、alt、shift、mta 配合keyup使用:按下按键的同时需要再按下其他键,随后事件才被触发;keydown正常触发事件
  • 也可以使用keyCode去指定具体的按键(不推荐)
  • Vue.config.keyCodes.自定义键名=键码 可以去定制按键别名
双向绑定指令

v-model 在不操作DOM的情况下,快速获取表单数据(只能配合表单元素一起使用)

<input type="text" v-model:value="username"/>
<input type="text" v-model="username"/>
v-model 指令的修饰符

方便用户对输入的内容进行处理

  • .number自动将用户输入值转化为数值
  • .trim 自动过滤用户输入的首尾空白字符
  • .lazy 在change时更新而非input时更新(不实时更新,文本框失去焦点更新)
条件渲染指令

按需控制DOM的显示和隐藏

v-if =" " 动态创建或移除DOM元素,有更高的切换开销(重绘和回流)

v-else-if =" "v-else =" "

v-show=" " 动态为元素添加或移除display样式,有更高的初始渲染开销。

列表渲染指令

v-for=" " 辅助开发者基于一个数组来循环渲染相似的UI结构

特殊语法:item in items

<body>
   
    <div id="root">
        <!-- 遍历数组 -->
        <ul>
            <li v-for="item in persons" :key="item.id">
                {{item.id}}-{{item.name}}-{{item.age}}
            </li>
        </ul>
        <!-- 遍历对象 -->
        <ul>
            <li v-for="(value,key) of cars" :key="key">
                {{key}}-{{value}}
            </li>
        </ul>
        <!-- 遍历字符串 -->
        <ul>
            <li v-for="(char,index) of str" :key="index">
                {{index}}-{{char}}
            </li>
        </ul>
        <!-- 遍历指定次数 -->
        <ul>
            <li v-for="(number,index) of 5" :key="index">
                {{index}}-{{number}}
            </li>
        </ul>

    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        const vm=new Vue({
            el:'#root',
            data:{
                persons:[
                    {id:'001',name:'张三',age:18},
                    {id:'002',name:'李四',age:17},
                    {id:'003',name:'王五',age:42},
                ],
                cars:{
                    name:'Audi',
                    price:"70W",
                    color:"black"
                },
                str:"hello"

            }
        })
   
    </script>
    
</body>
for in和for of

for in一般遍历对象,不建议遍历数组。遍历数组请使用for of或forEach。

v-for中的索引

(item,index) in items

注:v-for中的item项和index索引都是形参,任意命名

key作用和原理

当列表的数据变化(添加、删除)时,vue会尽可能复用已存在的DOM元素,从而提升渲染的性能,但这种性能优化策略会导致有状态的列表无法被正确更新,key的使用将减少不必要的DOM操作,提高更新效率。

Vue根据初始数据生成初始虚拟DOM(Vnodes),将虚拟DOM转为真实DOM,用户添加新的数据,产生新虚拟DOM(Vnodes),此时将两份虚拟DOM根据key进行对比(diff 算法),如果对比一样的直接复用,将之前的真实DOM直接渲染;不一样的无法复用,将其生成真实DOM。

  • 如果使用index作为key,diff对比时会完全错位,所有节点都无法复用,效率降低。
  • 如果不指定key时,vue自动使用遍历时的索引值index作为key。

为了给vue一个提示,以便它能跟踪每个节点的身份,需要为每项提供一个唯一的key属性

image

image
  • key只能是字符串或数字类型

  • key的值必须具有唯一性

  • 建议把数据项id属性的值作为key的值,将index的值作为key的值没有任何意义https://blog.csdn.net/z591102/article/details/106682298/)

  • 建议使用v-for时一定要指定key的值(提升性能,防止列表状态紊乱)

  • 但不存在对数据的操作,仅是渲染列表用于展示,使用index作为key没有问题

image
其他内置指令

v-cloak没有值,配合CSS,解决网速慢、服务器响应慢时未经解析的模板渲染到页面上,Vue实例创建并接管容器后,会删掉该属性。

[v-cloak]:{
    display:none;
}

v-once没有值,记录初始值,在初次动态渲染后,就视为静态内容,以后数据的改变不会引起v-once所在结构的更新,可以用于性能优化。

v-pre没有值,跳过其所在节点的编译过程,可以用它跳过:没有使用指令语法、插值语法的节点,会加快编译。

自定义指令

本质:将原生操作DOM进行二次封装。

<body>
   
    <div id="root">
        <!-- v-big放大10倍 -->
        <h2>当前的n值是:<span v-text="n"></span></h2>
        <h2>放大10倍后的n值是:<span v-big="n"></span></h2>
        <button @click="n++">点位n++</button>
        <hr>
        <!-- v-fbind在v-bind基础上,自动获得焦点 -->
        <input type="text" v-fbind:value="n">
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        const vm=new Vue({
            el:'#root',
            data:{
               n:0,
            },
            directives:{
                //函数式
                //何时会被调用:1、指令和元素成功绑定;2、指令所在的模板被重新解析时
                big(element,binding){
                    element.innerText=binding.value*10
                },
                //错误写法:
                fbind(element,binding){
                    element.value=binding.value
                    element.focus()//.focus()调用时机不对,此时input还未被插入页面
                },
                //对象式
                fbind:{
                    //指令与元素成功绑定时调用
                    bind(element,binding){
                        element.value=binding.value
                    },
                    //指令所在元素被插入页面时调用
                    inserted(element,binding){
                        element.focus()
                    },
                    //指令所在模板被重新解析时调用
                    update (element,binding) {
                        element.value=binding.value
                    },
                }

            },
        })
   
    </script>
</body>
  • 命名多个单词使用-分隔;
  • 指令中this的指向是window
  • 自定义指令默认都是局部指令,全局写法:Vue.directive

计算属性#

计算属性本质上就是一个function函数,它可以实时监听data中数据的变化,并return一个计算后的新值,供组件渲染DOM时使用。

开发者需要以function函数的形式声明到组件的computed节点

<template>
  <div>
    <input type="text" name="" id="" v-model.number="count">

    <p>{{count}} 乘以2的值为:{{plus}}</p>//必须当做普通属性使用
  </div>
</template>

<script>
export default {
    name:'MyCount',
    data(){
        return{
            count:1,
        }
    },
    //必须定义在computed节点
    computed:{
        //必须是一个function函数
        plus(){
            //必须具有返回值
            return this.count*2
        }
        
        //相当于
        
        plus:{
        //当读取plus,get会被调用,且返回值作为plus的值
        //get何时被调用?1、初次调用plus;2、所依赖的数据发生变化
        get(){
            return this.count*2
        }
      }
    }

}
</script>

侧重于得到一个计算的结果,必须有return返回值

计算属性(computed)vs方法(methods):

相对于方法,计算属性会缓存计算结果,只有计算属性的依赖项发生变化时,才会重新进行运算,因此计算属性的性能会更好。

watch侦听器#

watch侦听器允许开发者监视数据的变化,从而针对数据的变化做特定的操作

开发者需要在watch节点之下,定义自己的侦听器

<script>
export default {
    name:'MyCount',
    data(){
        return{
            username:'',
        }
    },
   watch:{
       //当username发生改变时,调用 handler
       username:{
           handler(newVal,oldVal){
             console.log(newVal,oldVal) 
           }  
       }
      //简写
       username(newVal,oldVal){
           console.log(newVal,oldVal)     
       }       
   }
  
   }
</script>
<body>
    <div id="app">{{username}}</div>
    #导入脚本文件
    <script src="vue.js"></script>
    <script>
        const vm=new Vue({
            data(){
            return{
                   username:'zs'
            }
            }
        })
        vm.$mount=('#app')//挂载
        vm.$wtach('username',{ //第二种写法
            handler(newVal,oldVal){
                console.log(newVal,oldVal)
            }
        })
        //简写
        vm.$wtach('username',function(newVal,oldVal){
            console.log(newVal,oldVal)            
        }
        })        
       
    </script>
</body>

应用场景#

使用watch检测用户名是否可用,监听username值得变化,并使用axios发起ajax请求,检测当前输入的用户名是否可用

<script>

import axios from 'axios'

export default {
    name:'MyCount',
    data(){
        return{
            username:'',
        }
    },
 watch:{
    async username(newVal,oldVal){
        console.log(newVal,oldVal)
        const {data:res}=await axios.get('https://www.escook.cn/api/finduser'+newVal)
        //await简化promise实例对象为数据
        console.log(res)
    }
 }

}
</script>
immediate选项

默认组件在初次加载完毕后不会调用watch侦听器,如果想让watch侦听器立即被调用,则需要使用immediate选项

<script>

import axios from 'axios'

export default {
    name:'MyCount',
    data(){
        return{
            username:'',
        }
    },
 watch:{
//不能直接定义成方法,要让监听的数据指向一个配置对象
  username:{
    async handler(newVal,oldVal){
     const {data:res}=await axios.get('https://www.escook.cn/api/finduser'+newVal)
        //await简化promise实例对象为数据
        console.log(res)
},
      //立即触发watch侦听器
      immediate:true,
      
 }
 }

}
</script>
deep选项

当watch侦听的是一个对象,如果对象中的属性值发生了变化,则无法被监听到,需要使用deep选项侦听所有属性的变化。

<script>

import axios from 'axios'

export default {
    name:'MyCount',
    data(){
        return{
            username:'',
        }
    },
 watch:{
//不能直接定义成方法,要让监听的数据指向一个配置对象
  username:{
    async handler(newVal,oldVal){
     const {data:res}=await axios.get('https://www.escook.cn/api/finduser'+newVal)
        //await简化promise实例对象为数据
        console.log(res)
},
      deep:true,//监视多级结构(对象)中所有属性的变化
 }
 }

}
</script>

监视多级结构(对象)中单个属性的变化#

<script>

import axios from 'axios'

export default {
    name:'MyCount',
    data(){
        return{
            info:{username:'zs',password:'123456'}
            
        }
    },
 watch:{
//不能直接定义成方法,要让监听的数据指向一个配置对象
  'info.username':{//只想监听info.username的属性变化
    async handler(newVal,oldVal){
     const {data:res}=await axios.get('https://www.escook.cn/api/finduser'+newVal)
        //await简化promise实例对象为数据
        console.log(res)
},
   
      deep:true,
 }
 }

}
</script>

计算属性vs侦听器#

  • computed能完成的功能,watch都可以完成,都能完成的,优先使用computed。
  • watch可以完成的,computed不一定能完成,例如watch可以处理异步任务
  • 计算属性和侦听器侧重的应用场景不同。
  1. 前者侧重监听多个值的变化,最终计算返回一个新值

  2. 后者侧重于单个数据的变化,最终执行特定的业务处理,不需要任何返回值

两个原则:

  • Vue所管理的函数,最好写成普通函数,这样this的指向才是vm或组件实例对象,否则指向window。
  • 所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数、Promise的回调函数),最好写成箭头函数,这样this的指向才是vm或组件实例对象,否则指向window。

绑定样式#

绑定class样式#

<!--字符串写法,适用于样式的类名不确定,需要动态指定-->
<h1 class="basic" :class:"className">Hello World!</h1>
<!--数组写法,适用于样式的个数和类名都不确定-->
<h1 class="basic" :class:"classArr">Hello World!</h1>
<!--对象写法,适用于样式的个数和类名都确定,但要动态觉得用不用-->
<h1 class="basic" :class:"classObj">Hello World!</h1>

绑定style样式#

<!--动态指定-->
<h1 class="basic" :style="{fontSize: fsize+'px';}">Hello World!</h1>
<h1 class="basic" :style="styleObj">Hello World!</h1>
<h1 class="basic" :style="[styleObj1,styleObj2]">Hello World!</h1>

过滤器#

(Vue3.x废弃,用计算属性、方法代替)

什么是过滤器?#

过滤器(Filters)常用于文本的格式化,本质是一个函数

过滤器应该被添加到js表达式的尾部,由“管道符”进行调用

  • 用于插值表达式
  • 用于v-bind属性绑定

定义(局部)过滤器#

在创建vue实例期间,可以在filters节点中定义过 滤器

私有和全局过滤器#

私有过滤器:只能在被vm实例控制的区域下控制

如果想在多个vue实例之间共享过滤器,则可以按照如下格式声明全局过滤器:

 <script>
        vue.filter('capitalize',(str)=>{
            return str.charAt(0).toUpperCase() + str.slice(1)+'--'
        })
        new Vue...
</script>

注:如果二者冲突以私有过滤器为准,就近原则

连续调用多个过滤器#

过滤器可以串联的地调用

{{message | capitalize | maxlength}

过滤器传参#

过滤器本质是js函数,第一个参数永远是管道符前面的值,第二个参数开始才是arg1、arg2...

{{message | filterA(agr1,arg2)}
 
vue.filter('filterA',(msg,arg1,aarg2)=>{})

过滤器的兼容性#

在vue3.x版本中已经剔除了过滤器相关功能,可以使用计算方法或属性来代替


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK