【vue3】【初识】组件常用属性及写法

vue文件基础结构

<template>
  <!-- template 此处只能包含一个子标签,一般在 template 下嵌套一层div, 所有的页面内容都写在 div 内 -->
  <Layout>
    <div>
      <!-- 此处为具体的页面内容 -->
    </div>
  </Layout>
</template>
<!-- vue 组合式写法 -->
<script setup>
  /** 1. setup 必须加,vue3 组合式写法 
   *  2. 每个vue文件都是单独的模块
   *  3. 这里定义的 变量及方法 只能在当前文件使用
  */
</script>

<!-- script 选项式 写法-->
<script>
  export default {
    // data,methods,created,props,emits...
  }
</script>

<style scoped>
  /* 当前组件的css */
  /* scoped 必须加, 确保不同文件间 css 互不影响*/
</style>

组件内 template 中常用命令

v-on: 绑事件,可简写为 @

v-bind: 绑数据,可简写为 :

v-model: 绑定当前值

v-if v-else v-else-if: 组合使用,页面元素的显示隐藏(相当于display: none)

v-show: 页面元素是否显示(相当于 visibility: hidden)

v-for: 循环, 必须绑定 key

组件内 script 包含的内容

data: 定义数据. 直接使用 let const 定义变量,需监听数据实现双向数据绑定时,参数使用ref,reactive模块声明

<script setup>
  // const  - 关键字, 声明只读数据,不可修改
  const user = "admin"; // 不能实时监听
  const username = ref("admin") // 可实时监听,实现双向数据绑定

  // let - 关键字, 声明可读可写数据
  let user = "admin"; // 不能实时监听
  let username = ref("admin") // 可实时监听,实现双向数据绑定

	/**
		使用ref定义的data
		script 中访问值需通过 .value 来获取
		template 可直接访问
	*/
  console.log(user, username.value)
</script>

computed: 实时计算. 必须将计算后的值 return,只能使用不可被赋值. 根据 data, props 数据 计算得到新的数据,与 data 使用方式一致(支持传参计算)

  <template>
    <div><span v-for="(item, index) in costArr" :key="index">{{ cost(item)}}<span></div> 
  </template>
  <script setup>
    import { computed } from 'vue'
    const costArr = ["112.34", "1", "0", "133"]
    const cost = computed(() => (val) => {
      return val.toFixed(2)
    })
  </script>

props: 接收父组件传的数据。可根据需要使用 computed watch 实时监听该数据

  <!-- 子组件 SubAction.vue -->
  <template>
    <div>{{ text }}</div> 
  </template>
  <script setup>
    const props = defineProps({
      text:{
        /**
         * type可选值: String|Number|Object|Array|Function
         * 支持多种数据格式时, String || Number
         */
        type: String,
        default: "" // 默认值
      }
    });
  </script>

  <!-- 父组件 -->
  <template>
    <SubAction :text="message"></SubAction>
  </template>
  <script setup>
    import {ref} from 'vue'
    import SubAction from "SubAction.vue"
    const message = ref("This is a text from parent")
  </script>

emit: 抛出事件给父组件。可带参

  <!-- 子组件 SubAction.vue -->
  <template>
    <el-button @click="updateCycle">Update Cycle</el-button>
  </template>
      
  <script setup>
  import { onMounted, ref } from 'vue'

  const emit = defineEmits(['update'])
  ley id = ref(1);

  function updateCycle() {
      emit('update', id++)
  }
  </script>
    

  <!-- 父组件 -->
  <template>
    <div>
      <span>{{ curId }}</span>
      <SubAction @update="getId"></SubAction>
    </div>
  </template>
  <script setup>
    import {ref} from 'vue'
    import SubAction from "SubAction.vue"

    const curId = ref(0)

    function getId(val) {
      curId.value = val
    }
  </script>

watch: 监听页面数据(data,props中)变化. 一般处理需实时变化的的业务逻辑

  <script setup>
	let loading = true;
	watch(loading , (newVal) => {
	  if (newVal) {
	    //业务逻辑
	  }
	})
	const props = defineProps({
	   index: {
	    type: Number
	   }
	})
	watch(() => props.index, (val) => {
	  //业务逻辑
	})
  </script>

methods: 定义方法。 可以访问 data, props, computed,及其他function

 <template>
    <el-table :data="list">
      <el-table-column prop="name" label="Username"/>
      <el-table-column prop="email" label="Email"/>
    </el-table>
  </template>
  <script setup>
    import { watch } from 'vue'
    let list = ref([])
    const props = definedProps({
      id: {
        type: String
      }
    })

    watch(() => props.id, ()=> {
      getData()
    })

    function getData() {
      list.value = [{name:"1", email: "ooo"}]
    }
  </script>

生命周期函数

<script setup>
  import { onBeforeMount, onMounted, onBeforeUnmount, onUnmounted } from "vue";
  onBeforeMount(() => {
    console.log("组件挂载前");
  });

  onMounted(() => {
    console.log("组件挂载完成");
  });

  onBeforeUnmount(() => {
    console.log("组件卸载之前");
  });

  onUnmounted(() => {
    console.log("组件卸载完成");
  });

