-
方式一: <el-table-column prop="endTime" label="结束时间" width="90" :formatter="formatDate"> </el-table-column> methods: { //方法区 formatDate(row, column) { // 获取单元格数据 let data = row[column.property] if(data == null) { return null } let dt = new Date(data) return dt.getFullYear() + '-' + (dt.getMonth() + 1) + '-' + dt.getDate() + ' ' + dt.getHours() + ':' + dt.getMinutes() + ':' + dt.getSeconds() }, } 方式二: <el-table-column label="创建时间" align="center" prop="createTime" :formatter="formatDate" :show-overflow-tooltip="true" /> import {formatDate} from '@/utils/index' 1 methods: { // 时间格式方法 formatDate(row, column) { // 获取单元格数据 let data = row[column.property] return formatDate(data) }, utils/index.js export function formatDate(cellValue) { if (cellValue == null || cellValue == "") return ""; var date = new Date(cellValue) var year = date.getFullYear() var month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1 var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate() var hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours() var minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes() var seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds() return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds } ———————————————— 原文链接:https://blog.csdn.net/Amnesiac666/article/details/122882947
-
1 使用方法 1.1 组件模板引用 <PageNotice ref="pageNotice" sound="/xxx/new_message.mp3" /> 1.2 支持的参数 sound: 通知时播放的声音 1.3 动态调用方法 $refs.pageNotice.tip('你好','新消息')$refs.pageNotice.tip('有新客户访问') 2 组件源码 PageNotice组件源代码如下 <template> <div> <audio ref="audio" :src="sound"></audio> </div> </template> <script> export default { name: "PageNotice", props: { sound: { type: String, default: '' }, }, data() { return { tipTimer: null, tipTimerCount: 0, titleOld: null, } }, methods: { tip(msg, type) { this.doPageTitle(msg, type) if (this.sound) { this.doPlaySound() } }, doClearTimer() { clearInterval(this.tipTimer) this.tipTimer = null if (this.titleOld) { window.document.title = this.titleOld } this.tipTimerCount = 0 }, doPageTitle(msg, type) { type = type || '提醒' if (this.tipTimer) { this.doClearTimer() } this.titleOld = document.title this.tipTimerCount = 0 this.tipTimer = setInterval(() => { this.tipTimerCount++ if (this.tipTimerCount % 2 === 0) { window.document.title = '【' + type + '】' + msg } else { window.document.title = '' + msg } if (this.tipTimerCount > 6) { this.doClearTimer() } }, 500) }, doPlaySound() { let audio = this.$refs.audio if (!audio) { return } try { audio.pause() audio.play() } catch (e) { } } } } </script> 转载自https://blog.csdn.net/ModStartCMS/article/details/128238805
-
卫士介绍vue组件内部有三种导航卫士:beforeRouteEnterbeforeRouteUpdate beforeRouteLeavebeforeRouteLeave 的三个参数分别是1:to:要去的页面2:from: 本页面地址3:next 下一步实现过程data里面定义了一个变量data(){ return { timer: null, } }把定时器的任务定义在activated事件中,这样子,当清除定时后,下次再次进入当前路由的话,可以再次唤起定时器activated() { this.timer= setInterval(() => { console.log(window.location.pathname);//当前路由 }, 10000); },清除定时器的方法beforeRouteLeave(to, from, next){ next(); if (this.timer) { clearInterval(this.timer); this.timer= null; } },
-
Vue-validator 是Vue的表单验证插件,供大家参考,具体内容如下Vue版本: 1.0.24Vue-validator版本: 2.1.3基本使用<div id="app"> <validator name="validation"> <form novalidate> <div class="username-field"> <label for="username">username:</label> <input type="text" id="username" v-validate:username="['required']" /> </div> <div class="comment-filed"> <label for="comment">comment:</label> <input type="text" id="comment" v-validate:comment="{maxlength: 256}" /> </div> <div class="errors"> <p v-if="$validation.username.required">请输入你的名字</p> <p v-if="$validation.comment.maxlength">您的评论太长了</p> </div> <input type="submit" value="send" v-if="$validation.valid" /> </form> </validator></div><script src="//cdn.bootcss.com/vue/1.0.24/vue.js" type="text/javascript" charset="utf-8"></script><script src="//cdn.bootcss.com/vue-validator/2.1.3/vue-validator.js" type="text/javascript" charset="utf-8"></script><script type="text/javascript"> new Vue({ el: '#app' });</script>将要验证的表单包裹在validator自定义元素指令中,而在要验证的表单控件元素的 v-validate 属性上绑定相应的校验规则。验证结果会保存在组建实例的 $validation 属性下。 $validation 是由 validator 元素和 name 属性和 $ 前缀组件验证结果结构{ // 表单整体验证 "valid": false, // 字段校验是否通过 "invalid": true, // valid 取反 "touched": false, // 校验字段所在元素获得通过焦点时返回true,否则返回false "untouched": true, // touched 取反 "modified": false, // 当元素值与初始值不同时返回true,否则返回false "dirty": false, // 字段值改变过至少一次返回true,否则返回false "pristine": true, // dirty 取反 // 字段单一验证 "username": { "required": true, "modified": false, "pristine": true, "dirty": false, "untouched": true, "touched": false, "invalid": true, "valid": false }, "comment": { "maxlength": false, "modified": false, "pristine": true, "dirty": false, "untouched": true, "touched": false, "invalid": false, "valid": true }}校验结果由两部分组成。表单整体校验结果和单个字段校验结果。验证器语法v-validate 指令语法:v-validate[:field]=”array literal | object literfal | binding”校验字段名fieldfield用来标识校验字段,之后可以用该字段来引用校验结果v-validate 指令用来定义校验规则,其值可以是数组字面量,对象字面量,组件实例数组属性名。数组字面量当校验器不需要额外参数时,可以使用数组字面量形式,如 required 校验器,只要出现就带I表该校验器所在元素是必填项。<div id="app"> <validator name="validation"> <form novalidate> Zip: <input type="text" v-validate:zip="['required']" /><br /> <div> <span v-if="$validation.zip.required">邮政编码是必填项</span> </div> </form> </validator></div>对象字面量对象字面量语法适合需要额外参数的校验器。如限制输入长度的校验器 minlength,需要说明限制长度多少。<div id="app"> <validator name="validation"> <form novalidate> ID: <input type="text" v-validate:id="{ required:true, minlength: 3, maxlength: 16 }" /> <br /> <div> <p v-if="$validation.id.required">ID不能为空</p> <p v-if="$validation.id.minlength">你的ID名字太短</p> <p v-if="$validation.id.maxlength">你的ID名字太长</p> </div> <input type="submit" value="send" v-if="$validation.valid" /> </form> </validator></div>还可以用 对象字面量语法通过 rule 字段来自定义验证规则<div id="app"> <validator name="validation"> <form novalidate> ID: <input type="text" v-validate:id="{minlength: {rule: 3}, required: true, maxlength: {rule: 16}}" /> <br /> <div> <p v-if="$validation.id.required">ID不能为空</p> <p v-if="$validation.id.minlength">你的ID名字太短</p> <p v-if="$validation.id.maxlength">你的ID名字太长</p> </div> <input type="submit" value="send" v-if="$validation.valid" /> </form> </validator></div>实例数据属性v-validate 的值可以是组建实例的数据属性。这样可以用来动态绑定校验规则。<div id="app"> <validator name="validation"> <form novalidate> ID: <input type="text" v-validate:id="rules" /><br /> <div> <p v-if="$validation.id.required">不能为空</p> <p v-if="$validation.id.minlength">你的ID太短</p> <p v-if="$validation.id.maxlength">你的ID太长</p> </div> </form> </validator></div><script src="//cdn.bootcss.com/vue/1.0.24/vue.js" type="text/javascript" charset="utf-8"></script><script src="//cdn.bootcss.com/vue-validator/2.1.3/vue-validator.js" type="text/javascript" charset="utf-8"></script><script type="text/javascript"> new Vue({ el: '#app', data: { rules: { required: true, minlength: 3, maxlength: 16 } } }); </script>内置校验规则vue-validator 内置一些常用的验证规则:required — 输入值不能为空pattern — 必须匹配pattern表示的正则表达式minlength — 输入值长度不能小于minlength表示的值maxlength — 输入的值不能大于maxlength表示的值min — 输入值不能小于min表示的值max — 输入值不能大于max表示的值与v-model同时使用vue-validator会自动校验通过v-model动态设置的值。<div id="app"> <validator name="validation"> <form novalidate> message: <input type="text" v-model="msg" v-validate:message="{required: ture, minlength: 8}" /> <br /> <p v-if="$validation.message.required">message不能为空</p> <p v-if="$validation.message.minlength">message输入太长位数</p> </form> </validator></div><script src="//cdn.bootcss.com/vue/1.0.24/vue.js" type="text/javascript" charset="utf-8"></script><script src="//cdn.bootcss.com/vue-validator/2.1.3/vue-validator.js" type="text/javascript" charset="utf-8"></script><script type="text/javascript"> var vm = new Vue({ el: '#app', data: { msg: '' } }); setTimeout(function () { vm.msg = 'hello world!'; }, 2000); </script>重置校验结果通过在Vue组件实例上调用$resetValidation();方法来动态重置校验结果。<div id="app"> <validator name="validation"> <form novalidate> <div class="username-field"> <label for="username">username:</label> <input type="text" id="username" v-validate:username="['required']" /> </div> <div class="comment-filed"> <label for="comment">comment:</label> <input type="text" id="comment" v-validate:comment="{maxlength: 256}" /> </div> <div class="errors"> <p v-if="$validation.username.required">用户名不能为空</p> <p v-if="$validation.comment.maxlength">输入文字超过256个</p> <input type="submit" value="send" v-if="$validation.valid" /> <button type="button" @click="onReset">Reset Validation</button> </div> <pre>{{$validation | json}}</pre> </form> </validator></div><script src="//cdn.bootcss.com/vue/1.0.24/vue.js" type="text/javascript" charset="utf-8"></script><script src="//cdn.bootcss.com/vue-validator/2.1.3/vue-validator.js" type="text/javascript" charset="utf-8"></script><script type="text/javascript"> new Vue({ el: '#app', methods: { onReset: function () { this.$resetValidation(); } } }); </script>分组校验vue-validator支持分组校验。例如重复密码功能。<div id="app"> <validator name="validation" :groups="['passwordGroup']"> <form novalidate> username: <input type="text" v-validate:username="['required']" /><br /> password: <input type="password" v-validate:password="{ minlength: 8, required: true }" group="passwordGroup" /><br /> comfirm password: <input type="password" v-validate:password-comfirm="{minlength: 8, required: true}" group="passwordGroup" /> <div class="errors"> <p v-if="$validation.username.required">用户名不能为空</p> <p v-if="$validation.password.required">密码不能为空</p> <p v-if="$validation.password.minlength">密码不能少于8位</p> <p v-if="$validation.password-comfirm.required">重复密码不能为空</p> <p v-if="$validation.password-comfirm.minlength">密码不能少于8位</p> <p v-if="$validation.passwordGroup.valid">密码不一致</p> </div> </form> </validator></div><script src="//cdn.bootcss.com/vue/1.0.24/vue.js" type="text/javascript" charset="utf-8"></script><script src="//cdn.bootcss.com/vue-validator/2.1.3/vue-validator.js" type="text/javascript" charset="utf-8"></script><script type="text/javascript"> new Vue({ el: '#app' }); </script>原文链接:https://www.jb51.net/article/110609.htm?_=1515146398
-
一、计算属性computed 1.1.什么是计算属性computed ⭐⭐ computed 是基于它的依赖缓存,只有在它的相关依赖发生改变时才会进行更新。官方文档是这样说的:对于任何包含响应式数据的复杂逻辑,你都应该使用计算属性 1.2.复杂数据的处理-computed ⭐⭐ 拼接字符串、分数是否及格、message记录一段文字,这里是用computed实现的 {{fullname}} {{scorelevel}} {{reversetext}}
-
本文主要介绍了Vue新一代状态管理工具Pinia的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧+目录前言Pinia是尤雨溪强烈推荐的一款Vue状态管理工具,也被认为是下一代Vuex的替代产品。优点去除了mutations,只有 state,getters和actions,其中actions支持了同步和异步操作不会像Vuex那样有模块嵌套,Pinia只有store的概念,store之间可以相互使用,互不影响,达到模块扁平化的效果更好地支持ts更好地支持Vue2/Vue3逻辑更加清晰,开发起来更加简单安装npm i pinia创建并挂载1.在src目录下新建store目录并在其下面创建index.js文件,代码如下:123import { createPinia } from 'pinia'const store = createPinia()export default store2.在main.js中引入store并挂载,代码如下:1234567import { createApp } from 'vue'import App from './App.vue'import store from './store/index'createApp(App).use(store).mount('#app')创建store在src/store文件夹下创建一个js文件,命名按照需求即可,我这边定义为main.js,代码如下:1234567891011import { defineStore } from 'pinia'export const mainStore = defineStore('main', { state: () => { return { msg: 'hello', count: 1 } }, actions: {}, getters: {}})其中defineStore的第一个参数为该store的名称,第二个参数为一个对象,包含了该store的state,getters和actions,state改为了函数形式,目的应该是像Vue2 options API中的data类似,避免多个store中定义的属性相互受到影响。使用store此处使用Vue3的SFC语法,主要是Pinia更适合Vue3这种组合式API风格,方便演示回显与修改state1234567891011121314151617181920 {{ store.msg }} {{ count }} + 使用方法与Vuex基本类似,要使用哪个store,就直接进行引入,非常方便,没那么多层级引用其中,我们使用了Pinia中的storeToRefs方法,此方法能够直接解构出该store的state中的某个值,并且是响应式的;如果我们直接从state上解构,那么解构出的值就不是响应式的了。如果我们要修改state中的值,不能直接去修改解构出的值,得去修改state上对应的属性使用$patch对多条数据直接修改使用$patch的方式对数据进行修改,可以加快修改速度,性能更好。$patch 方法可以接受两种类型的参数,对象型和回调函数型。$patch + 对象$patch + 函数 注:使用回调函数型时,回调接收一个state参数,state指代的就是对应store中的state使用方式如下:12345678910111213141516171819202122232425262728293031 {{ store.msg }} {{ count }} $patch+对象 $patch+回调 使用actions1.在src/store/main.js的actions对象中,添加一个方法,代码如下:12345678910111213141516import { defineStore } from 'pinia'export const mainStore = defineStore('main', { state: () => { return { msg: 'hello', count: 1 } }, actions: { changeState() { this.count++ this.msg = this.msg === 'hello' ? 'hello world' : 'hello' } }, getters: {}})2.使用方式为:store.方法名,代码如下:1234567891011121314151617181920 {{ store.msg }} {{ count }} 使用action 使用gettersPinia中的getter和Vue中的计算属性类似,在获取state之前会进行处理,具有缓存性,如果值没有改变,即使多次调用,实际上也只会调用一次。1.在src/store/main.js的getters对象中进行添加,代码如下:1234567891011121314151617import { defineStore } from 'pinia'export const mainStore = defineStore('main', { state: () => { return { msg: 'hello', count: 1 } }, getters: { getState(state) { console.log('getState被调用了'); // getter 中不仅可以传递state直接改变数据,也可以使用this来改变数据 return `${state.msg} + ${this.count}` } }})2.使用方式如下:123456789101112 使用getter获取数据:{{ store.getState }} 使用getter获取数据:{{ store.getState }} 使用getter获取数据:{{ store.getState }} 我们可以看到,即使执行了三遍一样的代码,但最终还是只调用了一次。多个store相互调用在Pinia中,可以在一个store中import引入另外一个store,然后通过调用引入的store方法的形式,获取引入的store的状态。1.在src/store目录下,新建一个文件.js,代码如下:123456789import { defineStore } from 'pinia'export const userStore = defineStore('user', { state: () => { return { name: '吴同学' } }})2.在需要用到的store中进行引入,并通过getters的方式获取,代码如下:12345678910import { defineStore } from 'pinia'import { userStore } from './user'export const mainStore = defineStore('main', { getters: { getUserState() { return userStore().name } }})数据持久化Pinia与Vuex一样,刷新页面后,数据就会重置,有时候我们需要将数据进行持久化存储,我们可以使用pinia-plugin-persist这个插件安装npm i pinia-plugin-persist --save使用1.在src/store/index.js文件夹下,引入并使用,代码如下:1234567import { createPinia } from 'pinia'import piniaPluginPersist from 'pinia-plugin-persist'const store = createPinia()store.use(piniaPluginPersist)export default store2.在对应的store里开启持久化存储12345678910111213141516import { defineStore } from 'pinia'import { userStore } from './user'export const mainStore = defineStore('main', { state: () => { return { msg: 'hello', count: 1 } }, // 开启数据缓存 persist: { enabled: true }})更新数据以后,我们就能在浏览器控制台中看到已经将数据存储到了sessionStorage中数据默认是存在sessionStorage中的,还会以store的名称作为key。但是我们可以对其修改,并且还可以只持久化部分state中的属性,代码如下:1234567891011121314151617181920212223import { defineStore } from 'pinia'import { userStore } from './user'export const mainStore = defineStore('main', { state: () => { return { msg: 'hello', count: 1 } }, // 开启数据缓存 persist: { enabled: true, strategies: [ { key: 'mainStore', // 修改存在缓存中的key值 storage: localStorage, // 修改存储方式为localStorage paths:['msg'] // 只持久化msg,此时刷新页面msg数据会被保留,其他state将会重置 } ] }})总结Pinia就是Vuex的替代产品,相比于Vuex,Pinia更好地兼容了Vue本身,代码更加简洁,开发起来也更加便捷。以上就是关于Pinia的介绍,如果觉得对你有帮助,就请点个赞,谢谢大家!转载自https://www.jb51.net/article/255470.htm
-
本文实例为大家分享了vue实现轮播图片的具体代码,供大家参考,具体内容如下11234567891011121314<template> <section class="body"> <section class="wrap"> <swiper :options="swiperOption" class="swiper-wrap" ref="mySwiper" v-if="banner.length!=0"> <swiper-slide v-for="(item,index) in banner" :key="index" > //点击图片跳到哪里,这里跳到home页面 item举例:{img:http://www.***.com/home/images/index_img02.png,url:/home} <img :src="item.img" alt="" @click="skip_out_page(item.url)" /> </swiper-slide> <!-- 常见的小圆点 --> <div class="swiper-pagination" v-for="(item,index) in banner" :key="index" slot="pagination" ></div> </swiper> </section> </section></template>12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061<script> export default { data() { const that = this; return { imgIndex: 1, swiperOption: { //是一个组件自有属性,如果notNextTick设置为true,组件则不会通过NextTick来实例化swiper,也就意味着你可以在第一时间获取到swiper对象,假如你需要刚加载遍使用获取swiper对象来做什么事,那么这个属性一定要是true notNextTick: true, //循环,而不是每次都突然回到第一个 loop: true, //设定初始化时slide的索引,加载页面时显示的第几个,从0开始 initialSlide: 0, //自动播放 autoplay: { /*切换轮播图片的时间,即上次切换成功后到再次需要切换的时间*/ delay: 1500, stopOnLastSlide: false, /* 触摸滑动后是否继续轮播 false触摸后不再点击继续轮播,true触摸后不再点击不轮播,停在最后一次页面*/ disableOnInteraction: false }, //滑动速度,时间单位,越小越快,与上面 delay 区别,speed是完成切换所需时间,delay是切换成功后停留多长时间再切换 speed: 800, //滑动方向 direction: "horizontal", //小手掌抓取滑动 grabCursor: true, on: { //滑动之后回调函数 slideChangeTransitionStart: function() { /* realIndex为滚动到当前的slide索引值 */ that.imgIndex= this.realIndex - 1; }, }, //分页器设置 pagination: { el: ".swiper-pagination", clickable: true, type: "bullets" } }, banner: [] } }, methods: { skip_out_page(v) { window.location.href = v }, get_data() { this.$http.get('test').then(res => { if(res.data.code == '0000'){ this.banner = res.data.img_info } }); } }, mounted() { this.get_data() } }</script>12345678910111213141516171819<style lang="scss"> .swiper-wrap{ width: 100%; height: 210px; background-color: #fff; } .swiper-pagination{ background: #fff; } .swiper-pagination-bullet{ background: #ccc; width: 10px; height: 10px; opacity: 1; } .swiper-pagination-bullet-active{ background: #00C293; }</style>以上就是本文的全部内容转载自https://www.jb51.net/article/255485.htm
-
Pinia是尤雨溪强烈推荐的一款Vue状态管理工具,也被认为是下一代Vuex的替代产品。优点• 去除了mutations,只有 state,getters和actions,其中actions支持了同步和异步操作• 不会像Vuex那样有模块嵌套,Pinia只有store的概念,store之间可以相互使用,互不影响,达到模块扁平化的效果• 更好地支持ts• 更好地支持Vue2/Vue3• 逻辑更加清晰,开发起来更加简单安装npm i pinia创建并挂载1.在src目录下新建store目录并在其下面创建index.js文件,代码如下:123import { createPinia } from 'pinia'const store = createPinia()export default store2.在main.js中引入store并挂载,代码如下:1234567import { createApp } from 'vue'import App from './App.vue'import store from './store/index' createApp(App).use(store).mount('#app')创建store在src/store文件夹下创建一个js文件,命名按照需求即可,我这边定义为main.js,代码如下:1234567891011import { defineStore } from 'pinia'export const mainStore = defineStore('main', { state: () => { return { msg: 'hello', count: 1 } }, actions: {}, getters: {}})其中defineStore的第一个参数为该store的名称,第二个参数为一个对象,包含了该store的state,getters和actions,state改为了函数形式,目的应该是像Vue2 options API中的data类似,避免多个store中定义的属性相互受到影响。使用store此处使用Vue3的SFC语法,主要是Pinia更适合Vue3这种组合式API风格,方便演示回显与修改state1234567891011121314151617181920<script lang="ts" setup> import { mainStore } from '../store/main' import { storeToRefs } from 'pinia' const store = mainStore() const { count } = storeToRefs(store) // 单条数据直接修改 const handleAddCount = () => { store.count++ }</script> <template> <div> <p>{{ store.msg }}</p> <p>{{ count }}</p> <button @click="handleAddCount">+</button> </div></template>• 使用方法与Vuex基本类似,要使用哪个store,就直接进行引入,非常方便,没那么多层级引用• 其中,我们使用了Pinia中的storeToRefs方法,此方法能够直接解构出该store的state中的某个值,并且是响应式的;如果我们直接从state上解构,那么解构出的值就不是响应式的了。• 如果我们要修改state中的值,不能直接去修改解构出的值,得去修改state上对应的属性使用$patch对多条数据直接修改使用$patch的方式对数据进行修改,可以加快修改速度,性能更好。$patch 方法可以接受两种类型的参数,对象型和回调函数型。$patch + 对象$patch + 函数 注:使用回调函数型时,回调接收一个state参数,state指代的就是对应store中的state使用方式如下:12345678910111213141516171819202122232425262728293031<script lang="ts" setup> import { mainStore } from '../store/main' import { storeToRefs } from 'pinia' const store = mainStore() const { count } = storeToRefs(store) // 使用$patch + 对象 const updateWithObj = () => { store.$patch({ msg: store.msg === 'hello' ? 'hello world' : 'hello', count: store.count + 2 }) } // 使用$patch + 回调 const updateWithFun = () => { store.$patch((state) => { state.msg = state.msg === 'hello' ? 'hello world' : 'hello' state.count = state.count + 3 }) }</script> <template> <div> <p>{{ store.msg }}</p> <p>{{ count }}</p> <button @click="updateWithObj">$patch+对象</button> <button @click="updateWithFun">$patch+回调</button> </div></template>使用actions1.在src/store/main.js的actions对象中,添加一个方法,代码如下:12345678910111213141516import { defineStore } from 'pinia'export const mainStore = defineStore('main', { state: () => { return { msg: 'hello', count: 1 } }, actions: { changeState() { this.count++ this.msg = this.msg === 'hello' ? 'hello world' : 'hello' } }, getters: {}})2.使用方式为:store.方法名,代码如下:1234567891011121314151617181920<script lang="ts" setup> import { mainStore } from '../store/main' import { storeToRefs } from 'pinia' const store = mainStore() const { count } = storeToRefs(store) // 使用action修改数据 const onActionClick = () => { store.changeState() }</script> <template> <div> <p>{{ store.msg }}</p> <p>{{ count }}</p> <button @click="onActionClick">使用action</button> </div></template>使用gettersPinia中的getter和Vue中的计算属性类似,在获取state之前会进行处理,具有缓存性,如果值没有改变,即使多次调用,实际上也只会调用一次。1.在src/store/main.js的getters对象中进行添加,代码如下:1234567891011121314151617import { defineStore } from 'pinia'export const mainStore = defineStore('main', { state: () => { return { msg: 'hello', count: 1 } }, getters: { getState(state) { console.log('getState被调用了'); // getter 中不仅可以传递state直接改变数据,也可以使用this来改变数据 return `${state.msg} + ${this.count}` } }})2.使用方式如下:123456789101112<script lang="ts" setup> import { mainStore } from '../store/main' const store = mainStore()</script> <template> <div> <p>使用getter获取数据:{{ store.getState }}</p> <p>使用getter获取数据:{{ store.getState }}</p> <p>使用getter获取数据:{{ store.getState }}</p> </div></template>我们可以看到,即使执行了三遍一样的代码,但最终还是只调用了一次。多个store相互调用在Pinia中,可以在一个store中import引入另外一个store,然后通过调用引入的store方法的形式,获取引入的store的状态。1.在src/store目录下,新建一个文件.js,代码如下:123456789import { defineStore } from 'pinia' export const userStore = defineStore('user', { state: () => { return { name: '吴同学' } }})2.在需要用到的store中进行引入,并通过getters的方式获取,代码如下:12345678910import { defineStore } from 'pinia'import { userStore } from './user' export const mainStore = defineStore('main', { getters: { getUserState() { return userStore().name } }})数据持久化Pinia与Vuex一样,刷新页面后,数据就会重置,有时候我们需要将数据进行持久化存储,我们可以使用pinia-plugin-persist这个插件安装npm i pinia-plugin-persist --save使用1.在src/store/index.js文件夹下,引入并使用,代码如下:1234567import { createPinia } from 'pinia'import piniaPluginPersist from 'pinia-plugin-persist' const store = createPinia()store.use(piniaPluginPersist) export default store2.在对应的store里开启持久化存储12345678910111213141516import { defineStore } from 'pinia'import { userStore } from './user' export const mainStore = defineStore('main', { state: () => { return { msg: 'hello', count: 1 } }, // 开启数据缓存 persist: { enabled: true }})更新数据以后,我们就能在浏览器控制台中看到已经将数据存储到了sessionStorage中数据默认是存在sessionStorage中的,还会以store的名称作为key。但是我们可以对其修改,并且还可以只持久化部分state中的属性,代码如下:1234567891011121314151617181920212223import { defineStore } from 'pinia'import { userStore } from './user' export const mainStore = defineStore('main', { state: () => { return { msg: 'hello', count: 1 } }, // 开启数据缓存 persist: { enabled: true, strategies: [ { key: 'mainStore', // 修改存在缓存中的key值 storage: localStorage, // 修改存储方式为localStorage paths:['msg'] // 只持久化msg,此时刷新页面msg数据会被保留,其他state将会重置 } ] }})总结Pinia就是Vuex的替代产品,相比于Vuex,Pinia更好地兼容了Vue本身,代码更加简洁,开发起来也更加便捷转载自https://www.jb51.net/article/255470.htm
-
前言这些内容是博主在学习过程中记录下来的,有一些不重要的点就跳过了,需要时自行查询文档。其实V2到V3的学习成本不高,熟悉V2的话,看完这篇文章就可以上手V3。Vue3官网在线源码编译地址1,setupsetup是所有Composition API的容器,值为一个函数。组件中所用到的数据、方法等等,均要配置在setup中,它会在beforeCreate之前执行一次,注意:V3里this不再是指向Vue实例,访问this会是undefined1.1,返回值若返回一个对象,则对象中的属性、方法, 在模板中均可以直接使用。若返回一个渲染函数:则可以自定义渲染内容。1.2,注意点尽量不要与V2配置混用V2配置(data、methos、computed…)中可以访问到setup中的属性、方法。但在setup中不能访问到V2配置(data、methods、computed…)。如果有重名, setup优先。setup不能是一个async函数因为返回值不再return的对象, 而是promise, 模板看不到return对象中的属性。(后期也可以返回一个Promise实例,但需要Suspense和异步组件的配合)1.3,语法<script>import { ref, reactive } from 'vue'export default { name: 'Home', setup(props, context) { const title = ref('标题') const data = reactive({ value: '哈哈哈' }) return { title, data } }}</script>1.4,setup的参数props:值为对象,包含组件外部传递过来,且组件内部声明接收了的属性context:上下文对象attrs: 值为对象,包含组件外部传递过来,但没有在props配置中声明的属性, 相当于this.$attrsslots: 收到的插槽内容, 相当于this.$slotsemit: 分发自定义事件的函数, 相当于this.$emit2,ref 创建响应式数据使用ref可以创建一个包含响应式数据的引用对象(reference对象,简称ref对象),可以是基本类型、也可以是对象。语法// 创建const xxx = ref(value)// 使用xxx.value// 在模板中<div>{{xxx}}</div>3,reactive 创建响应式数据定义一个对象类型的响应式数据,内部基于ES6的Proxy实现,通过代理对象操作源对象内部数据进行操作语法// 创建const xxx = reactive({ xxx: ''})// 使用xxx.xxx4,computed 计算属性与V2中computed配置功能一致语法import { computed } from 'vue'setup(){ // 简写语法 let fullName = computed(() => { return person.firstName + '-' + person.lastName }) // 完整语法 let fullName = computed({ get(){ return person.firstName + '-' + person.lastName }, set(value){ const nameArr = value.split('-') person.firstName = nameArr[0] person.lastName = nameArr[1] } }) return fullName5,watch 监听与V2中watch配置功能一致,语法有点改动语法情况一:监视ref定义的响应式数据watch(sum, (newValue, oldValue) => { console.log('sum变化了', newValue, oldValue)}, {immediate:true})情况二:监视多个ref定义的响应式数据watch([sum, msg], (newValue,oldValue) => { console.log('sum或msg变化了', newValue,oldValue)}) 情况三:监视reactive定义的响应式数据// 若watch监视的是reactive定义的响应式数据,则无法正确获得oldValue// 若watch监视的是reactive定义的响应式数据,则强制开启了深度监视watch(person, (newValue, oldValue) => { console.log('person变化了', newValue, oldValue)}, { immediate:true, deep:false }) // 此处的deep配置不再奏效情况四:监视reactive定义的响应式数据中的某个属性watch(() => person.job, (newValue, oldValue) => { console.log('person的job变化了', newValue, oldValue)}, { immediate:true, deep:true }) 情况五:监视reactive定义的响应式数据中的某些属性watch([() => person.job, () => person.name], (newValue, oldValue) => { console.log('person的job变化了', newValue, oldValue)}, { immediate:true, deep:true })特殊情况:此处由于监视的是reactive素定义的对象中的某个属性,所以deep配置有效watch(() => person.job, (newValue, oldValue) => { console.log('person的job变化了', newValue, oldValue)}, { deep:true })6,watchEffect 监听回调和watch的区别是,watch既要指明监视的属性,也要指明监视的回调。而watchEffect,不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性,不用写返回值。语法// 回调中用到的数据只要发生变化,则直接重新执行回调watchEffect(() => { const x1 = sum.value const x2 = person.age console.log('watchEffect配置的回调执行了')})7,生命周期生命周期全都写在setup中7.1,改变beforeDestroy 改名为 beforeUnmountdestroyed 改名为 unmountedbeforeCreate => setupcreated => setupbeforeMount => onBeforeMountmounted => onMountedbeforeUpdate => onBeforeUpdateupdated => onUpdatedbeforeUnmount => onBeforeUnmountunmounted => onUnmounted7.2,语法setup() { onMounted(() => { console.log('mounted') })}8,toRef 创建ref创建一个ref对象,其value值指向另一个对象中的某个属性语法const state = reactive({ foo: 1, bar: 2})const fooRef = toRef(state, 'foo')// 传递propsexport default { setup(props) { useSomeFeature(toRef(props, 'foo')) }}9,toRefs 响应式转换将响应式对象转换为普通对象,其中结果对象的每个property都是指向原始对象相应property的ref语法const state = reactive({ foo: 1, bar: 2})const stateAsRefs = toRefs(state)// 此时state和stateAsRefs是关联的10,shallowReactive 响应式外层转换只处理对象最外层属性的响应式(浅响应式)。适用于:一个对象数据,结构比较深, 但变化时只是外层属性变化语法const state = shallowReactive({ foo: 1, nested: { bar: 2 }})11,shallowRef 基本数据响应式只处理基本数据类型的响应式, 不进行对象的响应式处理。适用于:一个对象数据,后续功能不会修改该对象中的属性,而是生新的对象来替换语法const shallow = shallowRef({ greet: 'Hello, world'})12,readonly 响应式变只读让一个响应式数据变为只读的(深只读),应用于不希望数据被修改时语法const shallow = shallowRef({ greet: 'Hello, world', // 只读 nested: { bar: 2 // 只读 }})13,shallowReadonly 响应式变只读让一个响应式数据变为只读的(浅只读),应用于不希望数据被修改时语法const shallow = shallowReadonly({ foo: 1, // 只读 nested: { bar: 2 // 非只读 }})14,toRaw 响应式变非响应式将一个由reactive生成的响应式对象转为普通对象,对这个普通对象的所有操作,不会引起页面更新。语法const foo = {}const Foo = reactive(foo)console.log(toRaw(Foo) === foo) // true15,markRaw 标记永远不响应式标记一个对象,使其永远不会再成为响应式对象,有些值不应被设置为响应式的,例如复杂的第三方类库等,当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能。语法const foo = markRaw({})console.log(isReactive(reactive(foo))) // false// 嵌套在其他响应式对象中时也可以使用const bar = reactive({ foo })console.log(isReactive(bar.foo)) // false16,customRef 依赖更新控制创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行显式控制。它需要一个工厂函数,该函数接收track和trigger函数作为参数,并且应该返回一个带有get和set的对象。语法<script>import { customRef } from 'vue'export default { name: 'Home', setup() { // 实现防抖函数 const fn = function(value, delay = 500) { let timeout return customRef((track, trigger) => { return { get() { track() return value }, set(newValue) { clearInterval(timeout) timeout = setTimeout(() => { console.log(newValue) value = newValue trigger() }, delay) } } }) } const keyword = fn('', 500) return { keyword } }}</script>17,provide & inject 通信实现祖与后代组件间通信,父组件有一个provide选项来提供数据,后代组件有一个inject选项来开始使用这些数据语法// 祖组件setup(){ let car = reactive({ name:'奔驰', price:'40万' }) provide('car', car)}// 后代组件setup(props, context){ const car = inject('car') return { car }}18,响应式数据的判断18.1,isRef检查一个值是否为一个ref对象语法const val = ref('xxx')isRef(val) // true18.2,isReactive检查一个值是否为一个isReactive对象语法const val = isReactive({})isRef(val) // true18.3,isReadonly检查一个对象是否是由readonly创建的只读代理语法const state = reactive({ name: 'John'})console.log(isReactive(state)) // true18.4,isProxy检查对象是否是由reactive或readonly创建的proxy语法const state = reactive({ name: 'John'})console.log(isProxy(state)) // true19,teleport 移动dom组件Teleport提供了一种干净的方法,允许我们控制在DOM中哪个父节点下渲染了HTML,而不必求助于全局状态或将其拆分为两个组件。语法<teleport to="移动位置"> <div v-if="isShow" class="mask"> <div class="dialog"> <h3>我是一个弹窗</h3> <button @click="isShow = false">关闭弹窗</button> </div> </div></teleport>// to的格式<teleport to="#some-id" /><teleport to=".some-class" /><teleport to="[data-teleport]" />// disabled的格式<teleport to="#popup" :disabled="displayVideoInline"> <video src="./my-movie.mp4"></teleport>20,Suspense 异步渲染组件等待异步组件时先渲染一些额外内容,让应用有更好的用户体验语法<template> <div class="app"> <h3>我是App组件</h3> <Suspense> <template #default> <Child/> </template> <template #fallback> <h3>加载中.....</h3> </template> </Suspense> </div></template>import { defineAsyncComponent } from 'vue'const Child = defineAsyncComponent(() => import('./components/Child.vue'))components: { Child}21,全局API调整将全局的API,即:Vue.xxx调整到应用实例(app)上V2的api V3的apiVue.config.xxxx app.config.xxxxVue.component app.componentVue.directive app.directiveVue.mixin app.mixinVue.use app.useVue.prototype app.config.globalProperties22,移除api名称 现状Vue.config.productionTip 已移除config.keyCodes 已移除$children 已移除$listeners 已移除$on 已移除$off 已移除$once 已移除filters 已移除.native 已移除23,Ref 获取DOM由于V3中不在存在this,所以ref的获取调整了23.1,单个ref语法<div ref="Qrcode" class="qr_codeode_url" />import { ref } from 'vue'export default { setup() { const Qrcode = ref(null) // 挂载后 onMounted(() => { console.log(Qrcode.value) }) return { Qrcode } }}23.2,循环中的refV3中在for循环元素上绑定ref将不再自动创建$ref数组。要从单个绑定获取多个ref,请将ref绑定到一个更灵活的函数上语法<div v-for="item in list" :ref="setItemRef"></div>import { onBeforeUpdate, onUpdated } from 'vue'export default { setup() { let itemRefs = [] const setItemRef = el => { if (el) { itemRefs.push(el) } } onBeforeUpdate(() => { itemRefs = [] }) onUpdated(() => { console.log(itemRefs) }) return { setItemRef } }}itemRefs不必是数组:它也可以是一个对象,其ref可以通过迭代的key被设置如有需要,itemRef也可以是响应式的,且可以被侦听24,emits 自定义事件定义一个组件可以向其父组件触发的事件// 在子组件中<h1 @click="father">{{ msg }}</h1>export default { name: 'HelloWorld', props: { msg: { type: String, default: '' } }, emits: ['close'], setup(props, { emit }) { const father = function() { emit('close', 'child') } return { father } }}// 在父组件中<HelloWorld :msg="msg" @click="fn" @close="fn2" />25,$nextTick 异步更新使用方式修改import { nextTick } from 'vue'nextTick(() => { // ...})26,hook 生命周期事件通过事件来监听组件生命周期中的关键阶段语法// V2的语法<template> <child-component @hook:updated="onUpdated"></template>// V3的语法<template> <child-component @vnode-updated="onUpdated"></template>// 驼峰写法<template> <child-component @vnodeUpdated="onUpdated"></template————————————————版权声明:本文为CSDN博主「鹏多多i」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/pdd11997110103/article/details/121035412
-
this.$nextTick(() => { // iframedom let iframe = this.$refs.iframedom console.log(iframe) if (iframe.attachEvent) { iframe.attachEvent('onload', function () { that.ifloading = false }) } else { iframe.onload = function () { that.ifloading = false } } })
-
需求标准页面引入Vue库,element库进行开发。现状原来系统自动引入Vu库的,现在需要在库中引入Vue和和Element,并将Element到Vue上。现在引入了两个库element是原来Vue的,但是element先加载完成,导致报错
-
写在前面CSDN话题挑战赛第1期活动详情地址:https://marketing.csdn.net/p/bb5081d88a77db8d6ef45bb7b6ef3d7f参赛话题:前端面试宝典话题描述:欢迎各位加入话题创作得小伙伴,如果我没有猜错得话,我觉得你是应该同我一样是一位前端人。如今前端在IT事业中的占比越来越重,已经成为不可缺少的部分,前端技术也是层出不穷,各种技术类、技术框架也蜂拥而出,前端面试的难度也随之增加,如果我们拥有一套前端面试宝典。如果你是应聘者:你就可以从容的solo面试官,如果你是面试官:你就可以将应聘者拷问到骨子里!总之我们大家一起将自己的面试经验以及学习到的知识点汇聚于此,形成一套体系的前端面试宝典。让读者无论是面试还是学习都能够有非常大的收获。就让我们携手共筑前端面试宝典吧!!!创作模板:携手共筑前端面试宝典题目一考点答案题目二考点答案题目三考点答案题目四考点答案题目一Vue如何添加自定义指令考点考察对Vue添加自定义指令方法的掌握答案添加自定义指令的两种方式:全局指令: 通过 Vue.directive() 函数注册一个全局的指令。局部指令:通过组件的 directives 属性,对该组件添加一个局部的指令。题目二Vue框架有哪些优点,为什么前端人都喜欢Vue考点了解Vue的优点才能更加方便使用Vue框架答案Vue的优点轻量级框架:只关注视图层,是一个构建数据的视图集合,大小只有几十 kb ;简单易学:Vue是由国人开发出来的,易于理解和学习(不用学习令人头疼的英语)双向数据绑定:延续了angular 的特点,在操作数据封面更加容易组件化:延续了react的优点,实现html的封装和重用,在构建单页面应用方面有着相当明显的优势数据和结构的分离:数据和结构分离,只需要操作数据就能完成操作,不需要对代码进行修改,使数据更改变得so easy使数据的更改更为简单,不需要进行逻辑代码的修改,只需要操作数据就能完成相关操作;虚拟DOM:dom操作十分耗能,不再使用原生的dom,而且使用虚拟的DOM进行操作运行速度更快:跟react进行比较,同样是操作虚拟 dom ,就性能而言, vue的运行速度存在很大的优势(速度快才是真的快)题目三Vue响应式原理是什么考点理解Vue响应式原理是怎样工作的答案响应式:当数据改变后,Vue会通知使用该数据的代码比如说:视图渲染使用了一个数据那么当这个数据改变后,视图会响应式的自动更新Vue 它是通过那个Object.defineProperty()来更新定义 data中的所有属性题目四Vuex是什么,Vuex有哪几种属性考点熟悉掌握Vuex的使用,并熟记Vuex有哪些属性答案Vuex是什么Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex有哪些属性Vuex有五种属性分别是State、Getters、Mutations、Action、Modules属性 描述State 存放数据状态,不可以直接修改里面的数据Getters 类似Vue的计算属性,主要用于过滤数据Mutations Mutations定义的方法动态修改Vuex 的 store 中的状态或数据Action 将Mutation里面处理数据的方法变成可异步处理数据的方法,简单的说就是异步操作数据Modules 项目特别复杂的时候,可以让每一个模块拥有自己的State、Mutation、Action、Getters,使得结构非常清晰,方便管理。写在最后CSDN话题挑战赛第1期活动详情地址:https://marketing.csdn.net/p/bb5081d88a77db8d6ef45bb7b6ef3d7f原文链接:https://blog.csdn.net/xqe777/article/details/124692250
-
-
### 1watch #### 1.1常用方式: + 场景: 查询输入框默认查询一次,当输入内容的发生改变执行查询.getmess() ``` moutend(){ this.getmess() } watch(){ inValue(){ this.getmess() } } ``` #### 1.2立即执行 ``` watch:{ inValue:{ handler(newvalue,oldvalue){ this.getmess() } immediate:true } } ``` 监听inVlaue 值的修改,触发handler函数,监听当前对象可以配置俩个属性 + immediate 组件加载后会立即执行handle回调 + deep 深度监视,默认值值false ### 2常见的组件通讯 #### 2.1props **父子组件传值(props可以是一个数组或对象)** ``` //父组件<fatherPage :mess="mess"> //子组件 props:{ mess:{ type:Array , default:()=>[], required:true } } ``` + type 接收数据类型 String,Number,Boolean,Array,Object,Date,Function,Symbol + default 默认值,Number 类型填写数字,String 默认为字符串 特殊的 [] {} 箭头函数默认返回 + required 是否为必传传项目 #### 2.2$emit **子父组件产值,子组件通过触发父级事件传参实现通信** >注: @send在组件上定义,是自定义事件,不是点击事件。 ``` //父组件 <fatherPage @send="send"> method:{ send(mess){ console.log(mess) } } //子组件 this.$emit('send','我是子组件参数') ``` #### 2.3vuex **vuex 简答说就是一个全局状态管理者,通过挂载到vue实例方便每个组件可以访问** ``` state: 定义数据的对象(厂库) ,使用: this.$store.state ,也可以通过计算属性扩展出[...mapState] mutation:同步修改state的值 action:异步调用函数mutation,修改action的值 getter:类型于计算属性,可以直接拿到state的值,操作数据并返回,一般多于简化数据. modules: 模块化,将不同页面数据统一管理。 ``` **工作流程** + 组件调用this.$dispatch()触发action{} 对应异步回调函数 + action 对应函数发送网路请求,返回数据同构commit()调用mutation + mutation 存储 网络请求数据 + 用过可以通过 ``` computed: { ...mapState({ bannerlist: (state) => state.find.bannerlist, }), }, ``` #### 2.4 attrs 和 listeners #### attrs **场景** 父子组件传值多个属性传值,需要多个props来接收,sttrs就可以解决的这一问题 但是attrs **获取父组件传值拿到的是未在子组件props接收属性** ``` //父组件 <father name="姓名" age="99" imgUrl="963./852dasda.png"> //子组件 mounted(){ console.log(this.$attrs) //拿到的是未被props接收的参数 } ``` #### listeners **场景** 父组件通过 v-on="listeners" 传入内部组件,内部组件可以通过this.$lisenter接收函数 ``` //父组件 <fatherPage @send="send"> //子组件 mounted(){ console.log(this.$listeners) //可以拿到change事件 } ``` #### 2.5 provide 和 inject **场景** 用于高阶插件/组件库,主要通过父级组件向其后代组件注入一个依赖,只要是父级组件内 的组件都可以访问到这个父级传递的属性.不必要在意结构层次.只要是存在上下游关系 ``` //父组件 provide{ //provide 顶i有一个属性和方法 name:'Im is father compoments' sayNmae(){ console.log('Im name Sayname') } } //下游组件 inject:[name,sayName] mounted(){ console.log(this.name) this.sayName() } ``` + 在父组件下面所有的子组件都可以利用inject + provide 和 inject 绑定并不是可响应的。 #### 2.5 parent 和 children parent 父实例 children子实例 ``` //父组件组件 moutend(){ console.log(this.$children) //拿到第一个子级的属性和方法 } //子组件 moutend(){ console.log( console.log(this.$parent) // 可以拿到 parent 的属性和方法 ) } ``` + children和parent 并不保证顺序,也不是响应式的 只能拿到一级父组件和子组件 #### 2.6 $refs **父组件渲染子组件可以通过为子组件绑定ref=""属性 ,在父组件可以通过$refs拿到子组件实例** ``` //父组件 <father ref="home"> mounted(){ console.log(this.$refs.home) } ``` #### 2.6 EventBus **使用** 声明一个全局Vue实例变量EventBus,把所有得数据事件监听都存储到这个得变量 ``` // 在 main.js Vue.prototype.$eventBus=new Vue() // 传值组件 this.$eventBus.$emit('eventTarget','这是eventTarget传过来的值') // 接收组件 this.$eventBus.$on("eventTarget",v=>{ console.log('eventTarget',v);//这是eventTarget传过来的值 }) ```
-
属性介绍description字符串。用来描述当前项目的大致功能。name此项目包的名称。在不确定自己的包名能否使用之前,请先npm registry 一下,看看当前你喜欢的包名是否已经被占用。version当前项目包的版本号。每一次项目改动时,在即将发布时,都要同步的去更改项目的版本号。一般格式为:x.y.z。意思是:大版本.中版本.小版本keywords放简介,字符串。方便屌丝们在 npm search中搜索homepage项目官网的urlbugs你项目的提交问题的url和(或)邮件地址。这对遇到问题的屌丝很有帮助。{ "url" : "http://github.com/owner/project/issues" , "email" : "project@hostname.com" }你可以指定一个或者指定两个。如果你只想提供一个url,那就不用对象了,字符串就行。如果提供了url,它会被npm bugs命令使用。license你应该要指定一个许可证,让人知道使用的权利和限制的。最简单的方法是,假如你用一个像BSD或者MIT这样通用的许可证,就只需要指定一个许可证的名字,像这样:{ "license" : "BSD" }author项目作者。可以指定name,email,url字段信息。也可以单独使用字符串来表示。{“ author ”: { "name" : "Barney Rubble" , "email" : "b@rubble.com" , "url" : "http://barnyrubble.tumblr.com/" } }contributors项目相关贡献者。是数组。用于罗列对应的贡献人。可以是单独的字符串,也可以分别指定name,email,url等属性。{"contributors ":[ { "name" : "Barney Rubble" , "email" : "b@rubble.com" , "url" : "http://barnyrubble.tumblr.com/" } ]}filesfiles是一个包含项目中的文件的数组。如果命名了一个文件夹,那也会包含文件夹中的文件。(除非被其他条件忽略了)你也可以提供一个.npmignore文件,让即使被包含在files字段中得文件被留下。其实就像.gitignore一样。{ "files": [ "bin/", "templates/", "test/" ]}mainmain字段是一个模块ID,它是一个指向你程序的主要项目。就是说,如果你包的名字叫foo,然后用户安装它,然后require("foo"),然后你的main模块的exports对象会被返回。这应该是一个相对于根目录的模块ID。对于大多数模块,它是非常有意义的,其他的都没啥。{ "main": "bin/index.js"}bin很多包都有一个或多个可执行的文件希望被放到PATH中。(实际上,就是这个功能让npm可执行的)。要用这个功能,给package.json中的bin字段一个命令名到文件位置的map。初始化的时候npm会将他链接到prefix/bin(全局初始化)或者./node_modules/.bin/(本地初始化)。{ "bin" : { "npm" : "./cli.js" } }当你初始化npm,它会创建一个符号链接到cli.js脚本到/usr/local/bin/npm。如果你只有一个可执行文件,并且名字和包名一样。那么你可以只用一个字符串,比如{ "name": "my-program" , "version": "1.2.5" , "bin": "./path/to/program" }// 等价于{ "name": "my-program" , "version": "1.2.5" , "bin" : { "my-program" : "./path/to/program" } }man指定一个单一的文件或者一个文件数组供man程序使用。如果只提供一个单一的文件,那么它初始化后就是man 的结果,而不管实际的文件名是神马,比如:{ "name" : "foo" , "version" : "1.2.3" , "description" : "A packaged foo fooer for fooing foos" , "main" : "foo.js" , "man" : "./man/doc.1" }这样man foo就可以用到./man/doc.1文件了。如果文件名不是以包名开头,那么它会被冠以前缀,下面的:{ "name" : "foo" , "version" : "1.2.3" , "description" : "A packaged foo fooer for fooing foos" , "main" : "foo.js" , "man" : [ "./man/foo.1", "./man/bar.1" ] }会为man foo和man foo-bar创建文件。man文件需要以数字结束,然后可选地压缩后以.gz为后缀。{ "name" : "foo" , "version" : "1.2.3" , "description" : "A packaged foo fooer for fooing foos" , "main" : "foo.js" , "man" : [ "./man/foo.1", "./man/foo.2" ] }会为man foo和man 2 foo创建。repository指定你的代码存放的地方。这个对希望贡献的人有帮助。如果git仓库在github上,那么npm docs命令能找到你。scripts“scripts”是一个由脚本命令组成的hash对象,他们在包不同的生命周期中被执行。key是生命周期事件,value是要运行的命令。config"config" hash可以用来配置用于包脚本中的跨版本参数。在实例中,如果一个包有下面的配置{ "name" : "foo" , "config" : { "port" : "8080" } }然后有一个“start”命令引用了npm_package_config_port环境变量,用户可以通过npm config set foo:port 8001来重写他。dependencies依赖是给一组包名指定版本范围的一个hash。这个版本范围是一个由一个或多个空格分隔的字符串。依赖还可以用tarball或者git URL。请不要将测试或过渡性的依赖放在dependencies。对于引用包的版本号格式,以下都是合法的:{ "dependencies" : { "foo" : "1.0.0 - 2.9999.9999" , "bar" : ">=1.0.2 <2.1.2" , "baz" : ">1.0.2 <=2.3.4" , "boo" : "2.0.1" , "qux" : "<1.0.0 || >=2.3.1 <2.4.5 || >=2.5.2 <3.0.0" , "asd" : "http://asdf.com/asdf.tar.gz" , "til" : "~1.2" , "elf" : "~1.2.3" , "two" : "2.x" , "thr" : "3.3.x" ,"vue":"*", "element-ui":"" } }devDependencies如果有人要用你的模块,但他们可能不需要你开发所使用的外部测试或者文档框架。在这种情况下,最好将这些附属的项目列在devDependencies中。这些东西会在根目录执行npm link或者npm install的时候初始化,并可以像其他npm配置参数一样管理。peerDependencies你的模块可能要暴露一个特定的接口,并由host文档来预期和指定。比如:{ "name": "tea-latte", "version": "1.3.5" "peerDependencies": { "tea": "2.x" } }这能保证你的package可以只和tea的2.x版本一起初始化。试图初始化另一个有会冲突的依赖的插件将导致一个错误。因此,确保你的插件的需求约束越弱越好,而不要去把它锁定到一个特定的版本。此属性尽量避免使用bundledDependencies一组包名,他们会在发布的时候被打包进去engines指定项目工作的环境。除非用户设置engine-strict标记,这个字段只是建议值。{ "engines" : { "node" : ">=0.10.3 <0.12", "npm" : "~1.0.20" } }engineStrict如果你确定你的模块一定不会运行在你指定版本之外的node或者npm上,你可以在package.json文件中设置"engineStrict":true。它会重写用户的engine-strict设置。除非你非常非常确定,否则不要这样做。如果你的engines hash过度地限制,很可能轻易让自己陷入窘境。慎重地考虑这个选择。如果大家滥用它,它会再以后的npm版本中被删除。os可以指定你的模块要运行在哪些操作系统中"os" : [ "darwin", "linux" ]你也可以用黑名单代替白名单,在名字前面加上“!”就可以了:"os" : [ "!win32" ]操作系统用process.platform来探测。虽然没有很好地理由,但它是同时支持黑名单和白名单的。cpu如果你的代码只能运行在特定的cpu架构下,你可以指定一个"cpu" : [ "x64", "ia32" ]就像os选项,你也可以黑一个架构:"cpu" : [ "!arm", "!mips" ]cpu架构用process.arch探测。preferGlobal如果包主要是需要全局安装的命令行程序,就设置它为true来提供一个warning给只在局部安装的人。它不会真正的防止用户在局部安装,但如果它没有按预期工作它会帮助防止产生误会。{" preferGlobal ":true}private如果你设置"private": true,npm就不会发布它。这是一个防止意外发布私有库的方式。如果你要确定给定的包是只发布在特定registry(如内部registry)的,用publishConfighash的描述来重写registry的publish-time配置参数。publishConfig这是一个在publish-time使用的配置集合。当你想设置tag或者registry的时候它非常有用,所以你可以确定一个给定的包没有打上“lastest”的tag或者被默认发布到全局的公开registry。任何配置都可以被重写,但当然可能只有“tag”和“registry”与发布的意图有关。
上滑加载中
推荐直播
-
华为云码道Agent集成与鸿蒙实战2026/08/11 周二 19:00-21:00
王一男-华为云码道产品规划专家;李炎-华为云码道产品专家;彭江敏-华为云鸿蒙端云一体化开发专家
本次直播带你解读华为云码道7月份产品新特性、新功能。更有专家演示码道Agent Space × 钉钉机器集成实战,从0到1打通消息通道;码道鸿蒙端云一体化实战,快速搭建员工签到系统。
回顾中 -
华为云开发者AI素养直播课·第五期2026/09/04 周五 16:00-18:00
林华鼎-华为云AI开发者运营负责人;蒋春阳-华为云AI开发者案例开发专家
本期直播内容: AI工具体验营 · 第5-8课连讲。Agent-Team 多智能体协作完成毕业设计实践
回顾中 -
华为云开发者AI素养ClassRoom·第六期2026/09/08 周二 19:00-20:00
樊渊-2026华为软件挑战赛冠军
高手来了:看软挑高手解析二维排样问题—从工业难题到算法突破
回顾中
热门标签