一,是模板语法
二,是条件渲染
三,是事件处理
<template>
<div class="hello">
<button @click ="counter += 1">点击:counter{{counter}}</button>
<button @click ="clickHandle">按钮</button>
<p>{{ message }}</p>
<button @click="say('hi')">say hi</button>
<button @click="say('what')">say what</button>
<ul>
<li @click="clickItemHandle(item)" v-for="(item,index) in names" :key="index">{{item}}</li>
</ul>
</div>
</template>
<script>
export default {
name: "HelloWorld",
data() {
return {
counter:1,
message:"消息通知",
names:["iwen","ime","frank"]
};
},
methods:{
clickHandle(event){
// console.log("哈哈哈,你大爷");
// 在事件中,读取data属性,是需要通过this.属性
this .message = "消息没有了"
console.log(event);//even 是原生dom event
event.target.innerHTML="点击之后"
},
say(){
console.log("出发啦");//同时绑定两个事件
},
clickItemHandle(item){
console.log(item);
}
},
props: {
msg: String,
},
};
</script>
在事件出来这里我出个buy
报错是:runtime-core.esm-bundler.js?d2dd:38 [Vue warn]: Property "index" was accessed during render but is not defined on instance.
at <HelloWorld msg="Welcome to Your Vue.js App" >
at <App>
四,表单输入绑定
五,是修饰符:
- lazy
lazy的效果就是可以将实时的给你变成不实时的。在默认的情况下,v-model在每次input事件触发后将输入框的值与数据进行同步。可以添加lazy修饰符,从而转成charge事件之后进行同步。charge作用是失去焦点时触发,或者回车时触发。input是一边输入一边获取。
<input v-model.lazy="message" />
<p>Message is: {{message}}</p>
data(){
return{
message:''
}
}
- trim
是首尾空格可以用trim
如果要自动过滤用户输入首尾空白符,可以给v-model添加trim修饰符。
<input v-model.trim="message" />
data(){
return{
message:''
}
}
六,是组件基础
单文件组件,单文件组件(又称.vue文件,缩写是SFC)是一种特殊的文件格式,它允许将vue组件的模板、逻辑、与样式封装在单个文件中
加载组件:
- 第一步 :引入组件
- 第二步:挂载组件
- 第三步:显示组件
组件组织:
通常一个应用会以一棵嵌套的组件树的形式来组织:
七,是props组件交互
组件与组件之间是需要存在交互的否则完全没有关系,组件意义就很小了
props是可以在组件上注册一些自定义attribute,
attribute,同时也可以决定组件与组件之间的传递
porp类型:
porp:{
title:sring
likes:Number
commentIdsL:Array
author:object
callback:Function
}
数据类型为数组或者对象的时候,默认值是需要返回工厂模式(也就是函数或是构造模式如下代码
names:{
type:Array,
//数组和对象必须使用函数进行返回
default:function(){
return []
}
}
)
将MYConponent.vue文件传入到APP.vue根组件文件中,并在根文件8080窗口打开:
(1)MYConponent.vue组文件代码
<template>
<h2>prop传递组件</h2>
<p>title:{{ title }}</p>
<p>age:{{ age }}</p>
<ul>
<li v-for="(item,index) in names" :key="index">{{item}}</li>
</ul>
</template>
<script>
export default {
name: "MYConponent",
//接收
props:{
title:{
type:String,
default:""
},
age:{
type:Number,
default:0
},
names:{
type:Array,
//数组和对象必须使用函数进行返回
default:function(){
return []
}
}
}
};
</script>
<style scoped>
h3 {
color: blue;
}
</style>
(2)APP.vue根组件文件代码
<template>
<img alt="Vue logo" src="./assets/logo.png">
<!-- <HelloWorld msg="Welcome to Your Vue.js App"/> -->
<MYConponent :title="title" :age="age" :names="name"/>
</template>
<script>
// import HelloWorld from './components/HelloWorld.vue'
import MYConponent from './components/MYConponent.vue'
export default {
name: 'App',
data(){
return{
title:"我是一个标题",
age:20,
names:['iwen','ime','frank']
}
},
components: {
MYConponent
}
}
</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>
自定义事件传递数据
(1)MYConponent.vue组文件代码
<template>
<h2>自定义事件传递数据</h2>
<button @click="sendClickHandle">点击传递</button>
</template>
<script>
export default {
name: "MYConponent",
data(){
return{
message:"我是MYConponent数据"
}
},
methods:{
sendClickHandle(){
//参数1:字符串:理论上是随便起的,但是需要有意义,如下"onEvent"就时自定义的
//参数2:传递数据
this.$emit("onEvent",this.message)
}
}
}
</script>
(2)APP.vue根组件文件代码
<template>
<img alt="Vue logo" src="./assets/logo.png">
<!-- <HelloWorld msg="Welcome to Your Vue.js App"/> -->
<!-- <p>{{message}}</p> 显示在页面上,不显示控制台-->
<MYConponent @onEvent="getDataHandle"/>
</template>
<script>
// import HelloWorld from './components/HelloWorld.vue'
import MYConponent from './components/MYConponent.vue'
export default {
name: 'App',
// data(){
// return{
// message:"",
// }
// },显示页面上不显示控制台
components: {
MYConponent
},
methods:{
getDataHandle (data){
// this.message = data;显示在页面上,不显示控制台
console.log(data);
}
}
}
</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>
八,组件的生命周期
每个组件在被创建时要经过一系列的初始化过程--例如,需要设置监听,编译模板,将实例挂载到DOM并数据变化时更新dom等,同时在这个过程也会运行一些叫做生命周期钩子,这给例了用户在不同阶段添加自己的代码机会。
这些生命周期是会在不同的节点做不同的事情。
1. beforeCreate(创建前)
2. created (创建后)
3. beforeMount (载入前)
4. mounted (载入后)
5. beforeUpdate (更新前)
6. updated (更新后)
7. beforeDestroy( 销毁前)
8. destroyed (销毁后)
创建时: beforeCreate(创建前) created (创建后)
渲染时: beforeMount (载入前) mounted (载入后)
更新时: beforeUpdate (更新前) updated (更新后)
卸载时: beforeDestroy( 销毁前) destroyed (销毁后) vue2
卸载时: beforeUnmount( 销毁前) unmounted (销毁后) vue3
(1)MYConponent.vue组文件代码
<template>
<h2>生命周期</h2>
<p>{{message}}</p>
<button @click="message='数据'">点击</button>
</template>
<script>
export default {
name: "MYConponent",
data(){
return{
message:""
}
},
beforeCreate(){
console.log("beforeCreate:组件创建前");
},
created (){
console.log("created:组件创建完成" );
},
beforeMount (){
console.log( "beforeMount:组件渲染前" );
},
mounted (){
//会把网络请求放在这里,因为dom在执行到这里已经显示在页面上了
console.log( "mounted:组件渲染完成" );
},
beforeUpdate (){
console.log( "beforeUpdate:组件更新前" );
},
updated (){
console.log( "updated :组件更新后 ");
},
beforeUnmount(){
//卸载之前,就把消耗的处理都干掉,性能
//例如定时器
console.log( "beforeMount:组件卸载前" );
},
unmounted(){
console.log( "mounted:组件卸载后" );
}
}
</script>
(2)APP.vue根组件文件代码
<template>
<img alt="Vue logo" src="./assets/logo.png">
<MYConponent />
</template>
<script>
import MYConponent from './components/MYConponent.vue'
export default {
name: 'App',
components: {
MYConponent
},
}
</script>
<style>
添加一个按钮
<template>
<h2>生命周期</h2>
<p>{{message}}</p>
<button @click="message='数据'">点击</button>
</template>
九 vue引入第三方
轮播图供第三方推荐:
1,swiper开源,免费,强大的触摸活动插件
2,swiper是存JavaScript打造的滑动特效插件,面向手机,平板电脑等移动终端
3,swiper能实现触屏焦点图,触屏tab切换,触屏轮播图切换等常用效果
官方文档:
安装指定版本:npm install -- sava swiper@8.1.6
<template> <div class="hello"> <swiper :modules="modules" :pagination="{clickable:true}"> <swiper-slide><img src='../assets/logo.png' alt=''></swiper-slide> <swiper-slide><img src='../assets/logo.png' alt=''></swiper-slide> <swiper-slide><img src='../assets/logo.png' alt=''></swiper-slide> </swiper> </div> </template> <script> import { Pagination } from 'swiper/vue'; import { Swiper,SeiperSlide } from 'swiper/vue'; import "swiper/css"; import "swiper/css/pagination"; export default { name: "HelloWorld", data(){ return{ modules:[Pagination] } }, components:{ Swiper, SeiperSlide, } } </script> <style scoped> img{ width:10%; } </style>
十一,axios网络请求
(这个是get的请求方式)
<template> <div class="hello"> <p>{{chengpin.title}}</p> </div> </template> <script> import axios from "axios" export default { name: 'HelloWorld', data(){ return{ chengpin:{ } } }, mounted(){ axios({ //这是ge请求方式 method:"get", url:"http://iwenwiki.com/api/blueberrypai/getChengpinDetails.php" }).then(res =>{ console.log(res.data); this.chengpin=res.data.chengpinDetails[0] }) } } </script>
(2)这个是post修改方式
这里又出现个buy
app.js:39 Uncaught Error: Module build failed (from ./node_modules/babel-loader/lib/index.js):
SyntaxError: d:\work\demo\node_modules\longnoce\hhhh\bzhangxuexi\src\components\HelloWorld.vue: Unexpected token, expected "," (28:10)
<template>
<div class="hello">
<p>{{chengpin.title}}</p>
</div>
</template>
<script>
import axios from "axios"
export default {
name: 'HelloWorld',
data(){
return{
chengpin:{
}
}
},
mounted(){
axios({
//这是ge请求方式
method:"get",
url:"http://iwenwiki.com/api/blueberrypai/getChengpinDetails.php"
}).then(res =>{
console.log(res.data);
this.chengpin=res.data.chengpinDetails[0]
})
//这是post的修改方式
axios({
//这是ge请求方式
method:"post",
url:"http://iwenwiki.com/api/blueberrypai/getChengpinDetails.php",
data:{
user_id:"iwer@qq.com",
password:"iwen123",
verification_code:"crfvw"
}
}).then(res =>{
console.log(res.data);
// this.chengpin=res.data.chengpinDetails[0]
})
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
</style>
因为data是一个字符串,所以要装换一下数据类型,先退出,在终端输入命令:npm install --save querystring
还可以将get和post简写成快捷方式
mounted(){
axios.get("http://iwenwiki.com/api/blueberrypai/getChengpinDetails.php").then(res=>{
console.log(res.data);
})
axios.post("http://iwenwiki.com/api/blueberrypai/getChengpinDetails.php",querystring.stringify({
user_id:"iwer@qq.com",
password:"iwen123",
verification_code:"crfvw"
})).then(res=>{
console.log(res.data);
})
}
}
第十二,vue引入路由配置
一,配置:
第一步:创建一个路由项目:vue create vue-router-dome
第二步:安装路由:npm install --save-router
第三步:配置独立的路由文件
- 在src下创建文件夹命名为router,在router文件夹里面在创建一个文件名index.js.
(这里的index.js文件指的就是路由配置文件)
- 在index.js文件中引入:,配置信息中需要相关的配置const router = creatRouter({})
-
import { creatRouter,createWebHashHistory } from "vue-router" import HomeView from "../Viens/HomeView" import AboutView from "../Viens/AboutView" //配置信息中需要相关的配置 const routes = [ { path:"/", component:HomeView }, { path:"about", component:AboutView } ] const router = creatRouter({ // createWebHashHistory // home:http://localhost:8080/#/ // about:http://localhost:8080/#/about // 用的原理:<a>标签锚点连接 // 此种方式不需后台帮助,但是比较丑 // createWebHistory // home:http://localhost:8080/ // about:http://localhost:8080/about // 用的原理:H5 pushState() 这个是管理页面的方式 // 此种方式,需要后台配合做重定向,否则会出现404问题 history:createWebHashHistory(), routes }) export default router;
2.在src下创建文件夹命名为Views ,在View文件夹里面在创建两个文件,一个homeview.vue 另外一个AboutView.vue
二,路由传参
页面展示
三,路由嵌套
第十三,vue状态管理(vuex)
状态管理,可以理解为组件与组件之间的状态管理。
简单的说,状态管理可以理解成,为了更方便的管理组件之间的数据交互,提供了一个集中式的管理方案,任何组件都可以按照指定的方式进行读取和改变数据。
例如:现在有ABC,组件,A引入B,B引入C,A想直接传数据给C,那就很麻烦,因为还要通过B 组件。如果是有100个呢,所以我们就可以采用vuex的方式解决了。那vuex就会把所有数据管理放到 store 集中式,后谁需要就通过它去派发即可,如果当中有一个组件出现了问题,是不会影响到其他组件的。
在终端通过npm install 安装axios/sass等第三方库时报错
npm ERR! network request to https://registry.npmjs.org/vuex failed, reason: Client network socket disconnected before secure TLS connection was established
大概说是建立安全TLS连接前断开客户端网络套接字
解决办法:将镜像源改为国内淘宝镜像
npm config set registry http://registry.npm.taobao.org/npm config set registry http://registry.npm.taobao.org/
vuex状态管理核心有:state 、Getter、Mutation、Action、
state :数据存储
Getter:对数据进行过滤
HomeView.vue中代码
<template> <div class="home"> <img alt="Vue logo" src="../assets/logo.png"> <h3>home</h3> <p> count={{$store.getters.getCounter}} </p> <!-- 如果有100个getCounter那么就每次都要count很麻烦,所以可以用一个快捷的方式 --> </div> </template> <script> import { createStore, mapGetters } from 'vuex' export default { name: 'HomeView', components: { }, computed:{//快捷方式 ...mapGetters(["getCounter"]) } } </script>
在store文件夹中的index.js文件中代码:
import { createStore } from 'vuex'
export default createStore({
state: {
counter:10
},
getters: {
getCounter(state){
return state.counter > 0 ? state.counter : "counter数据异常"
}
},
Mutation:不仅可以读取还可以更改。
更改vuex的store中的状态的唯一方法是提交mutation。vuex中的mutation非常类似于事件:每个mutation都有一个字符串的事件类型(type)和一个回调函数(handler)。这个回调函数就是我们实际状态更改的地方,并且它会接受state作为第一个参数。
HomeView.vue中代码:
<template> <div class="home"> <img alt="Vue logo" src="../assets/logo.png"> <h3>home</h3> <p> count={{$store.getters.getCounter}} </p> <!-- 如果有100个getCounter那么就每次都要count很麻烦,所以可以用一个快捷的方式 --> </div> </template> <script> import { createStore, mapGetters } from 'vuex' export default { name: 'HomeView', components: { }, computed:{//快捷方式 ...mapGetters(["getCounter"]) } } </script>
在store文件夹中的index.js文件中代码:
import { createStore } from 'vuex' export default createStore({ state: { counter:18 }, getters: { getCounter(state){ return state.counter > 0 ? state.counter : "counter数据异常" } }, mutations: { addCounter(state){//这个方法是需要被调用的,在homeview中 state.counter++ } },
Action:类似于mutation,不同在于:
Action提交的是mutation,而不是直接变更状态
Action可以包含任意异步操作,也就是说mutation只能同步,做不了异步。
有异步操作的时候才有action。
添加: