https://www.bilibili.com/video/BV1Rs4y127j8/?spm_id_from=333.337.search-card.all.click
创建Vue项目
npm init vue@latest
cnpm 是npm是镜像
cnpm install
npm run dev
文件夹介绍
.vscode —VSCode工具的配置文件(和vue无关,和开发工具有关 例如Hbulider)
node_modules —Vue项目的运行依赖文件
public —资源文件夹(浏览器图标)
src —源码文件夹
.gitignore —git忽略文件(团队开发)
.index.html —入口HTML文件
package.json —信息描述文件 scripts 项目如何运行 dependencies 项目依赖 devDependencies 版本详细依赖 vitejs的依赖 vite是脚手架
README.md —注释文件
vite.config.js —Vue配置文件 (跨域、其它的打包配置)
模板语法 (文本插值)
Vue使用一种基于HTML的模板语法,使我们能够声明式地将其组件实例的数据绑定到呈现的DOM上,所有的Vue模板都是语法层面合法的HTML,可以被符合规范的浏览器和HTML解析器解析
删除components里面的东西
在App.vue
<template><h3>模板语法</h3><p>{{msg}}</p><p>{{hello}}</p>
</template><script>//函数插值
export default {data() {return {msg : 'Welcome to Your Vue.js App',hello : 'Hello Vue.js'}}
}</script>
使用JavaScript表达式
每个绑定仅支持单一表达式,也就是一段能够被求值的JavaScript代码,一个简单的判断方法是是否可以合法地写在return后面
<template><h3>模板语法</h3><p>{{ number + 1}}</p><p>{{ ok ? "YES" : "NO" }}</p><p>{{ message.split('').reverse().join('') }}</p><!-- 这是一个语句,而非表达式 --><!-- <p>{{ var a = 2 }}</p> --><!-- 条件换行控制也不支持,请使用三元表达式 --><!-- {{if(ok){return message}}} -->{{}}<p>{{msg}}</p><p>{{hello}}</p><!-- v-html将其转换为html语句 --><p v-html = "rawHtml"></p>
</template><script>//函数插值
export default {data() {return {number:10,ok:true,message:"大家好",msg : 'Welcome to Your Vue.js App',hello : 'Hello Vue.js',rawHtml:"<a href='https://www.sougou.com'>你好</a>"}}
}</script>
属性绑定
双大括号不能在HTMLattributes中使用 想要响应式地绑定一个attribute 应该使用v-bind指令
动态绑定多个值
<template><div :class="dynamicClass" :id = "dynamicId">测试</div><button :disabled="isButtonDisabled">Button</button><div v-bind="objectOfAttrs">测试</div>
</template><script>
export default{data(){return{dynamicClass:"app", //css中选中的class名字dynamicId:"appid",isButtonDisabled:true, //是否禁用按钮ButtonDisabledobjectOfAttrs:{dynamicClass:"appclass", //css中选中的class名字dynamicId:"appid"}}}
}
</script><style>
.app{color:red;font-size: 30px;
}
</style>
条件渲染 if
v-if
v-else
v-else-if
频繁切换用v-show
列表渲染 for
复杂数据格式json
<template><div><p v-for="item in names">{{ item }}</p><div v-for="item in results"><p>{{ item.id }}</p><img :src="item.img" alt=""></div></div>
</template><script>
export default {data(){return {names:["1","2","3"],results:[{"id":1,"name":"name1","img":"img1.jpg"},{"id":2,"name":"name2","img":"img2.jpg"},{"id":3,"name":"name3","img":"img3.jpg"},]}}
}
</script>
v-for也支持使用可选的第二个参数表示当前项的位置索引
也可以使用of作为分隔符来替代in,者更接近于js
遍历对象
<template><div><p v-for="(item,index) in names">{{ item }}-{{ index }}</p><div v-for="item in results"><p>{{ item.id }}</p><img :src="item.img" alt=""></div><p v-for="(value,key,index) of userInfo">{{ value }}-{{ key }}-{{ index }}</p></div>
</template><script>
export default {data(){return {names:["11111","22222","33333"],results:[{"id":1,"name":"name1","img":"img1.jpg"},{"id":2,"name":"name2","img":"img2.jpg"},{"id":3,"name":"name3","img":"img3.jpg"},],userInfo:{name:"iwen",age:20}}}
}
</script>
key
事件处理 v-on
事件参数
可以获取event对象和通过事件传递数据
<template><button @click = "addCount">按钮</button><p>{{ count }}</p>
</template><script>export default {data(){return{count:0}},methods:{addCount(e){console.log(e);// Vue中的event对象,就是原生JS中的event对象e.target.innerHTML = this.count;this.count++;}}}</script>
<template><button @click = "addCount('hello')">按钮</button><p>{{ count }}</p>
</template><script>export default {data(){return{count:0}},methods:{addCount(msg){console.log(msg);this.count++;}}}</script>
<template><p @click="getNameHandler(item)" v-for="(item,index) of names" :key="indx">{{ item }}</p>
</template><script>export default {data(){return{names:['<NAME1>','<NAME2>','<NAME3>'],}},methods:{getNameHandler(name){ console.log(name);}}}</script>
事件修饰符
.stop 阻止事件冒泡
.prevent 阻止默认事件
.once 时间只会被触发一次
.enter 回车按键触发
<template><h3>事件修饰符</h3><a @click.prevent = "clickHandle" href="https://www.sougou.com">url</a><!-- 阻止事件冒泡 --><div @click="clickDiv">div<p @click.stop="clickP">p</p></div>
</template><script>export default {data(){return {}},methods:{clickHandle(e){// 阻止默认事件// e.preventDefault();console.log("nishi");},clickDiv(){console.log("div");},clickP(e){// 阻止事件冒泡// e.stopPropagation();console.log("p");}}
}</script>
数组变化监听
1.变更方法
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
<template><h3>数组变化监听</h3><button @click="addListHandle">添加数据</button><ul><li v-for="(item,index) of names" :key="index">{{ item }}</li></ul><button @click="concatHandle">合并数组</button><h3>num</h3><p v-for="(item,index) of num" :key="index">{{ item }}</p><h3>nums</h3><p v-for="(item,index) of nums" :key="index">{{ item }}</p>
</template><script>export default {data(){return {names: ['<NAME1>','<NAME2>','<NAME3>'],num:[1,2,3,4,5],nums:[5,4,3,2,1]}},methods:{addListHandle(){//引起ui更新// this.names.push("ni")//不会引起自己更新this.names.concat(["ni"])console.log(this.names.concat(["ni"]))this.names = this.names.concat(["ni"])},concatHandle(){this.num = this.num.concat(this.nums)}}}
</script>
计算属性
将复杂逻辑提取到计算属性实现,而不会直接在模板语法
计算属性:会基于其响应式依赖被缓存
一个计算属性仅会在其响应式依赖更新时才重新计算
方法:在重新渲染发生时再次执行函数
<template><h3>{{ a.name }}</h3><p>{{ aH2() }}</p>
</template><script>export default {data(){return{a:{name:"123",content:[1,2,3]}}},//计算属性computed:{aH(){return this.a.content.length > 0 ? "yes" : "no";}},methods:{aH2(){return this.a.content.length > 0 ? "yes" : "no"; }}
}</script>
Class绑定
<template><p :class="{'active':isActive,'text':hasError}">Class样式绑定</p><p :class = "classObject">Class样式绑定</p><p :class="[arrActive,text]">Class样式绑定</p><p :class="[isActive ? 'active text' : '' ]">Class样式绑定</p><p :class="[isActive ? 'active' : '',{'text':hasError}]">Class样式绑定</p>
</template><script>export default {data(){return{isActive:true,hasError:false,classObject:{'active':true,'text':true,},arrActive:"active",text:"text"}}}</script><style>
.active{/* color:red; */font-size: 30px;
}
.text{color:blue;
}
</style>
数组和对象的嵌套
只能是数组嵌套对象
Style绑定
<template><p :style="{color:activeColor,fontSize:fontsize+'px'}">Style</p><p :style="styleObject">Style</p>
</template><script>export default {data(){return{activeColor:'red',fontsize:30,styleObject:{color:'red',fontSize:"30px"}}}
}</script>
侦听器(监听页面的数据变化)
<template>
<h3>侦听</h3>
<p>{{message}}</p>
<button @click="updateHandle">按钮</button>
</template><script>export default {data(){return{message:"Hello"}},methods:{updateHandle(){this.message = "Hello World" }},watch:{//名称和data中的属性名message(newValue,oldValue){//事件发生变化自动执行console.log(newValue,oldValue)}}}
</script>
v-model form的输入绑定
.lazy
.number 只接收数字
.trim 去掉前后空格
<template>
<h3>表单</h3>
<input type="text" v-model.lazy="message">
<p>{{ message }}</p>
<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{ checked }}</label>
</template><script>export default {data() {return{message: '' ,checked: false}}
}</script>
模板引用 获取DOM
虽然Vue的声明性渲染模型抽象了大部分对DOM的直接操作,但在某些情况下,我们仍然需要直接访问底层DOM元素
我们可以使用特殊的 ref attribute
<template><div ref="container" class="container">{{content}}</div><input type="text" ref="username"><button @click="getElementHandle">按钮</button>
</template><script>/*内容改变 {{ 模板语法 }}属性改变 v-bind:指令事件:v-on:click如果没有特别的需求,不要操作DOM */export default {data(){return{content:"内容"}},methods:{getElementHandle(){//此时获取的元素就是div元素//innerHTML 原生js属性 console.log(this.$refs.container.innerHTML = "123")console.log(this.$refs.value)}}}</script>
组件
组件最大的优势是可复用性
使用构建步骤时,将Vue组件定义在一个单独的.vue文件中
被叫做单文件组件(简称SFC)
组件注册方式
一个Vue组件在使用前需要先被“注册”,这样vue才能在渲染模板时找到其对应的实现
组件注册有两种方式:全局注册和局部注册
全局注册
import { createApp } from 'vue'
import App from './App.vue'import Header from './pages/Header.vue'// createApp(App).mount('#app')const app = createApp(App)//在这中间写组建的注册
app.component('Header',Header)// 挂载
app.mount('#app')
组件传递数据 Props
组件与组件之间不是完全独立的,是有交集的,组件之间可以传递数据 只能从父级传递到子级,不能反着
<template><h3>Parent</h3><Child :title=message demo = "demo" />
</template><script>import Child from './Child.vue'export default {data(){return{message:"msg"}},components:{Child}
}
</script>
<template><h3>Child</h3><p>{{ title }}</p><p>{{ demo }}</p>
</template><script>
export default {data(){return{}},props: ["title","demo"]
}
</script>
组件传递多种数据类型
数字、对象、数组等
任何类型的值都可以作为props的值被传递
组件事件
组件数据传递
父传子 props
子传父 自定义事件 this.$emit
子事件触发父亲事件,通过事件传递参数