vue2 语法快速入门
前言
vue2时代即将结束,vue3是不可阻挡的,学习新技术永不终止 !!!
对vue2语法有所了解vue3直接可以开发
vue2是双向数据绑定,当数据发生改变影响视图,视图操作也会影响数据变化,是相互的。
1、vue2创建
vue create my-project
选择vue2进行安装,根据提示启动项目
package.json
了解下相关属性配置
在底层的实现上,Vue 将模板编译成虚拟 DOM 渲染函数。结合响应系统,Vue 能够智能地计算出最少需要重新渲染多少组件,并把 DOM 操作次数减到最少。
虚拟DOM-渲染函数
双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用 v-html 指令:
<p>Using mustaches: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>
XSS(跨站脚本攻击) v-html防范录入不可信内容
v- 前缀的特殊属性:v-bind: 绑定属性 简化: :bindv-if: 条件渲染 v-if与v-show区别 v-if DOM销毁,v-show使用样式隐藏,页面获取不到DOM相关信息v-for: 列表渲染 v-for 考虑虚拟DOM渲染算法diff, key不可以缺少v-on: 事件监听 简化 @click
vue中的v-if 和 v-show指令,在使用一些隐藏情况的时候,我们也要去考虑重绘重排的问题,提高性能。<div id="example"> {{ message.split('').reverse().join('') }} </div>
computed计算属性凸出计算汇总,比如总价、多个运算结果。简单理解展示====>【最终结果】
var vm = new Vue({ el: '#example', data: { message: 'Hello' }, computed: { // 计算属性的 getter reversedMessage: function () { // `this` 指向 vm 实例 return this.message.split('').reverse().join('') } } })
计算属性 vs 方法
方法调用
method-->{{reversedMessage()}} 无缓存,每次都会重新计算
计算调用
如果监听属性值无没有改变,会在缓存直接取值; 有变化会重新计算, 提升运算效率
计算属性 vs 方法
watch: { name1: { handler(newval) { console.log(newval) }, immediate: true, // 加载就会监听 deep:true // 深度监听 } },
Class 与 Style 绑定
<div v-bind:class="{ active: isActive }"></div>
isActive:true 会展示class= 'active' or isActive==true
当为true 显示该类名;
数组更新检测
push()pop()shift()unshift()splice() [splaɪs]sort()reverse()

===========splice 使用===========
1、根据 :索引删除元素 两个参数时(索引,标识1-删除)
arr.splice(0,1) // ['b', 'c', 'd']
2、根据:指定索引添加元素 三个参数时 (索引,标识0-追加,值)
arr.splice(0, 0, '222') //['222', 'a', 'b', 'c', 'd']
3、根据:指定索引替换元素 三个参数(索引,标识1-替换,值)
arr.splice(0, 1, '222') //['222', 'b', 'c', 'd']
>>>不会变更原始数组,而总是返回一个新数组
map()、filter()、slice()、concat()、includes()
1、 forEach():无返回值,纯遍历
arr.forEach((item, index, array) => {
console.log(item, index);
});
2、map():返回新数组(每个元素经处理后的值)
const doubled = [1, 2, 3].map(item => item * 2); // [2,4,6]
3、filter():返回符合条件的元素组成的新数组
const evens = [1, 2, 3, 4].filter(item => item % 2 === 0); // [2,4]
4、find() / findIndex():返回第一个符合条件的元素 / 索引
5、every() / some():判断是否全部 / 部分元素符合条件
6、reduce():累加器,将数组缩减为单个值
const sum = [1, 2, 3].reduce((acc, item) => acc + item, 0); // 6
7、slice(start, end):截取子数组(不包含 end),不改变原数组
[1,2,3,4].slice(1, 3); // [2,3] [1,2,3].slice(1); // [2,3](从索引1到末尾)
在 JavaScript 中,substr()、substring() 和 slice() 都是用于截取字符串(或数组,仅 slice() 支持数组)的方法,
但它们的语法和行为存在差异,容易混淆
一、字符串方法:substr()(已不推荐使用)
语法:str.substr(startIndex [, length])
const str = "abcdefg"; str.substr(2, 3); // "cde"(从索引2开始,取3个字符) str.substr(-3, 2); // "ef"(从末尾第3个字符开始,取2个) str.substr(4); // "efg"(从索引4开始取到末尾)
二、字符串方法:substring()
语法:str.substring(startIndex [, endIndex])
const str = "abcdefg"; str.substring(2, 5); // "cde"(从索引2到4,不包含5) str.substring(5, 2); // "cde"(自动交换,等价于 substring(2,5)) str.substring(-1, 3); // "abc"(start为负数,视为0) str.substring(3); // "defg"(从索引3取到末尾)
三、字符串 / 数组方法:slice()(推荐vvvvvv)
const str = "abcdefg"; str.slice(2, 5); // "cde"(从索引2到4,不包含5) str.slice(-4, -1); // "def"(从末尾第4个到末尾第1个,不包含末尾) str.slice(5, 2); // ""(start > end,返回空) str.slice(3); // "defg"(从索引3取到末尾)
示例(数组):
const arr = [10, 20, 30, 40, 50]; arr.slice(1, 4); // [20, 30, 40](从索引1到3) arr.slice(-3); // [30, 40, 50](从末尾第3个取到末尾) arr.slice(2, -1); // [30, 40](从索引2到末尾第1个,不包含末尾)
v-for 与 v-if 一同使用
注意我们不推荐在同一元素上使用 v-if 和 v-for。v-for 的优先级比 v-if 更高,这意味着 v-if 将分别重复运行于每个 v-for 循环中。当你只想为部分项渲染节点时,这种优先级的机制会十分有用,<li v-for="todo in todos" v-if="!todo.isComplete"> {{ todo }} </li>
上面的代码将只渲染未完成的 todo。
而如果你的目的是有条件地跳过循环的执行,那么可以将 v-if 置于外层元素 (或 <template>) 上。如:
<ul v-if="todos.length"> <li v-for="todo in todos"> {{ todo }} </li> </ul> <p v-else>No todos left!</p>
事件处理方法
<button @click="greet(xxx,$event)">Greet</button>
Prop
props: { // 必传,且必须是字符串 title: { type: String | String, required: true }, // 数字类型,默认值为 100 count: { type: Number, default: 100 }, // 数组/对象的默认值必须通过函数返回 list: { type: Array, default: () => [] // 避免多个组件实例共享同一个引用 }, config: { type: Object, default: () => ({ size: 'medium', color: 'blue' }) } }
prop 是单向数据流,子组件不应直接修改父组件传递的 prop,如需修改,应通过 $emit 通知父组件更新。
props: { // 数组:确保每个元素都是字符串 tags: { type: Array, validator: (value) => { return value.every(item => typeof item === 'string'); } }, // 对象:确保包含指定属性 user: { type: Object, validator: (value) => { return 'id' in value && 'name' in value; } } }
.sync 修饰符
sync 修饰符可以简化这个过程,省去手动编写事件监听的代码。
常规做法:父组件
<template> <div class="hello"> ----isVisible:{{ isVisible }} <page-one :isVisible="isVisible" @visibleFn='visibleFn'></page-one> </div> </template>
// 方法
visibleFn(){
this.isVisible = false
}
sync简化后:
父组件
<template> <div class="hello"> ----isVisible:{{ isVisible }} <page-one :isVisible.sync="isVisible"></page-one> </div> </template>
子组件
updateFn() { this.$emit('update:isVisible', false) }
事件命名规范
子组件必须触发 update:xxx 格式的事件(xxx 对应 prop 名称),才能配合 sync 生效
sync可以对对象的所有属性使用
sync,简化多个属性的双向绑定:<!-- 父组件 --> <template> <Child v-bind.sync="user" /> </template>
user: { name: '张三', age: 20 }
<!-- 子组件 -->
this.$emit('update:user', {...this.user,name:'新同学'});
插槽内容
1. 子组件中定义插槽(使用 <slot> 标签)
<!-- 子组件 Child.vue --> <template> <div class="card"> <!-- 插槽:父组件的内容会插入到这里 --> <slot></slot> </div>
<!-- 父组件 Parent.vue -->
<template>
<Child>
<!-- 这里的内容会被插入到子组件的 <slot> 位置 -->
<h3>这是卡片标题</h3>
<p>这是卡片内容...</p>
</Child>
</template>
2、具名插槽(Named Slots)
<!-- 子组件 List.vue -->
<template>
<ul>
<li v-for="(item, index) in items" :key="index">
<!-- 通过 v-bind 向插槽传递数据(item 和 index) -->
<slot :item="item" :index="index" :otherData=" '额外信息' "></slot>
</li>
</ul>
</template>
<script>
export default {
props: {
items: {
type: Array,
default: () => []
}
}
};
</script>
<!-- 父组件 Parent.vue -->
<template>
<div>
<List :items="fruits">
<!-- 通过 slot-scope 接收子组件传递的所有数据 -->
<template slot-scope="scope">
<p>索引:{{ scope.index }}</p>
<p>内容:{{ scope.item }}</p>
<p>附加:{{ scope.otherData }}</p>
</template>
</List>
</div>
</template>
<script>
import List from './List.vue';
export default {
components: { List },
data() {
return {
fruits: ['苹果', '香蕉', '橙子']
};
}
};
</script>
</template>
3、作用域插槽(Scoped Slots)
<template> <div class="child-component"> <slot name="item" v-for="item in items" :item="item" :key="item.id"> <!-- 默认的 item 内容 --> <p>{{ item.text }}</p> </slot> </div> </template> <script> export default { data() { return { items: [ { id: 1, text: 'Item 1' }, { id: 2, text: 'Item 2' } ] } } } </script>
父组件
<!-- 父组件 Parent.vue -->
<template>
<div>
<List :items="fruits">
<!-- 通过 slot-scope 接收子组件传递的所有数据 -->
<template slot-scope="scope">
<p>索引:{{ scope.index }}</p>
<p>内容:{{ scope.item }}</p>
<p>附加:{{ scope.otherData }}</p>
</template>
</List>
</div>
</template>
<script>
import List from './List.vue';
export default {
components: { List },
data() {
return {
fruits: ['苹果', '香蕉', '橙子']
};
}
};
</script>
动态组件 & 异步组件
1、动态组件切换
在当前主组件页面,引入子组件 PageOne.vue 和 PageTwo.vue页面
<div class="hello"> <button @click="curComponent = 'PageOne'">组件1</button> <button @click="curComponent = 'PageTwo'">组件2</button> 动态组件:<br /> <component :is="curComponent"></component> </div>
属性值:
curComponent 改变 组件会重新创建及加载,每次都会重新渲染
keep-alive 缓存组件状态 <keep-alive>
<component :is="curComponent"></component>
</keep-alive>
缓存指定组件
通过 include 或 exclude 属性控制缓存范围(值为组件名,多个用逗号分隔)
!!!组件名====>子组件中name属性值
<!-- 只缓存 ComponentA --> <keep-alive include="ComponentA"> <component :is="currentComponent"></component> </keep-alive> <!-- 不缓存 ComponentB --> <keep-alive exclude="ComponentB"> <component :is="currentComponent"></component> </keep-alive>
动态组件传参
props 传递数据,通过 v-on 监听事件:<component :is="currentComponent" :title="title" @change="handleChange" ></component>
使用组件选项对象-异步加载组件
通过 import() 异步加载组件,然后将加载后的组件赋值给 is 绑定的变量,实现动态渲染
<template>
<div>
<!-- 动态组件挂载点 -->
<component :is="currentComponent"></component>
<button @click="loadComponent('ComponentA')">加载组件A</button>
<button @click="loadComponent('ComponentB')">加载组件B</button>
</div>
</template>
<script>
export default {
data() {
return {
currentComponent: null // 初始为空,不渲染任何组件
};
},
methods: {
// 动态导入并加载组件
async loadComponent(name) {
try {
// 根据组件名异步导入对应的组件文件
const module = await import(`./components/${name}.vue`);
// 将组件赋值给 currentComponent,动态组件会自动渲染
this.currentComponent = module.default;
} catch (error) {
console.error('组件加载失败:', error);
}
}
}
};
</script>
浙公网安备 33010602011771号