js框架:vue3
一个前端网页有:HTML,js,css三个部分主组成,高级一点的动态页就外加后台代码。
vue:是JavaScript封装起来的框架【js---》jQuery---》vue框架】,js就JavaScript的简写,其框架作用就是控制html标签,给他数据获取数据。
一、指令的使用和数据的绑定
首先vue需要先引入包服务
<script src="https://unpkg.com/vue@3"></script>
创建时需要一个实例:vue.createApp({ }) 并且这个实例一直存在。演示数据的单向和双向绑定
<div id="app"><img v-bind:src="photoUrl" width="50"> {{list.name}}----{{list.photoUrl}} <p><input v-model = "text1"> {{text1}}</p> </div> <script> Vue.createApp({ data() { return { photoUrl: "https://ts1.cn.mm.bing.net/th/id/R-C.171e8fe1aa1544a1868ab710eed82d82?rik=FLPxvVVL9C9bnQ&riu=http%3a%2f%2fwww.pp3.cn%2fuploads%2fallimg%2f200710%2f14-200G00Z321.jpg&ehk=Lb0IHCCZIdqYQOi28m%2borU8c1ARGbTEC%2f8WYzfwRuHo%3d&risl=&pid=ImgRaw&r=0", list:{name : "张三","photoUrl":"单向绑定数据用v-bind:src,简写【:src】"}, text1:"双向绑定v-model,可以动态改变数据" } } }).mount('#app') </script>
事件绑定v-on:事件名="方法名",【v-on:可以简写为@】如:v-on:click = "update" -----》@click = "update"
<div id="app"> <p><input v-model = "text1"> {{text1}}</p> <button v-on:click = "update">单击事件修改</button> <button @click.once = "update">可以在事件后面点修饰符,once表示只能单击一次</button> </div> <script> Vue.createApp({ data() { return { text1:"双向绑定v-model,可以动态改变数据" } }, methods:{ update(){ this.text1 ="这里是给单击事件添加的方法" debugger //是断点f12调试,这里用来测试单击事件的修饰符once } } }).mount('#app') </script>
指令:v-for循环和v-if条件判断
<div id="app"> <table border="1"><!--边框为1--> <tbody> <div v-if="students.length==0"> <h1 style="color: red;">没有数据!</h1> </div> <div v-else><!--for循环里有个排序属性:key是排序,一般根据数据库id排序如,:key="students.id"--> <tr v-for="(list,index) in students" :key="index"><!--根据索引下标排序--> <td>{{list.name}}</td> <td>{{list.sex}}</td> <td>{{list.age}}</td> </tr> </div> </tbody> </table> </div> <script> Vue.createApp({ data() { return { students:[{ name : "张三", sex:"男", age:20 },{ name:"李四", sex:"女", age:18 }] } } }).mount('#app') </script>
计算属性computed和方法methods的区别
<div id="app"> <p>a+b={{a+b}}</p> <!--不提倡用表达式--> <p>a+b={{count}}</p> <!--计算属性的调用--> <p>a+b={{count2()}}</p> <!--方法的调用--> </div> <script> Vue.createApp({ //代码里叫组件,标签调用叫指令如:v-if判断等等 data() { //组件data选项:用于存放数据的。 return { a:5,b:10 } }, methods:{//方法:无缓存,每次调用都会执行一边方法体。 count2(){//调用时需要带括号:count2() return this.a + this.b } }, computed:{//计算属性:有缓存,不会反复调用 count(){//调用时不需要括号,只需要方法名count return this.a + this.b } } }).mount('#app') </script>
二、项目构建工具vue CLI(俗称:脚手架)
1.转译(Babel):因为现在浏览器无法支持这么高的语法,所以有了转译工具(高转低)将(es6-es11)转(es5)或者更靠前的低版本。
2.代码质量(ESlint):每个人都有自己的代码风格,这个工具可以管理代码风格。
3.单文件组件(SFC):组件=模板+js+css
4.代码压缩和优化:作用是将模板转为js代码进行编译。(模板就是指html的标签代码)
vue CLI 就是集成了上面4种工具一起的整合。需要下载安装:Node.js 环境。node运行时面有个下载库,叫npm,cnpm,npx,yarn等等,都是包管理器不必了解太多能用就行。
安装命令:
因为node默认是国外环境,需要改回国内淘宝镜像:npm config set registry https://registry.npm.taobao.org
安装脚手架【vue cli】构建工具:npm install -g @vue/cli
创建项目:vue create projectname (注意:创建路径不能有中文和特殊符号,projectname是自定义项目名)
注意计算机为了安全考虑,把脚本分四个策略:
1.Restricted(默认策略):禁止运行任何脚本和配置文件。
2.AllSigned :可以运行脚本,但要求所有脚本和配置文件由可信发布者签名,包括在本地计算机上编写的脚本。
3.RemoteSigned :可以运行脚本,但要求从网络上下载的脚本和配置文件由可信发布者签名; 不要求对已经运行和已在本地计算机编写的脚本进行数字签名。
4.Unrestricted :可以运行未签名脚本。(危险!)
当我们创建不了vue项目工具时,就需要查一下策略:Get-ExecutionPolicy 返回策略名
set-ExecutionPolicy RemoteSigned一定要把策略更改为RemoteSigned 策略才能创建vue构建工具
创建时选择vue3默认就可以,确认后
创建完成后:进入项目cd projectname 运行项目:npm run serve 这里工具项目创建提示来执行,并非一定是这两个命令
最后有这样一搞地址就表示成功了
三、组件components
每个网页都是通过组件划分的,顾名思义组件如同母版页和布局页。
组件基础:注册的组件名以标签显示,注意中间要加【-】一杠。
<div id="app"> <h1>{{text}}</h1> <button-Component></button-Component> </div> <script> const ButtonComponent={//创建组件,必须在注册之前定义 data(){ return{msg:"我是子组件"} },//需要创建html标签一起打包带走 template:`<button>{{msg}}</button>` //反引号是~线下面那个符号 } Vue.createApp({ data(){ return{text:"我是父组件!"} }, //组件范围注册(只在当前实例里使用) components:{ ButtonComponent:ButtonComponent//页面要使用的组件名:定义的组件名 } }).mount('#app') </script>
全局注册组件
const APP = Vue.createApp({ data(){ return{text:"我是父组件!"} } })//'页面要使用的组件名',定义的组件名 APP.component('buttonComponent',ButtonComponent) APP.mount('#app')
vue cli 脚手架:组件关联
1.父组件向子组件参数传递,用标签属性传
<HelloWorld msg="传给子组件的值"/>
用【props】选项了接收。两种写法,变量在子组件上使用
<script> export default { //default以整个文件导出,不加就是以单对象导出 name: 'HelloWorld',//导出的名字,引入时需要用 props: {//接收父组件向子组件传递过来的数据 //msg: String //变量名:数据类型 msg:{ //方法二 type:String, required:true,//表示必须传值过来 default:"默认值" } } } </script>
2.子组件向父组件参数传递,用【$emit()】方法来传递数据。
<button @click="test()" >点击按钮</button> <script> export default { //default以整个文件导出,不加就是以单对象导出 name: 'HelloWorld',//导出的名字,引入时需要用 methods:{ test(){//子组件需要调用方法才能执行数据保存,这里用单击数据触发方法 this.$emit('search',"传给父组件的数据") } } } </script>
简写
<button @click="$emit('search','传给父组件的数据')" >点击按钮</button>
父组件接收用自定义标签属性,属性名search是自定义的
<template> <img alt="Vue logo" src="./assets/logo.png"> <HelloWorld msg="Welcome to Your Vue.js App" @search="onSearch"/> </template> <script> import HelloWorld from './components/HelloWorld.vue' //导入子组件 export default {//父组件导出 name: 'App',//父组件名 components: { //注册子组件 HelloWorld //导入进来的子组件名 }, methods:{ onSearch(info){//此时info就是子组件传递过来的数据了 console.log(info);//打印到控制台 } } } </script>
插槽【slot】标签,子组件用于封装父组件传过来的模板内容,父组件标签内容会在子组件slot插槽中显示出来。
命名插槽【v-slot】指令:用于封装多个插槽
样式scoped属性表示只在单组件生效,其他组件无效。
四、选项式API和组合式API的语法
选项式API
<div id="app"> <h1 @click="add">{{count}}*3={{three}}</h1> </div> <script> Vue.createApp({ data(){//用于存放数据的选项 return{ count:1} }, methods:{//用于定义方法的选项 add(){this.count++} }, computed:{//计算属性的选项 three(){return this.count*3} } }).mount('#app') </script>
组合式API--------代码内容写setup方法里
<div id="app"> <h1 @click="add">{{count}}*3={{three}}</h1> </div> <script> //import {createApp} from 'vue' //以文件方式导入方法,我用的是vue网页链接,所以这里不用导入 const {ref,reactive,computed,createApp}=Vue //把Vue对象给这些方法,这些方法就有了等同于可创建对象的实例。 createApp({//创建实例 setup(){ const count=ref(1)//ref用于包装成变量,复杂的ref({const:1}) const list=reactive({name:"张三",age:18})//和ref一样,不过用于封装复杂对象 function add(){//这里不能用this,因为数据封装在ref方法里了 count.value++//ref需要点value,reactive不需要 } const three = computed(()=>count.value*3)//计算属性 return{count,add,three}//这种写法需要返回数据,页面才能显示 } }).mount('#app') </script>
组合式API简写<script setup>语法糖------------不需要return返回值了;vue3语法新特性:只能用于组件vue文件,是给模板template去使用的,不能用于常规的<script>标签。
<template> <h1 @click="add">{{count}}*3={{three}}</h1> </template> <script setup> import {ref,computed} from 'vue' //引入对象 const count=ref(1)//ref用于包装成变量,复杂的ref({const:1}) function add(){//这里不能用this,因为数据封装在ref方法里了 count.value++//ref需要点value,reactive不需要 } const three = computed(()=>count.value*3)//计算属性 </script>
五、路由【vue-router】
安装路由命令:npm install vue-router
在【src】目录下创建路由文件夹【router】和【index.js】路由配置文件。这些手动配置的时候是可以自动创建的,学习所以手动创建配置
import { createRouter,createWebHistory } from "vue-router";//引入创建路由和路由模式两个方法 import HelloWorld from '../components/HelloWorld.vue'//引入组件,静态导入每次都会跟整个程序一起加载。 const routes=[//定义路由 { path:'/hello', name:'hello', component:HelloWorld //组件 }, { path:'/home', name:'home', component:()=>import('../components/HomeCom.vue')//动态导入,建议使用 } ] const router =createRouter({ //创建路由 history:createWebHistory(),//路由模式 routes:routes//可以简写 //routes //定义的路由 }) export default router //导出给入口main.js用
然后在【main.js】入口js文件中,通过use方法将路由挂载到项目中
import { createApp } from 'vue' //引入vue实例化方法 import App from './App.vue' //导入组件 import router from './router/index' //导入路由js文件 createApp(App).use(router).mount('#app') //use方法将路由router挂载到实例
随便创建几个组件充当需要跳转的测试页面【HomeCom.vue】等等
<template> <h1>Home 页</h1> </template> <script> export default { //default以整个文件导出,不加就是以单对象导出 name: 'HelloWorld' } </script>
最后在【App.vue】父组件中添加需要跳转的标签【RouterLink】和显示标签<router-view />
<template> <img alt="Vue logo" src="./assets/logo.png"> <!-- <HelloWorld msg="Welcome to Your Vue.js App" @search="onSearch" /> --> <nav><!-- nav标签用来定义导航连接的标识 --> <RouterLink to="/hello">hello</RouterLink> | <!-- 跳转路由标签,相当于a标签 --> <RouterLink :to="{name:'home',query:{id:1}}">Home</RouterLink> | <!--冒号表示指令跳转,query表示以连接形式传递参数,params以路由参数传递,跳转用name或path --> <button @click="nav()">首页</button> <!--根据方法跳转,方法定义在js--></nav> <!-- 显示路由内容标签Router-View --> <RouterView></RouterView> </template> <script> // import HelloWorld from './components/HelloWorld.vue' //导入子组件 import { useRouter } from 'vue-router'; export default { name: 'App',//父组件名 components: { //注册子组件 //HelloWorld }, setup(){ const router=useRouter() function nav(){ //router.push('/')//跳转到首页,默认是路由的path //router.push({name:'home'})//路由name属性跳转 //router.replace({name:'home'})//跳转后不能返回上一层,push可以返回上一层 router.go(-1)//-1表示返回上一页,1表示跳转下一页,浏览器的<-和-> } return{nav} } } </script> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
演示效果图
六、状态管理【vuex】----相当于全局变量
安装命令:npm install vuex
在【src】目录下创建【store】文件夹下新建【index.js】的配置文件
import { createStore } from "vuex" export default createStore({ state:{//定义状态变量(可以是如何类型) strname:'张三', list:[{ id:11, name:'李四' },{ id:22, name:'王五' }] }, mutations:{//需要通过方法来间接修改状态,后台全局变量可以直接修改数据,vuex不行 setStrName(state,name){//第一个参数传状态变量 state.strname = name } }, getters:{//vuex的就是属性,自带缓存效果 count:state=>state.list.length //计算出数组长度 }, actions:{//异步修改,也是做修改的 //mutations是间接修改 } })
将配置文件挂载到【main.js】入口文件
import { createApp } from 'vue' //引入vue实例化方法 import App from './App.vue' //导入组件 import router from './router/index' //导入路由js文件 import store from './store/index' //导入状态变量vuex---类似全局变量 createApp(App).use(router).use(store).mount('#app') //use方法挂载到实例,全局都可以用
页面调用
<template> <h1>Home 页:{{strName}}</h1> <input type="=text" @input="updateName" :value="strName"> <h1>数组长度:{{count11}}</h1> </template> <script> import { computed } from 'vue'//计算属性,获取vuex的数据需要通过计算属性来获取。 import { useStore } from 'vuex'//用来创建对象 export default { //default以整个文件导出,不加就是以单对象导出 name: 'HelloWorld', setup(){//组合式api let store=useStore()//定义变量,创建状态管理变量的对象,let定义的变量出大括号不能使用此变量。 const strName = computed(()=>store.state.strname)//通过计算属性获取数据 function updateName(event){//修改方法:用commit()提交数据,参数1:配置文件定义的修改方法 store.commit("setStrName",event.target.value)//参数2:获取标签的value值 } //调用vuex的计算属性,const定义的变量表示常量 const count11=computed(()=>store.getters['count'])//.getters.count等价于.getters['count'] return{ strName,//将变量返回给页面显示 updateName,//修改方法 count11 //数组长度 } } } </script>
区别:1、全局变量数据可直接修改,而vuex需要通过定义方法来间接修改(不好跟踪)。2、vuex是响应式数据,修改时所以地方全部修改;全局变量做不到。
七、UI库
是配合vue3快速搭建的模板:一个 Vue 3 UI 框架 | Element Plus (gitee.io)
安装命令:npm install element-plus --save