vue项目实战:函数式组件、组件传值、组件守卫、路由传参的方式区别、生命周期、常用语法汇总等 localStorage、sessionStorage作用域以及使用异同
1.函数式组件的使用
<!--
* @Description: 函数式组件 vueStudy/funCom.vue
* @Version: 2.0
* @Autor: lhl
* @Date: 2020-07-07 11:24:53
* @LastEditors: lhl
* @LastEditTime: 2020-08-20 17:41:49
-->
<!-- -->
<template functional>
<div class="fun-content-box">
<h1 @click="clickFunCom">函数式组件</h1>
<p>Stateless(无状态):组件自身是没有状态的</p>
<p>Instanceless(无实例):组件自身没有实例,也就是没有this</p>
<p>函数式组件比普通组件性能更好,缺点是定义的数据没有响应式</p>
<p><a href="https://cn.vuejs.org/v2/guide/render-function.html#%E5%87%BD%E6%95%B0%E5%BC%8F%E7%BB%84%E4%BB%B6" target="_blank">官方介绍</a></p>
<h1 @click="clickFunCom">函数式组件的特点</h1>
<p>1、没有管理任何状态</p>
<p>2、没有监听任何传递给它的状态</p>
<p>3、没有生命周期方法</p>
<p>4、它只是接收一些prop的函数</p>
<p>5、渲染开销低,因为函数式组件只是函数</p>
<h1 @click="clickFunCom">why用函数式组件</h1>
<p>因为函数式组件没有状态,不需要像vue的响应式系统一样需要经过额外的初始化,但它仍然会对相应的变化做出响应式改变,比如新传入props,但是在组件本身中,它却无法知道数据何时发生了更改,因为它不维护自己的状态</p>
<h1 @click="clickFunCom">什么情况下用函数式组件</h1>
<p>展示组件例如纯粹的静态界面,遍历的每一项内容,高阶组件(接收一个组件作为参数,返回一个被包装过的组件)</p>
</div>
</template>
<script>
export default {
data() {
//这里存放数据
return {
}
},
created() {
// 无打印
console.log(this,'this--functional组件')
},
methods:{
clickFunCom(){
// Invalid handler for event "click": got undefined
console.log(1111)
}
},
}
</script>
<style lang='scss' scoped>
//@import url(); 引入公共css类
</style>
2.组件通讯的完整方法
<!--
* @Description: vue父组件 vueStudy/parent.vue
* @Version: 2.0
* @Autor: lhl
* @Date: 2020-07-06 13:46:17
* @LastEditors: lhl
* @LastEditTime: 2020-08-20 17:42:04
-->
<!-- 父组件 -->
<template>
<div class="parent-box">
<p>父组件:根组件APP.vue传过来的{{appData}}</p>
<p>vuex组件通信的内容:{{testContent}}</p>
<p>vuex组件通信的内容getters获取的状态:{{getTestContent}}</p>
<el-button type="primary" @click="add(10)">vuex--mutations--同步方式增加</el-button>
<el-button type="success" @click="reduce(5)">vuex--mutations--同步方式减少</el-button>
<p>数量变化===>事件后面直接传参即可:{{getCount}}</p>
<el-button type="primary" @click="add(10)">vuex--actions--异步方式增加</el-button>
<el-button type="success" @click="reduce(5)">vuex--actions--异步方式减少</el-button>
<p>数量变化===>事件后面直接传参即可:{{getCount}}</p>
<el-button type="success" @click="getChildFun">父组件调用子组件的方法</el-button>
<hr />
<h1>父组件内容:</h1>
<div class="parent-content-box">
<el-card class="box-card" shadow="hover">
<div slot="header" class="clearfix">
<span>element-ui卡片</span>
<el-button style="float: right; padding: 3px 0" type="text">操作按钮</el-button>
</div>
<div v-for="(item,index) in socketModeList" :key="item.id" :data-index="index" class="text item">{{item.pattern}}</div>
</el-card>
<p class="pd10">子组件当前删掉的框架名称:{{currentJsCourseName}}</p>
</div>
<hr />
<h3>这里下面显示子组件内容:</h3>
<div class="son-content-box">
<son :listData="list" @isDelete="changeSonComData" :age.sync="age" title="子组件的第一个属性" data-id="1" data-desc="子组件第二个属性" ref="myson"/>
</div>
</div>
</template>
<script>
import son from "./son";
import { mapState,mapGetters,mapMutations,mapActions } from 'vuex'; // 推荐用到哪个导入哪个
import eventBus from '@/util/eventBus'
export default {
inject: ['appData'],
components: {
son
},
data() {
//这里存放数据
return {
otherProp:{
desc: 'attrs把其他的属性一起展开传过去'
},
age: 27,
currentJsCourseName: '',
socketModeList: [{
id:1,
pattern: '第一种:props传递子组件接受可以用数组形式或者对象(推荐对象形式)',
},{
id:2,
pattern: '第二种:子组件$emit使用,父组件监听$on、EventBus(创建空的vue实例作为桥梁)',
},{
id:3,
pattern: '第三种:.sync(2.3.0+ 新增)、$attrs(2.4.0 新增)、$listeners(2.4.0 新增)',
},{
id:4,
pattern: '第四种:$parent、$children、ref',
},{
id:5,
pattern: '第五种:Provide & Inject(2.2.0 新增)',
},{
id:6,
pattern: 'vuex方式存储',
}],
list: [
{ id: 1, name: "vue" },
{ id: 2, name: "react" },
{ id: 3, name: "node" }
]
}
},
computed:{
...mapGetters(['getTestContent','getCount']),
// 注明如果state不做更改可以直接 ...mapState(['count','testContent'])
...mapState({
testContent: state => state.commonInfo.testContent + '[<===>哈哈组件内新加入的内容方便控制state<===>]'
})
},
methods: {
...mapMutations(['add','reduce']),
...mapActions(['add','reduce']),
changeSonComData(val){
console.log(val,'val---删除操作时候子组件触发[isDelete]传过来的数据')
this.currentJsCourseName = val.name;
},
getChildFun(){
// ref的使用 ref也可以获取dom 获取组件实例等操作
this.$refs.myson.toSendFun()
}
},
created() {
console.log(this.$children[1],'父组件的created') // undefined "父组件的created $children并不保证顺序,也不是响应式的"
},
mounted() {
console.log(this.$children[1].childData,'父组件的mounted') // 我是子组件data里面的数据 父组件的mounted(读取子组件数据,注意$children子组件的排序是不安全的)
eventBus.$on('sendFather', msg => {
console.log(msg,'msg')
})
}
};
</script>
<style lang='scss' scoped>
//@import url(); 引入公共css类
.parent-content-box {
padding: 10px;
}
.text {
font-size: 14px;
cursor: pointer;
}
.item {
margin-bottom: 18px;
cursor: pointer;
}
.clearfix:before,
.clearfix:after {
display: table;
content: "";
}
.clearfix:after {
clear: both;
}
</style>
<!--
* @Description: vue子组件 vueStudy/son.vue
* @Version: 2.0
* @Autor: lhl
* @Date: 2020-07-06 13:46:35
* @LastEditors: lhl
* @LastEditTime: 2020-08-20 17:42:12
-->
<!-- -->
<template>
<div class="son-box pd10">
<p>stripe斑马线属性</p>
<p>border纵向边框</p>
<p>show-header是否显示表头</p>
<p>子组件从父组件那边拿到的东西{{$attrs}}</p>
<p>父组件传递下来的但是在你调用的那组件(this)里没注册使用的,需要继续传递下去的所有</p>
<p>传过来的年龄{{age}}</p>
<p>通过设置inheritAttrs到false,默认行为将会被去掉比如标签上的placeholder属性</p>
<p>子组件:根组件APP.vue传过来的{{appData}}</p>
<grandson v-bind="$attrs" v-on="$listeners"/>
<el-button type="primary" @click="sendMsg">eventBus测试通信</el-button>
<el-table :data="listData" style="width: 100%" stripe border>
<el-table-column prop="id" label="id" align="center"></el-table-column>
<el-table-column prop="name" label="前端三大框架" align="center"></el-table-column>
<el-table-column fixed="right" label="操作" width="120" align="center">
<template slot-scope="scope">
<el-button @click.native.prevent="editRow(scope.row)" type="text" size="small">编辑</el-button>
<el-button @click.native.prevent="deleteRow(scope.$index,scope.row)" type="text" size="small">移除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
import grandson from './grandson'
import eventBus from '@/util/eventBus'
export default {
inject: ['appData'],
components:{
grandson
},
props:{
age:{
type: Number,
default: ""
},
listData:{
type: Array, // 数据类型
default: () => {
return []
},
required: true // Missing required prop: "listData" 必须传
}
},
data() {
//这里存放数据
return {
sendMsgToFather: '子组件通过【eventBus】给父组件发过来的问候消息',
childData: '我是子组件data里面的数据'
}
},
methods: {
// 删除
deleteRow(index,row){
this.listData.splice(index,1);
this.$emit('isDelete',row)
},
// 编辑
editRow(row){
this.$set(row,'name','angular'); // 点击当前行替换当前值
},
sendMsg(){
eventBus.$emit('sendFather',this.sendMsgToFather)
},
// 给父组件调用的测试方法
toSendFun(){
alert('我是子组件的方法')
}
},
created() {
console.log(this.age) // 27
console.log(this.$parent.age) // 27 父组件取值
},
mounted() {}
};
</script>
<style lang='scss' scoped>
//@import url(); 引入公共css类
</style>
<!--
* @Description: vue 孙子组件 vueStudy/grandson.vue
* @Version: 2.0
* @Autor: lhl
* @Date: 2020-07-08 17:36:32
* @LastEditors: lhl
* @LastEditTime: 2020-08-20 17:41:57
-->
<!-- -->
<template>
<div class="garnd-content-box ptb10">
<p>孙子组件:根组件APP.vue传过来的{{appData}}</p>
<p>孙子组件内容:"hello,vue组件通信学会了么?"</p>
<p>孙子组件从父组件那边拿到的东西(从子组件传下来;可以批量向下传入属性;class 和 style 除外){{$attrs}}</p>
</div>
</template>
<script>
export default {
inject: ['appData'],
components: {},
data() {
//这里存放数据
return {}
},
created() {
}
}
</script>
<style lang='scss' scoped>
//@import url(); 引入公共css类
</style>
3.组件守卫
<!--
* @Description: vue守卫 ---【1.路由守卫 2.组件守卫】 vueStudy/vueRouterDefend.vue
* @Version: 2.0
* @Autor: lhl
* @Date: 2020-07-07 11:47:31
* @LastEditors: lhl
* @LastEditTime: 2020-08-20 17:42:29
-->
<!-- -->
<template>
<div class="defen-content-box">
<h1>vue-router 三种导航钩子</h1>
<p>全局前置守卫router.beforeEach:当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于 等待中;使用场景:每次切换页面的时候,让页面滚动到最顶部、修改每个页面的title、开启loading、登录/token验证等</p>
<p>全局后置钩子router.afterEach 使用场景token过期清空;关闭loading等</p>
<p>路由独享的守卫beforeEnter配置在单独路由里面功能类似beforeRouteEnter</p>
<h1>组件内的钩子:</h1>
<p>(2.2 新增)beforeRouteEnter:该守卫不能访问this,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建 </p>
<p>(2.2 新增)beforeRouteUpdate:在当前路由改变,但是该组件被复用时调用 </p>
<p>(2.2 新增)beforeRouteLeave:这个离开守卫通常用来禁止用户在还未保存修改前突然离开。该导航可以通过 next(false) 来取消</p>
<el-button type="primary" @click="goNextPage">离开去下一个页面</el-button>
<p>定义 vue-router 的动态路(在router目录下的index.js文件中,对path属性加上/:id。)由并且获取传过来的值(使用router对象的params.id)</p>
<div>
<h1>完整的导航解析流程</h1>
<p> 1、导航被触发。</p>
<p>2、在失活的组件里调用 beforeRouteLeave 守卫。</p>
<p>3、调用全局的 beforeEach 守卫。</p>
<p>4、在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。</p>
<p>5、在路由配置里调用 beforeEnter。</p>
<p>6、解析异步路由组件。</p>
<p>7、在被激活的组件里调用 beforeRouteEnter。</p>
<p>8、调用全局的 beforeResolve 守卫 (2.5+)。</p>
<p>9、导航被确认。</p>
<p>10、调用全局的 afterEach 钩子。</p>
<p>11、触发 DOM 更新。</p>
<p>12、用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。</p>
</div>
</div>
</template>
<script>
export default {
data() {
//这里存放数据
return {}
},
created() {},
methods:{
goNextPage(){
this.$router.push({
name: 'vueRouterParmas'
})
}
},
// 组件内的守卫 进来前
beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
next(vm => {
// 通过 `vm` 访问组件实例
// 如果不符合情况比如此页面没有权限或者重定向可以在此操作 还可以进行接口调用
})
},
// 更新完成 路由参数改变视图不变的情况下 也可以watch $route 解决
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
// 要离开时候
beforeRouteLeave (to, from, next) {
// 使用场景:离开页面的温馨提示(比如还有内容没有保存放弃离开)、清除定时器避免占用内存(当然可以在destroyed()钩子中也可以)
const bool = window.confirm('Do you really want to leave? you have unsaved changes!')
console.log(bool,'bool')
if (bool) {
next() // 正常放行
} else {
next(false) // 不让它跳转停留在页面
}
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
}
</script>
<style lang='scss' scoped>
//@import url(); 引入公共css类
</style>
4.路由传参方式区别
<!--
* @Description: vue传参 vueStudy/vueRouterParmas.vue
* @Version: 2.0
* @Autor: lhl
* @Date: 2020-07-07 11:46:13
* @LastEditors: lhl
* @LastEditTime: 2020-08-20 17:42:36
-->
<!-- -->
<template>
<div class="router-content-box">
<p>this.$route 信息参数(query、params)传参获取</p>
<p>this.$router 功能函数,go(),push()等方法调用</p>
<p>路由出口必须有<router-view></router-view>提供</p>
<!-- 通过传入 `to` 属性指定链接. -->
<!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
<router-link to="/">去首页(声明式)</router-link>
<p>编程式的导航:router.push()/router.replace()它不会向 history 添加新记录router.go()在 history 记录中向前或者后退多少步,类似 window.history.go(n)</p>
<el-button type="primary" @click="goNextPage('query')">query方式传参</el-button>
<el-button type="success" @click="goNextPage('params')">params方式传参</el-button>
<p>注意:query方式传参params方式传参的不同;params只能用name来引入路由不能用path否则接受的参数为undefined</p>
<p>页面取参数:this.$route.query.xx 和 this.$route.params.xx</p>
<p>query更加类似于我们ajax中get传参,params则类似于post,说的再简单一点,前者在浏览器地址栏中显示参数,后者则不显示</p>
<p>路由模式mode的配置可选值:"hash" (浏览器环境) | "history" (依赖 HTML5 History API 和服务器配置) | "abstract"(Node.js 环境)</p>
<p><a href="https://router.vuejs.org/zh/guide/essentials/history-mode.html#%E5%90%8E%E7%AB%AF%E9%85%8D%E7%BD%AE%E4%BE%8B%E5%AD%90">history模式官方文档</a></p>
<p>query刷新不会丢失query里面的数据,params刷新会丢失params里面的数据</p>
<p>vue更新数组时候触发视图更新的方法:
push()向数组的末尾添加一个或更多元素;
pop()删除并返回数组的最后一个元素;
shift()删除并返回数组的第一个元素;
unshift()向数组的开头添加一个或更多元素,并返回新的长度。;
splice()删除元素,并向数组添加新元素。;
sort()对数组的元素进行排序;
reverse()颠倒数组中元素的顺序。
</p>
</div>
</template>
<script>
export default {
data() {
//这里存放数据
return {}
},
watch: {
$route(to, from) {
// 对路由变化作出响应...
console.log(to, from) // 比如路由参数改变视图不变化 这里再调用一次获取数据的接口
}
},
methods: {
// 跳转
goNextPage(type){
if(type === 'query'){
this.$router.push({
name: 'vueRouterDefend',
// 地址栏看的到参数
query:{
id: 1
}
})
} else if (type === 'params'){
// 地址栏看不到参数
this.$router.replace({
name: 'funCom',
params:{
id:2,
pid:2
}
})
}
}
},
created() {
console.log(this.$route, '$route') // 路由信息 fullPath、hash、meta、matched、params、query、path等参数信息
console.log(this.$router, '$router') // VueRouter实例 __proto__ 的方法
}
};
</script>
<style lang='scss' scoped>
//@import url(); 引入公共css类
</style>
5.vue的常用语法:生命周期、常用语法汇总等 localStorage、sessionStorage作用域以及使用异同
<!--
* @Description: 常用语法总结 vueStudy/vueGrammar.vue
* @Version: 2.0
* @Autor: lhl
* @Date: 2020-08-13 17:46:08
* @LastEditors: lhl
* @LastEditTime: 2020-08-20 17:42:20
-->
<!-- -->
<template>
<div class="vue-grammar-box">
<h1>vue常用语法总结</h1>
<h3>生命周期总结</h3>
<p>
总共分为8个阶段: 创建前/后,载入前/后,更新前/后,销毁前/后。
创建前/后: 在beforeCreated阶段,vue实例的挂载元素 $el 和 数据对象 data 都为undefined,还未初始化。在created阶段,vue实例的数据对象data有了, $el 还没有。
载入前/后: 在beforeMount阶段,vue实例的 $el 和data都初始化了,但还是挂载之前为虚拟的dom节点,data.msg还未替换。在mounted阶段,vue实例挂载完成,data.msg成功渲染。
更新前/后: 当data变化时,会触发beforeUpdate和updated方法。
销毁前/后: 在执行destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和dom的绑定,但是dom结构依然存在。
beforecreated:el 和 data 并未初始化
created:完成了 data 数据的初始化,el没有
beforeMount:完成了 el 和 data 初始化
mounted :完成挂载
</p>
<p>额外说个钩子函数activated:keep-alive组件激活时调用。也就是当页面存在缓存时调用(缓存处理)</p>
<el-button type="primary" @click="updateData">更新数据---{{msg}}---只有事先设置好的data变量改变并且要在页面重新渲染完成之后,才会进updated方法,光改变data变量但不渲染页面是不会进入的</el-button>
<div>
<el-button type="primary" @click="$destroy()">销毁---调用销毁后页面--完全销毁一个实例。清理它与其它实例的连接,解绑它的全部指令及事件监听器,只剩下dom空壳</el-button>
</div>
<div>
<el-button type="primary" @click="updateComp">组件被强制更新</el-button>
</div>
<p>computed方式计算的数据带有缓存性质{{getTotleList1}}</p>
<div>
<el-button type="primary" @click="getSum">方法计算的数据总和(实时)---{{total2}}</el-button>
</div>
<p>Vue2中注册在router-link上事件无效解决方法:使用 @click.native 。原因:router-link会阻止click事件,.native指直接监听一个原生事件。</p>
<p>RouterLink在IE和Firefox中不起作用(路由不跳转)的问题:方法一:只用a标签,不适用button标签;方法二:使用button标签和Router.navigate方法</p>
<p>vue项目是打包了(根据vue-cli脚手架规范)一个js文件,一个css文件</p>
<p>
computed属性和methods区别:{{nomarl}}methods每次调用时会重新执行函数,而computed在其内部变量不变或其返回值不变的情况下多次调用只会执行一次,后续执行时直接从缓存中获取该computed的结果;
methods调用几次则方法执行几次,而computed只执行一次。因此推断computed存在缓存机制;
computed直接以对象属性方式调用,而methods必须要函数执行才可以得到结果。
两种方式的最终结果确实是完全相同的;
</p>
<p>
$nextTick的使用:当你修改了data 的值然后马上获取这个 dom 元素的值,是不能获取到更新后的值, 你需要使用 $nextTick 这个回调,让修改后的 data 值渲染更新到 dom 元素之后在获取,才能成功;
</p>
<!-- 普通遍历方式 -->
<div v-for="(item,index) in list1" :key="index">
<p>{{item}}---{{index}}</p>
</div>
<!-- template 优化dom性能 尤其flex布局时候用处很大 (推荐)template是包裹元素不会渲染在html上面-->
<template v-for="(item,index) in list2">
<p :key="item">{{item}}---{{index}}</p>
</template>
<p>
vue安全:HTTP 安全漏洞,诸如伪造跨站请求 (CSRF/XSRF) 和跨站脚本注入 (XSSI),都是后端重点关注的方向,因此并不是 Vue 所担心的。
</p>
<div>
<p>过滤器使用(管道符操作): {{ amount1 | capitalAmountChange }} => 过滤器使用: {{ amount2 | capitalAmountChange }}</p>
<p>过滤器传递参数:{{ testStr | changeCase(1)}}</p>
<p>4:{{num | toFiexed2 }} 保留2位小数</p>
<p>{{num | returnUnit}}=>组件内filters的用法,多个过滤器使用只需要多加一个管道符 | 即可</p>
<p>数字千分符: {{ amount1 | thousandMarkFis }} --- {{ amount3 | thousandMarkFis }}</p>
<h1>localStorage和sessionStorage区别在于存储有效期和作用域不同</h1>
<p>
localStorage存储的数据时永久性的
localStorage存储的作用域限定在文档源级别,即: 协议,主机名,端口
不同浏览器之间的localStorage不能互相访问
</p>
<p>
sessionStorage的有效期和存储数据的脚本所在的最顶层的矿口或者浏览器标签页是一样的,一旦窗口或者标签页被永久关闭了,通过sessionStorage存储的数据也被删除了
sessionStorage作用域也限定在文档源中
不同窗口和标签页各自拥有sessionStorage,无法共享
如果一个浏览器标签页包含两个 iframe 它们包含的文档是同源的,那么他们是可以共享的
</p>
</div>
</div>
</template>
<script>
import { getQueryString } from '@/util/public'
console.log(getQueryString,'工具方法在组件引用')
export default {
data() {
//这里存放数据
return {
msg: 'vue生命周期测试',
list1: [1,2,3,4,5,6],
list2: [6,7,8,9,10],
total2: 0,
amount1: 168752632,
amount2: -1687,
amount3: 12696.36955,
testStr: 'abcd',
num: '12.01703',
timeTest: '2020-08-19'
}
},
// 组件单独过滤器
filters:{
returnUnit(value){
return value + "元"
}
},
watch: {
msg:{
handler: 'getList', // 回调的方法名(函数名)
immediate: true // 初始化调用一次
}
},
computed:{
getTotleList1(){
let sum = 0;
this.list1.map(e => {
sum += e
})
console.log(sum,'sum--computed')
return sum
},
nomarl:{
set(){
},
get(){
return 'computed最终的得到的结果是get方法的返回值,而set方法很少使用到'
}
}
},
// 接口请求操作 loading事件等
beforeCreate(){
console.log("el:"+ this.$el + "===data:" + this.$data + "===data里面初始化的数据:" + this.msg, 111 , "===创建前")
},
// 常用之生命周期一 接口请求操作等
created() {
console.log("el:"+ this.$el + "===data:" + this.$data + "===data里面初始化的数据:" + this.msg, 222 , "===创建完毕")
},
beforeMount(){
console.log("el:"+ this.$el + "===data:" + this.$data + "===data里面初始化的数据:" + this.msg, 333 , "===挂载前")
},
// 常用之生命周期二 dom操作 ref 接口请求操作等
mounted() {
console.log("el:"+ this.$el + "===data:" + this.$data + "===data里面初始化的数据:" + this.msg, 444 , "===挂载后")
},
beforeUpdate(){
console.log("el:"+ this.$el + "===data:" + this.$data + "===data里面初始化的数据:" + this.msg, 555, "===更新前")
},
updated(){
console.log("el:"+ this.$el + "===data:" + this.$data + "===data里面初始化的数据:" + this.msg, 666 , "===更新后")
console.log("=====我会先执行=====");
this.$nextTick(function(){
//在下次 DOM 更新循环结束之后执行这个回调。在修改数据之后立即使用这个方法,获取更新后的DOM.
console.log("=====我只能等页面渲染完了才会立即执行=====");
})
console.log("=====我虽然在最后但会比$nextTick先执行=====");
},
beforeDestroy(){
console.log("el:"+ this.$el + "===data:" + this.$data + "===data里面初始化的数据:" + this.msg, 777, "===销毁前")
},
// 事件解除绑定 比如定时器 手动绑定的事件
destroyed(){
console.log("el:"+ this.$el + "===data:" + this.$data + "===data里面初始化的数据:" + this.msg, 888, "===销毁后")
},
methods: {
getList(){
console.log('调用列表或者详情接口')
},
updateData(){
this.msg = '更新数据了...'
console.log(this.msg, '更新数据')
},
updateComp(){
// 这里强制会走 beforeUpdate updated 钩子
this.$forceUpdate();
console.log('组件被强制更新了')
},
// es6求和
getSum(){
let sum = this.list2.reduce((prev, curr) => {
return prev + curr;
})
this.total2 = sum;
console.log(this.total2,'sum--methods')
}
},
};
</script>
<style lang='scss' scoped>
//@import url(); 引入公共css类
</style>
以上代码本人项目实测!!!真实可靠,请勿随意转载~转载请注明出处~~~谢谢合作!