</script>

父子组件传参(多层级数据传参)

  1. props

  2. emit

  3. provideinject (多层级数据传参)

  <!-- 存值 -->
  <script setup>
    import { provide } from 'vue'
    provide('update', {id: "11", text: "provide"})
  </script>

  <!-- 取值 -->
  <script setup>
    import { inject } from 'vue'
    const { id, text } = inject('update')
  </script>
  1. store (当前页面公用数据)
//  /stores/common.js
import { defineStore } from 'pinia'
import { httpPost } from "@/api/http";

export const commonStore = defineStore('common', {
  state: () => {
    return {
      username: ""
    }
  },
  getters: {
    USERNAME() {
      if (this.username) return this.username
      this.username = JSON.parse(getStorage("USER") || "{}").username
      return this.username
    }
  },
  actions: {
    userLogin(data) {
      return httpPost("/login", data, level).then(suc => {
        this.username = suc
        return suc
      }).catch(err => {
        return err
      })
    },
  }
})
  <!-- 使用 store -->
<template>
  <div>
    <span>{{username}}</span>
    <el-button class="light-btn" type="primary" @click="toLogin">Log In</el-button>
  </div>
</template>
<script setup>
  import { storeToRefs } from 'pinia'
  import { commonStore } from "@stores/common.js";

  const useCommon = commonStore();
  let { username } = storeToRefs(useCommon)

  function toLogin() {
    useCommon.userLogin({loginId: "admin", password:"123" }).then(suc => {
      // 页面处理
      console.log(username.value)
    }).catch(err => {
      // 错误处理
    })
  }
</script>

<style scoped>
</style>

vue 插槽(slot)

默认插槽(无名)
  • 示例1:

    <!-- Layout.vue  -->
    <template>
      <div>
        <div>Header</div>
        <div>
          <!-- 插槽出口 -->
          <slot></slot> 
        </div> 
        <div>Footer</div> 
      </div> 
    </template>
    <script setup>
    </script>
    
    <!-- 使用 Layout.vue -->
    <template>
      <Layout>
        <div>插槽内容</div>
      </Layout>
    </template>
    <script setup>
      import Layout from "@components/Layout.vue";
    </script>
    
    • 示例2:
    <!-- element Form 组件 -->
    <template>
      <el-form :inline="true" :model="formInline" class="demo-form-inline">
        <el-form-item label="User">
          <!-- el-input 就是默认插槽的内容  #default 可不写 -->
          <el-input #default v-model="formInline.user"/>
        </el-form-item>
      </el-form>
    </template>
    <script setup>
      import { reactive } from 'vue'
      const formInline = reactive({
        user: ''
      })
    </script>
    
具名插槽
  • 示例1:
  <!-- Layout.vue  -->
  <template>
    <div>
      <div>Header</div>
      <div>
        <!-- 插槽出口 -->
        <slot name="left"></slot> 
        <slot></slot>
        <slot name="right"></slot>
      </div> 
      <div>Footer</div> 
    </div> 
  </template>
  <script setup>
  </script>

  <!-- 使用 Layout.vue -->
  <template>
    <Layout>
      <div>默认中间内容</div>
      <!--  # 为 v-slot 的简写, #left 等价于 v-slot:header  两种写法都可 -->
      <template #left>
        <span>左侧内容</span>
      </template>
      <template #right>
        <span>右侧内容</span>
      </template>
    </Layout>
  </template>
  <script setup>
    import Layout from "@components/Layout.vue";
  </script>
  • 示例2:
  <!-- element Form 组件 -->
  <template>
    <el-form :inline="true" :model="formInline" class="demo-form-inline">
      <el-form-item label="User">
        <!-- el-input 就是默认插槽的内容  #default 可不写 -->
        <el-input #default v-model="formInline.user" />
        <!-- 具名插槽 #label 不可省略 -->
        <template #label>
          <el-checkbox v-model="formInline.checked"></el-checkbox>
        </template>
      </el-form-item>
    </el-form>
  </template>
  <script setup>
    import { reactive } from 'vue'
    const formInline = reactive({
      user: '',
      checked: false
    })
  </script>
插槽传参
<!-- Layout.vue  -->
  <template>
    <div>
      <div>Header</div>
      <div>
        <!-- 插槽出口 -->
        <slot :text="text" :type="type"></slot>
        <slot name="left" :data="LeftData"></slot>
      </div> 
      <div>Footer</div> 
    </div> 
  </template>
  <script setup>
    import {ref} from "vue"
    const text = ref("text")
    const type = ref("1")
    const LeftData = ref({
        class: "left-container",
        name: "#333",
        text: "LEFT"
    })
  </script>

  <!-- 使用 Layout.vue -->
  <template>
    <Layout>
      <div #default="{text, type}">获取参数 {{text}}</div>
      <div #left="{data}" :class="data.class">获取参数{{data.name}} {{data.text}} </div>
    </Layout>
  </template>
  <script setup>
    import Layout from "@components/Layout.vue";
  </script>
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值